mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 00:03:02 +01:00
9772a398af
Add FB_DLL_EXPORT to public headers. Use default visibility also for Linux/Unix (in addition to MacOS) as user application can also be compiled with -fvisibility=hidden.
3797 lines
211 KiB
HTML
3797 lines
211 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||
<html>
|
||
<head>
|
||
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
|
||
<title></title>
|
||
<meta name="generator" content="LibreOffice 6.4.7.2 (Linux)"/>
|
||
<meta name="author" content="alex "/>
|
||
<meta name="created" content="2013-05-31T00:00:00.010003100"/>
|
||
<meta name="changed" content="2021-09-10T16:41:58.007600045"/>
|
||
<meta name="created" content="00:00:00">
|
||
<meta name="created" content="00:00:00">
|
||
<meta name="created" content="00:00:00">
|
||
<meta name="created" content="00:00:00">
|
||
<meta name="created" content="00:00:00">
|
||
<meta name="created" content="00:00:00">
|
||
<meta name="created" content="00:00:00">
|
||
<meta name="created" content="00:00:00">
|
||
<style type="text/css">
|
||
@page { margin: 2.01cm }
|
||
h1 { color: #000000 }
|
||
p { margin-bottom: 0.2cm; color: #000000 }
|
||
</style>
|
||
</head>
|
||
<body lang="en-US" text="#000000" dir="ltr"><p style="margin-top: 0.43cm; margin-bottom: 0.51cm; page-break-after: avoid">
|
||
<font face="Albany, sans-serif"><font size="5" style="font-size: 18pt">Firebird
|
||
interfaces.</font></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Firebird's
|
||
OO API is based on use of interfaces. That interfaces, though looking
|
||
in some aspects like OLE2 interfaces (some of them have addRef() and
|
||
release() methods) are non standard and have features, missing in
|
||
other widely used types of interfaces. First of all Firebird
|
||
interfaces are </font><font size="4" style="font-size: 14pt"><b>language
|
||
independent</b></font> – <font size="4" style="font-size: 14pt">that
|
||
means that to define/use them one need not use language specific
|
||
constructions like </font><font size="4" style="font-size: 14pt"><i>class</i></font>
|
||
<font size="4" style="font-size: 14pt">in C++, interface may be
|
||
defined using any language able to call functions using C calling
|
||
conventions and having concepts of array and pointer to
|
||
procedure/function. Next interfaces are </font><font size="4" style="font-size: 14pt"><b>versioned</b></font>
|
||
– <font size="4" style="font-size: 14pt">i.e. we support different
|
||
versions of same interface. Binary layout of interfaces is designed
|
||
to support that features very efficient (there is no need in
|
||
additional virtual calls like in OLE2/COM with it's </font><strong><font size="4" style="font-size: 14pt">QueryInterface)</font></strong><strong>
|
||
</strong><strong><font size="4" style="font-size: 14pt">but it's not
|
||
convenient for direct use from most languages. Therefore
|
||
language-specific wrappers should better be designed for different
|
||
languages making use of API easier. Currently we have wrappers for
|
||
C++ and Pascal, Java is coming soon. From end-user POV calls from C++
|
||
and Pascal have absolutely no difference, though some additional
|
||
language-specific features present in C++ (like ability to turn off
|
||
automatic status check after API calls) are missing in Pascal.</font></strong></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm; font-weight: normal"><font size="4" style="font-size: 14pt">Typically
|
||
database API is used to access data stored in database. Firebird OO
|
||
API certainly performs this task but in addition it supports writing
|
||
your own </font><font size="4" style="font-size: 14pt"><b>plugins</b></font>
|
||
– <font size="4" style="font-size: 14pt">modules, making it
|
||
possible to enhance Firebird capabilities according to your needs.
|
||
Therefore this document contains 2 big parts – accessing databases
|
||
and writing plugins. Certainly some interfaces (like status vector)
|
||
are used in both parts of API, they will be discussed in data access
|
||
part and freely referenced later when discussing plugins. Therefore
|
||
even if you plan to write some plugin you should better start with
|
||
the first part of this document. Moreover a lot of plugins need to
|
||
access databases themselves and data access API is typically needed
|
||
for it.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="result_box"></a><font size="4" style="font-size: 14pt">Firebird
|
||
installation package contains a number of live samples of use of OO
|
||
API – they are in examples/interfaces (database access) and
|
||
examples/dbcrypt (plugin performing fictitious database encryption)
|
||
directories. It's supposed that the reader is familiar with ISC API
|
||
used in Firebird since interbase times.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">This
|
||
document does not pretend to be a full Firebird 3 documentation –
|
||
it just describes new object oriented API, and a reader should be
|
||
familiar with main Firebird concepts, knowledge about ISC API is also
|
||
much welcome. For example – when describing how to work with
|
||
services there is no explanation what is service and why is it
|
||
needed, only description of how to obtain <a href="#Service">IService</a>
|
||
interface and how to use it. Also pay attention that samples of code
|
||
do not use a lot of powerful features of C++. Not used reference
|
||
counted pointers, not used other RAII holders, not used templates
|
||
(except one present in firebird public headers), etc. Primary goal is
|
||
to make this text usable not only to C++ people because our API is
|
||
oriented to support not only C++ but other, more simple languages
|
||
too.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-top: 0.43cm; margin-bottom: 0.51cm; page-break-after: avoid">
|
||
<font face="Albany, sans-serif"><font size="5" style="font-size: 18pt">Accessing
|
||
databases.</font></font></p>
|
||
<h1><font size="4" style="font-size: 14pt">Creating database and
|
||
attaching to existing database.</font></h1>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">First
|
||
of all we need to get access to <b>IMaster</b> interface. IMaster is
|
||
primary Firebird interface, required to access all the rest of
|
||
interfaces. Therefore there is a special way of accessing it – the
|
||
only one needed to use OO API plain function called
|
||
fb_get_master_interface(). This function has no parameters and always
|
||
succeeds. There is one and only one instance of IMaster per Firebird
|
||
client library, therefore one need not care about releasing memory,
|
||
used by master interface. A simplest way to access it from your
|
||
program is to have appropriate global or static variable:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>static
|
||
<a href="#Master">IMaster</a>* master = fb_get_master_interface();</i></font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">For
|
||
a lot of methods, used in Firebird API, first parameter is <b>IStatus</b>
|
||
interface. It's a logical replacement of ISC_STATUS_ARRAY, but works
|
||
separately with errors and warnings (not mixing them in same array),
|
||
can contain unlimited number of errors inside and (this will be
|
||
important if you plan to implement IStatus yourself) always keeps
|
||
strings, referenced by it, inside interface. Typically you need at
|
||
least one instance of IStatus to call other methods. You obtain it
|
||
from IMaster:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i><a href="#Status">IStatus</a>*
|
||
st = master->getStatus();</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">If
|
||
method getStatus() fails for some reason (OOM for example) it returns
|
||
NULL – obviously we can't use generic error reporting method which
|
||
is based on use of IStatus here.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Now
|
||
we are going to deal with first interface, directly related to
|
||
database calls. This is <a href="#Provider">IProvider</a> –
|
||
interface called this way cause it's exactly that interface that must
|
||
be implemented by any provider in Firebird. Firebird client library
|
||
also has it's own implementation of IProvider, which must be used to
|
||
start any database activity. To obtain it we call IMaster's method:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>IProvider*
|
||
prov = master->getDispatcher();</i></font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">When
|
||
attaching to existing database or moreover creating new one it's
|
||
often necessary to pass a lot of additional parameters
|
||
(logon/password, page size for new database, etc.) to API call.
|
||
Having separate language-level parameters is close to unreal – we
|
||
will have to modify a call too often to add new parameters, and
|
||
number of them will be very big no matter of the fact that typically
|
||
one needs to pass not too much of them. Therefore to pass additional
|
||
parameters special in-memory data structure, called </font><font size="4" style="font-size: 14pt"><i>database
|
||
parameters block</i></font> <font size="4" style="font-size: 14pt">(DPB)
|
||
is used. Format of it is well defined, and it's possible to build DPB
|
||
byte after byte. But it's much easier to use special interface
|
||
</font><a href="#XpbBuilder"><font size="4" style="font-size: 14pt"><b>IXpbBuilder</b></font></a><font size="4" style="font-size: 14pt">,
|
||
which simplifies creation of various parameters blocks. To obtain an
|
||
instance of IXpbBuilder you must know one more generic-use interface
|
||
of firebird API – </font><a href="#Util"><font size="4" style="font-size: 14pt"><b>IUtil</b></font></a><font size="4" style="font-size: 14pt">.
|
||
It's a kind of placeholder for the calls that do not fit well in
|
||
other places. So we do</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>IUtil*
|
||
utl = master->getUtilInterface();</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>IXpbBuilder*
|
||
dpb = utl->getXpbBuilder(&status, IXpbBuilder::DPB, NULL, 0);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">This
|
||
creates empty parameters' block builder of DPB type. Now adding
|
||
required parameter to it is trivial:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>dpb->insertInt(&status,
|
||
isc_dpb_page_size, 4 * 1024);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">will
|
||
make firebird to create new database with pagesize equal to 4Kb and
|
||
meaning of</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>dpb->insertString(&status,
|
||
isc_dpb_user_name, “sysdba”);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>dpb->insertString(&status,
|
||
isc_dpb_password, “masterkey”);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">is
|
||
(I hope) obvious.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="Status Wrapper"></a><font size="4" style="font-size: 14pt"><u>The
|
||
following is C++ specific: </u>We are almost ready to call
|
||
createDatabase() method of IProvider, but before it a few words about
|
||
concept of <b>Status Wrapper</b> should be said. Status wrapper is
|
||
not an interface, it's very thin envelope for IStatus interface. It
|
||
helps to customize behavior of C++ API (change a way how errors,
|
||
returned in IStatus interface, are processed). For the first time we
|
||
recommend use of <b>ThrowStatusWrapper</b>, which raises C++
|
||
exception each time an error is returned in IStatus.</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>ThrowStatusWrapper
|
||
status(st);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Now
|
||
we may create new empty database:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i><a href="#Attachment">IAttachment</a>*
|
||
att = prov->createDatabase(&status, "fbtests.fdb",
|
||
dpb->getBufferLength(&status), dpb->getBuffer(&status));</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>printf("Database
|
||
fbtests.fdb created\n");</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Pay
|
||
attention that we do not check status after the call to
|
||
createDatabase(), because in case of error C++ or Pascal exception
|
||
will be raised (therefore it's very good idea to have
|
||
try/catch/except syntax in your program). We also use two new
|
||
functions from IXpbBuilder – getBufferLength() and getBuffer(),
|
||
which extract data from interface in native parameters block format.
|
||
As you can see there is no need to check explicitly for status of
|
||
functions, returning intermediate results.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Detaching
|
||
from just created database is trivial:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>att->detach(&status);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Now
|
||
it remains to enclose all operators into <i>try</i> block and write a
|
||
handler in catch block. When using ThrowStatusWrapper you should
|
||
always catch defined in C++ API exception class FbException, in
|
||
Pascal you must also work with class FbException. Exception handler
|
||
block in simplest case may look this way:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>catch
|
||
(const FbException& error)</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>{</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>char
|
||
buf[256];</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>utl->formatStatus(buf,
|
||
sizeof(buf), error.getStatus());</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>fprintf(stderr,
|
||
"%s\n", buf);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>}</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Pay
|
||
attention that here we use one more function from <a href="#Util">IUtil</a>
|
||
– formatStatus(). It returns in buffer text, describing an error
|
||
(warning), stored in IStatus parameter.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">To
|
||
attach to existing database just use attachDatabase() method of
|
||
IProvider instead createDatabase(). All parameters are the same for
|
||
both methods.</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>att
|
||
= prov->attachDatabase(&status, "fbtests.fdb", 0,
|
||
NULL);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">This
|
||
sample is using no additional DPB parameters. Take into account that
|
||
without logon/password any remote connection will fail if no trusted
|
||
authorization plugin is configured. Certainly login info may be also
|
||
provided in environment (in ISC_USER and ISC_PASSWORD variables) like
|
||
it was before.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Our
|
||
examples contain complete samples, dedicated except others to
|
||
creating databases – 01.create.cpp and 01.create.pas. When samples
|
||
are present it will be very useful to build and try to run
|
||
appropriate samples when reading this document.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<h1><font size="4" style="font-size: 14pt">Working with transactions.</font></h1>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Only
|
||
creating empty databases is definitely not enough to work with RDBMS.
|
||
We want to be able to create various objects (like tables and so on)
|
||
in database and insert data in that tables. Any operation within
|
||
database is performed by firebird under transaction control.
|
||
Therefore first of all we must learn to start transaction. Here we do
|
||
not discuss distributed transactions (supported by <a href="#Dtc">IDtc</a>
|
||
interface) to avoid unneeded to most users overcomplication. Starting
|
||
of non-distributed transaction is very simple and done via attachment
|
||
interface:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i><a href="#Transaction">ITransaction</a>*
|
||
tra = att->startTransaction(&status, 0, NULL);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">In
|
||
this sample default transaction parameters are used – no TPB is
|
||
passed to startTransaction() method. If you need non-default
|
||
parameters you may create appropriate <a href="#XpbBuilder">IXpbBuilder</a>,
|
||
add required items to it:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i><a href="#XpbBuilder">IXpbBuilder</a>*
|
||
tpb = utl->getXpbBuilder(&status, IXpbBuilder::TPB, NULL, 0);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>tpb->insertTag(&status,
|
||
isc_tpb_read_committed);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">and
|
||
pass resulting TPB to startTransaction():</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>ITransaction*
|
||
tra = att->startTransaction(&status,
|
||
tpb->getBufferLength(&status), tpb->getBuffer(&status));</i></font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Transaction
|
||
interface is used as a parameter in a lot of other API calls but
|
||
itself it does not perform any actions except commit/rollback
|
||
transaction, may be retaining:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>tra->commit(&status);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">You
|
||
may take a look at how to start and commit transaction in examples
|
||
01.create.cpp and 01.create.pas.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<h1><font size="4" style="font-size: 14pt">Executing SQL operator
|
||
without input parameters and returned rows.</font></h1>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">With
|
||
started transaction we are ready to execute our first SQL operators.
|
||
Used for it execute() method in <a href="#Attachment">IAttachment</a>
|
||
is rather universal and may be also used to execute SQL operators
|
||
with input and output parameters (which is typical for EXECUTE
|
||
PROCEDURE statement), but right now we will use the simple most form
|
||
of it. Both DDL and DML operators can be executed:</font></p>
|
||
<p style="margin-bottom: 0cm; font-weight: normal"><font size="4" style="font-size: 14pt"><i>att->execute(&status,
|
||
tra, 0, "create table dates_table (d1 date)",
|
||
SQL_DIALECT_V6, NULL, NULL, NULL, NULL);</i></font></p>
|
||
<p style="margin-bottom: 0cm; font-weight: normal"><font size="4" style="font-size: 14pt"><i>tra->commitRetaining(&status);</i></font></p>
|
||
<p style="margin-bottom: 0cm; font-weight: normal"><font size="4" style="font-size: 14pt"><i>att->execute(&status,
|
||
tra, 0, "insert into dates_table values (CURRENT_DATE)",
|
||
SQL_DIALECT_V6, NULL, NULL, NULL, NULL);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">As
|
||
you can see transaction interface is a required parameter for
|
||
execute() method (must be NULL only if you execute START TRANSACTION
|
||
statement). Next follows length of SQL operator (may be zero causing
|
||
use of C rules to determine string length), text of operator and SQL
|
||
dialect that should be used for it. The following for NULLs stand for
|
||
metadata descriptions and buffers of input parameters and output
|
||
data. Complete description of this method is provided in <a href="#Attachment">IAttachment</a>
|
||
interface.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">You
|
||
may take a look at how to start and commit transaction in examples
|
||
01.create.cpp and 01.create.pas.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<h1><font size="4" style="font-size: 14pt">Executing SQL operator
|
||
with input parameters.</font></h1>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">There
|
||
are 2 ways to execute statement with input parameters. Choice of
|
||
correct method depends upon do you need to execute it more than once
|
||
and do you know in advance format of parameters. When that format is
|
||
known and statement is needed to be run only once single call to
|
||
IAttachment::execute() may be used. In other cases SQL statement
|
||
should be prepared first and after it executed, may be many times
|
||
with different parameters.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">To
|
||
prepare SQL statement for execution use prepare() method of
|
||
<a href="#Attachment">IAttachment</a> interface:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i><a href="#Statement">IStatement</a>*
|
||
stmt = att->prepare(&status, tra, 0, “UPDATE department SET
|
||
budget = ? * budget + budget WHERE dept_no = ?”,</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>SQL_DIALECT_V6,
|
||
IStatement::PREPARE_PREFETCH_METADATA);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">If
|
||
you are not going to use parameters description from firebird (i.e.
|
||
you can provide that information yourself) please use
|
||
IStatement::PREPARE_PREFETCH_NONE instead PREPARE_PREFETCH_METADATA –
|
||
this will save client/server traffic and server resources a bit.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">In
|
||
ISC API XSQLDA is used to describe format of statement parameters.
|
||
New API does not use XSQLDA – instead interface IMessageMetadata is
|
||
used. A set of input parameters (and also a row fetched from cursor)
|
||
is described in firebird API in same way and later called message.
|
||
<a href="#MessageMetadata">IMessageMetadata</a> is passed as a
|
||
parameter to the methods performing message exchange between your
|
||
program and database engine. There are many ways to have an instance
|
||
of IMessageMetadata – one can:</font></p>
|
||
<ul>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">get
|
||
it from <a href="#Statement">IStatement</a>,</font></p>
|
||
</ul>
|
||
<ul>
|
||
<li value="1"><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">build
|
||
using <a href="#MetadataBuilder">IMetadataBuilder</a> interface,</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">have
|
||
your own implementation of this interface.</font></p>
|
||
</ul>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Getting
|
||
metadata from prepared statement is very simple – method
|
||
getInputMetadata() return interface describing input message (i.e.
|
||
statement parameters), interface returned by getOutputMetadata()
|
||
describes output message (i.e. row in selected data or values
|
||
returned by procedure). In our case we can:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i><a href="#MessageMetadata">IMessageMetadata</a>*
|
||
meta = stmt->getInputMetadata(&status);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Or
|
||
we can build message metadata ourself. First of all we need builder
|
||
interface for it:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i><a href="#MetadataBuilder">IMetadataBuilder</a>*
|
||
builder = master->getMetadataBuilder(&status, 2);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Second
|
||
parameter is expected number of fields in the message, it can be
|
||
changed later, i.e. that's just an optimization.</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Now
|
||
it's necessary to set individual fields characteristics in the
|
||
builder. An absolute minimum is field types and length for string
|
||
fields:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>builder->setType(&status,
|
||
0, SQL_DOUBLE + 1);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>builder->setType(&status,
|
||
1, SQL_TEXT + 1);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>builder->setLength(&status,
|
||
1, 3);</i></font></p>
|
||
<p style="margin-bottom: 0cm; font-variant: normal; font-style: normal">
|
||
<font size="4" style="font-size: 14pt">New API is using old constants
|
||
for SQL types, smallest bit as earlier stands for nullability. In
|
||
some case it may also make sense to set sub-type (for blobs),
|
||
character set (for text fields) or scale (for numeric fields). And
|
||
finally it's time to get an instance of IMessageMetadata:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i><a href="#MessageMetadata">IMessageMetadata</a>*
|
||
meta = builder->getMetadata(&status);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm; font-variant: normal; font-style: normal">
|
||
<font size="4" style="font-size: 14pt">Here we do not discuss in
|
||
details own implementation of IMessageMetadata. If one cares there is
|
||
a sample 05.user_metadata.cpp.</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">So
|
||
finally we have obtained (one or another way) an instance of metadata
|
||
description of input parameters. But to work with a message we also
|
||
need buffer for it. Buffer size is one of main message metadata
|
||
characteristics and it's returned by method in IMessageMetadata:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>char*
|
||
buffer = new char[meta->getMessageLength(&status)];</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">To
|
||
deal with individual values inside buffer offset to them should be
|
||
taken into an account. IMessageMetadata is aware of offsets for all
|
||
values in a message, using it we can create pointers to them:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>double*
|
||
percent_inc = (double*) &buffer[meta->getOffset(&status,
|
||
0)];</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>char*
|
||
dept_no = &buffer[meta->getOffset(&status, 1)];</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Also
|
||
let's do not forget to set to NOT NULL null flags:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>short*
|
||
flag = (short*)&buffer[meta->getNullOffset(&status, 0)];</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>*flag
|
||
= 0;</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>flag
|
||
= (short*) &buffer[meta->getNullOffset(&status, 1)];</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>*flag
|
||
= 0;</i></font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">After
|
||
finishing with offsets we are ready to execute statement with some
|
||
parameters values:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>getInputValues(dept_no,
|
||
percent_inc);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">and
|
||
may execute prepared statement:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>stmt->execute(&status,
|
||
tra, meta, buffer, NULL, NULL);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Two
|
||
more NULLs in the end of parameters stand for output message and is
|
||
used typically for EXECUTE PROCEDURE statement.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">If
|
||
you do not need to get metadata from statement and plan to execute it
|
||
only once you may choose a simpler way – use method execute() in
|
||
<a href="#Attachment">IAttachment</a> interface:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>att->execute(&status,
|
||
tra, 0, "UPDATE department SET budget = ? * budget + budget
|
||
WHERE dept_no = ?", SQL_DIALECT_V6, meta, buffer, NULL, NULL);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">In
|
||
that case you do not need to use <a href="#Statement">IStatement</a>
|
||
at all.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">An
|
||
example how to execute UPDATE with parameters is present in
|
||
02.update.cpp, you will also see how raised in trigger/procedure
|
||
exception may be caught by C++ program.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<h1><font size="4" style="font-size: 14pt">Opening cursor and
|
||
fetching data from it.</font></h1>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">The
|
||
only way to get rows of data, returned by SELECT operator, in OO API
|
||
is to use <a href="#ResultSet">IResultSet</a> interface. This
|
||
interface is returned by openCursor() method in both IAttachment and
|
||
IStatement. openCursor() is in most aspects alike execute() and a
|
||
choice how to open cursor (using prepared statement or directly from
|
||
attachment interface) is the same. In the samples 03.select.cpp and
|
||
04.print_table.cpp both methods are used. Let's pay attention at one
|
||
specific openCursor() feature compared with execute() - one does not
|
||
pass buffer for output message into openCursor(), it will be passed
|
||
later when data is fetched from cursor. This makes it possible to
|
||
open cursor with unknown format of output message (NULL is passed
|
||
instead output metadata). Firebird is using in this case default
|
||
message format which may be requested from IResultSet interface:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>const
|
||
char* sql = "select * from ..."; // some select statement</i></font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i><a href="#ResultSet">IResultSet</a>*
|
||
curs = att->openCursor(&status, tra, 0, sql, SQL_DIALECT_V6,
|
||
NULL, NULL, NULL, NULL, 0);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i><a href="#MessageMetadata">IMessageMetadata</a>*
|
||
meta = curs->getMetadata(&status);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Later
|
||
this metadata may be used to allocate buffer for data and parse
|
||
fetched rows.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">As
|
||
an alternative one can first prepare statement, get metadata from
|
||
prepared statement and after it open cursor. This is preferred way if
|
||
cursor is likely to be opened >1 times.</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><a href="#Statement">IStatement</a>*
|
||
stmt = att->prepare(&status, tra, 0, sql, SQL_DIALECT_V6,
|
||
Istatement::PREPARE_PREFETCH_METADATA);</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><a href="#MessageMetadata">IMessageMetadata</a>*
|
||
meta = stmt->getOutputMetadata(&status);</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><a href="#ResultSet">IResultSet</a>*
|
||
curs = stmt->openCursor(&status, tra, NULL, NULL, NULL, 0);</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">We
|
||
have obtained (one or another way) an instance of metadata
|
||
description of output fields (a row in a set). To work with a message
|
||
we also need buffer for it:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>unsigned
|
||
char* buffer = new unsigned char[meta->getMessageLength(&status)];</i></font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IResultSet
|
||
has a lot of various fetch methods but when cursor is not opened with
|
||
SCROLL option only fetchNext() works, i.e. one can navigate only
|
||
forward record by record. In addition to errors and warnings in
|
||
status fetchNext() returns completion code, which may have values
|
||
RESULT_OK (when buffer is filled with values for next row) or
|
||
RESULT_NO_DATA (when no more rows left in cursor). RESULT_NO_DATA is
|
||
not error state, it's normal state after completion of the method,
|
||
but we know that data in cursor is over. If status wrapper, not
|
||
throwing exception in case of error return is used, one more value –
|
||
RESULT_ERROR – may be returned, that means no data in buffer and
|
||
error vector in status. Method fetchNext() is usually called in a
|
||
cycle:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>while
|
||
(curs->fetchNext(&status, buffer) == IStatus::RESULT_OK)</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>{</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>//
|
||
row processing</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>}</i></font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">What
|
||
is done during row processing depends upon your needs. To access
|
||
particular field field's offset should be used:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>unsigned
|
||
char* field_N_ptr = buffer + meta->getOffset(&status, n);</i></font></p>
|
||
<p style="margin-bottom: 0cm; font-variant: normal; font-style: normal">
|
||
<font size="4" style="font-size: 14pt">where n is the number of a
|
||
field in a message. That pointer should be casted to appropriate
|
||
type, depending upon field type. For example, for a VARCHAR field
|
||
cast to struct vary should be used:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>vary*
|
||
v_ptr = (vary*) (buffer + meta->getOffset(&status, n));</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Now
|
||
we may print the value of a field:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>printf(“field
|
||
%s value is %*.*s\n”, meta->getField(&status, n),
|
||
v_ptr->vary_length, v_ptr->vary_length, v_ptr->vary_string);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">If
|
||
you need maximum performance it will be good idea to cache needed
|
||
metadata values like it's done in our samples 03.select.cpp and
|
||
04.print_table.cpp.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<h1><font size="4" style="font-size: 14pt">Using FB_MESSAGE macro for
|
||
static messages.</font></h1>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Working
|
||
with data using offsets is rather efficient but requires a lot of
|
||
code to be written. In C++ this problem can be solved using
|
||
templates, but even compared with them the most convenient way to
|
||
work with the message is to represent it in native (for given
|
||
language) way – structure in C/C++, record in Pascal, etc.
|
||
Certainly this works only if format of a message is known in advance.
|
||
To help building such structures in C++ firebird contains special
|
||
macro FB_MESSAGE.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_MESSAGE
|
||
has 3 arguments – message (struct) name, type of status wrapper and
|
||
list of fields. Usage of first and second is obvious, list of fields
|
||
contains pairs (field_type, field_name), where field_type is one of
|
||
the following:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_BIGINT</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_BLOB</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_BOOLEAN</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_CHAR(len)</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_DATE</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_DECFIXED(scale)</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_DECFLOAT16</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_DECFLOAT34</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_DOUBLE</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_FLOAT</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_INTEGER</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_INTL_CHAR(len,
|
||
charSet)</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_INTL_VARCHAR(len,
|
||
charSet)</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_SCALED_BIGINT(scale)</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_SCALED_INTEGER(scale)</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_SCALED_SMALLINT(scale)</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_SMALLINT</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_TIME</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_TIMESTAMP</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_VARCHAR(len)</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">In
|
||
generated by preprocessor structure integer and float types are
|
||
matched with appropriate C types, date and time – with classes
|
||
<a href="#FbDate">FbDate</a> and <a href="#FbTime">FbTime</a> (all
|
||
mentioned here classes are in namespace Firebird), timestamp – with
|
||
class FbTimestamp, containing two public data members date and time
|
||
of appropriate class, char - with struct <a href="#FbChar">FbChar</a>
|
||
and varchar – with struct <a href="#FbVarChar">FbVarChar</a>. For
|
||
each field preprocessor creates two data members in the message –
|
||
</font><font size="4" style="font-size: 14pt"><i>name</i></font> <font size="4" style="font-size: 14pt">for
|
||
field/parameter value and </font><font size="4" style="font-size: 14pt"><i>nameNull</i></font>
|
||
<font size="4" style="font-size: 14pt">for NULL indicator. Message
|
||
constructor has 2 parameters – pointer to status wrapper and master
|
||
interface:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>FB_MESSAGE(Output,
|
||
ThrowStatusWrapper,</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>(FB_SMALLINT,
|
||
relationId)</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>(FB_CHAR(31),
|
||
relationName)</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>(FB_VARCHAR(100),
|
||
description)</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>)
|
||
output(&status, master);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">For
|
||
static messages use of FB_MESSAGE is sooner of all the best choice –
|
||
they can be at the same time easily passed to execute, openCursor and
|
||
fetch methods:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>rs
|
||
= att->openCursor(&status, tra, 0, sqlText,</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>SQL_DIALECT_V6,
|
||
NULL, NULL, output.getMetadata(), NULL, 0);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">and
|
||
used to work with values of individual fields:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>while
|
||
(rs->fetchNext(&status, output.getData()) ==
|
||
IStatus::RESULT_OK)</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>{</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>printf("%4d
|
||
%31.31s %*.*s\n", output->relationId,
|
||
output->relationName.str,</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>output->descriptionNull
|
||
? 0 : output->description.length,</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>output->descriptionNull
|
||
? 0 : output->description.length, output->description.str);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>}</i></font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">An
|
||
example of using macro FB_MESSAGE to work with messages is in the
|
||
sample 06.fb_message.cpp.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<h1><font size="4" style="font-size: 14pt">Working with blobs.</font></h1>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">For
|
||
blobs in message buffer firebird stores blob identifier – an 8-byte
|
||
entity which should be aligned on 4-byte boundary. Identifier has
|
||
ISC_QUAD type. Interface <a href="#Attachment">IAttachment</a> has 2
|
||
methods to work with blobs – openBlob() and createBlob(), both
|
||
returning interface <a href="#Blob">IBlob</a> and having same set of
|
||
parameters, but performing somewhat contrary actions: openBlob()
|
||
takes blob identifier from the message and prepares blob for reading
|
||
but createBlob() creates new blob, puts it's identifier into message
|
||
and prepares blob for writing. </font>
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">To
|
||
work with blobs one must first of all include blob identifier into
|
||
the message. If you get metadata from firebird engine field of
|
||
appropriate type will be already present. You just use it's offset
|
||
(assuming variable blobFieldNumber contains number of blob field)
|
||
(and appropriate null offset to check for nulls or set null flag) to
|
||
obtain pointer into the message buffer:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>ISC_QUAD*
|
||
blobPtr = (ISC_QUAD*) &buffer[metadata->getOffset(&status,
|
||
blobFieldNumber)];</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>ISC_SHORT*
|
||
blobNullPtr = (ISC_SHORT*) &buffer[metadata->getNullOffset(&status,
|
||
blobFieldNumber)];</i></font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">If
|
||
you use static messages and FB_MESSAGE macro blob field is declared
|
||
as having FB_BLOB type:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>FB_MESSAGE(Msg,
|
||
ThrowStatusWrapper,</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>(FB_BLOB,
|
||
b)</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>)
|
||
message(&status, master);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>ISC_QUAD*
|
||
blobPtr = &message->b;</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>ISC_SHORT*
|
||
blobNullPtr = &message->bNull;</i></font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">To
|
||
create new blob invoke createBlob() method:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i><a href="#Blob">IBlob</a>*
|
||
blob = att->createBlob(status, tra, blobPtr, 0, NULL);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Last
|
||
two parameters are required only if you want to use blob filters or
|
||
use stream blob, that's out of scope here.</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Blob
|
||
interface is ready to accept data into blob. Use putSegment() method
|
||
to send data to engine:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>void*
|
||
segmentData;</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>unsigned
|
||
segmentLength;</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>while
|
||
(userFunctionProvidingBlobData(&segmentData, &segmentLength))</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>blob->putSegment(&status,
|
||
segmentLength, segmentData);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">After
|
||
sending some data to blob do not forget to close blob interface:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>blob->close(&status);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Make
|
||
sure that null flag is not set (not required if you nullified all
|
||
message buffer before creating blob):</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>*blobNullPtr
|
||
= 0;</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">and
|
||
message, containing blob, may be used in insert or update statement.
|
||
After execution of that statement new blob will be stored in
|
||
database.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">To
|
||
read a blob begin with getting containing it's identifier message
|
||
from firebird engine. This may be done using fetch() or execute()
|
||
methods. After it use openBlob() attachment's method:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i><a href="#Blob">IBlob</a>*
|
||
blob = att->openBlob(status, tra, blobPtr, 0, NULL);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Blob
|
||
interface is ready to provide blob data. Use getSegment() method to
|
||
receive data from engine:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>char
|
||
buffer[BUFSIZE];</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>unsigned
|
||
actualLength;</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>for(;;)</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>{</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>switch
|
||
(blob->getSegment(&status, sizeof(buffer), buffer,
|
||
&actualLength))</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>{</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>case
|
||
IStatus::RESULT_OK:</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>userFunctionAcceptingBlobData(buffer,
|
||
actualLength, true);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>continue;</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>case
|
||
IStatus::RESULT_SEGMENT:</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>userFunctionAcceptingBlobData(buffer,
|
||
actualLength, false);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>continue;</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>default:</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>break;</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>}</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>}</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Last
|
||
parameter in userFunctionAcceptingBlobData() is a flag that end of
|
||
segment is reached – when getSegment() returns RESULT_SEGMENT
|
||
completion code that function is notified (by passing false as last
|
||
parameter) that segment was not read completely and continuation is
|
||
expected at next call.</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">After
|
||
finishing with blob do not forget to close it:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>blob->close(&status);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<h1><a name="Modifying data in a batch"></a><font size="4" style="font-size: 14pt">Modifying
|
||
data in a batch.</font></h1>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Since
|
||
version 4 firebird supports batch execution of statements with input
|
||
parameters – that means sending more than single set of parameters
|
||
when executing statement. <a href="#Batch">Batch</a> interface is
|
||
designed (first of all) in order to satisfy JDBC requirements for
|
||
prepared statement’s batch processing but has some serious
|
||
differences:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">-
|
||
like all operations with data in firebird it’s oriented on
|
||
messages, not single field;</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">-
|
||
as an important extension out batch interface supports inline use of
|
||
blobs (specially efficient when working with small blobs);</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">-
|
||
execute() method returns not plain array of integers but special
|
||
<a href="#BatchCompletionState">BatchCompletionState</a> interface
|
||
which can (depending upon batch creation parameters) contain both
|
||
update records info and in addition to error flag detailed status
|
||
vectors for messages that caused execution errors.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><a href="#Batch">Batch</a>
|
||
(exactly like <a href="#ResultSet">ResultSet</a>) may be created in 2
|
||
ways – using <a href="#Statement">Statement</a> or <a href="#Attachment">Attachment</a>
|
||
interface, in both cases createBatch() method of appropriate
|
||
interface is called. In second case text of SQL statement to be
|
||
executed in a batch is passed directly to createBatch(). Tuning of
|
||
batch operation is performed using <a href="#Batch_PB">Batch
|
||
parameters block</a> which has format more or less similar to DPB v.2
|
||
– tag in the beginning (IBatch::CURRENT_VERSION) followed by the
|
||
set of wide clumplets: 1-byte tag, 4-byte length, length-byte value.
|
||
Possible tags are <a href="#Batch_PB">described</a> in batch
|
||
interface. The simplest (and recommended) way to create parameters
|
||
block for batch creation is to use appropriate <a href="#XpbBuilder">XpbBuilder</a>
|
||
interface:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>IXpbBuilder*
|
||
pb = utl->getXpbBuilder(&status, IXpbBuilder::BATCH, NULL, 0);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>pb->insertInt(&status,
|
||
IBatch::RECORD_COUNTS, 1);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Use
|
||
of such parameters block directs batch to account number of updated
|
||
records on per-message basis.</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">To
|
||
create batch interface with desired parameters pass parameters block
|
||
to createBatch() call:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>IBatch*
|
||
batch = att->createBatch(&status, tra, 0, sqlStmtText,
|
||
SQL_DIALECT_V6, NULL,</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>pb->getBufferLength(&status),
|
||
pb->getBuffer(&status));</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">In
|
||
this sample batch interface is created with default format of
|
||
messages cause NULL is passed instead input metadata format.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">In
|
||
order to proceed with created batch interface we need to know format
|
||
of messages in it. It can be obtained using getMetadata() method:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>IMessageMetadata*
|
||
meta = batch->getMetadata(&status);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Certainly
|
||
if you have passed your own format of messages to the batch you may
|
||
simply use it.</font></p>
|
||
<p style="margin-bottom: 0cm; font-variant: normal; font-style: normal">
|
||
<font size="4" style="font-size: 14pt">In the former text I suppose
|
||
that some function fillNextMessage(unsigned char* data,
|
||
IMessageMetadata* metadata) is present and can fill buffer ‘data’
|
||
according to passed format ‘metadata’. In order to work with
|
||
messages we need a buffer for a data:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>unsigned
|
||
char* data = new unsigned char[meta->getMessageLength(&status)];</i></font></p>
|
||
<p style="margin-bottom: 0cm; font-variant: normal; font-style: normal">
|
||
<font size="4" style="font-size: 14pt">Now we can add some messages
|
||
full of data to the batch:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>fillNextMessage(data,
|
||
meta);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>batch->add(&status,
|
||
1, data);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>fillNextMessage(data,
|
||
meta);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>batch->add(&status,
|
||
1, data);</i></font></p>
|
||
<p style="margin-bottom: 0cm; font-variant: normal; font-style: normal">
|
||
<font size="4" style="font-size: 14pt">An alternative way of working
|
||
with messages (using FB_MESSAGE macro) is present in the sample of
|
||
using batch interface 11.batch.cpp.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm; font-variant: normal; font-style: normal">
|
||
<font size="4" style="font-size: 14pt">Finally batch should be
|
||
executed:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i><a href="#BatchCompletionState">IBatchCompletionState</a>*
|
||
cs = batch->execute(&status, tra);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">We
|
||
requested accounting of the number of modified (inserted, updated or
|
||
deleted) records per message. To print it we must use
|
||
<a href="#BatchCompletionState">BatchCompletionState</a> interface.
|
||
Determine total number of messages processed by batch (it can be less
|
||
than the number of messages passed to the batch if error happened and
|
||
an option enabling multiple errors during batch processing was not
|
||
turned on):</font></p>
|
||
<p><font size="4" style="font-size: 14pt"><i>unsigned total =
|
||
cs->getSize(&status);</i></font></p>
|
||
<p><font size="4" style="font-size: 14pt">Now print the state of each
|
||
message:</font></p>
|
||
<p><font size="4" style="font-size: 14pt"><i>for (unsigned p = 0; p <
|
||
total; ++p) printf(“Msg %u state %d\n”, p, cs->getState(&status,
|
||
p));</i></font></p>
|
||
<p style="font-variant: normal; font-style: normal"><font size="4" style="font-size: 14pt">When
|
||
finished analyzing completion state don’t forget to dispose it:</font></p>
|
||
<p><font size="4" style="font-size: 14pt"><i>cs->dispose();</i></font></p>
|
||
<p><font color="#000000"><font size="4" style="font-size: 14pt">Full
|
||
sample of printing contents</font></font><font color="#000000"> of
|
||
</font><font color="#000000"><font size="4" style="font-size: 14pt"><a href="#BatchCompletionState">BatchCompletionState</a>
|
||
is in print_cs() function in sample 11.batch.cpp.</font></font></p>
|
||
<p style="font-variant: normal; font-style: normal"><font size="4" style="font-size: 14pt">If
|
||
for some reason you want to make batch buffers empty not executing it
|
||
(i.e. prepare for new portion of messages to process) use cancel()
|
||
method:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>batch->cancel(&status);</i></font></p>
|
||
<p style="margin-bottom: 0cm; font-variant: normal; font-style: normal">
|
||
<font size="4" style="font-size: 14pt">Like the rest of our data
|
||
access interfaces Batch has special method to close it:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>batch->close(&status);</i></font></p>
|
||
<p style="margin-bottom: 0cm; font-variant: normal; font-style: normal">
|
||
<font size="4" style="font-size: 14pt">Standard release() call may be
|
||
used instead if one does not care about errors:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>batch->release();</i></font></p>
|
||
<p style="margin-bottom: 0cm; font-variant: normal; font-style: normal">
|
||
<font size="4" style="font-size: 14pt">Described methods help to
|
||
implement all what one needs for JDBC-style prepared statement batch
|
||
operations. </font>
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Notice:
|
||
JDBC does not recommend to use too large batches, for example “<a href="https://docs.oracle.com/cd/E11882_01/java.112/e16548/oraperf.htm#JJDBC28753">Oracle
|
||
recommends you to keep the batch sizes in the general range of 50 to
|
||
100</a>”. Firebird supports bigger batches but it anyway has to
|
||
limit maximum batch size – see <a href="#TAG_BUFFER_BYTES_SIZE">TAG_BUFFER_BYTES_SIZE</a>.
|
||
If total size of messages exceeds that limit isc_batch_too_big error
|
||
is returned. Pay attention that due to deep buffering of batch data
|
||
when sending it over the wire you will not get this error at once but
|
||
only when buffers are flashed from client to server. This may happen
|
||
in both add() and execute() methods – execute() performs final
|
||
flash. If you still wish to execute the batch with the messages that
|
||
fit in a buffer you may do it (when error was returned by execute()
|
||
just repeat it). An actual number of processed messages will be
|
||
returned in </font><font color="#000000"><font size="4" style="font-size: 14pt"><a href="#BatchCompletionState">BatchCompletionState</a>.
|
||
An optimal batch size should be found for each particular case but
|
||
sooner of all having it >1000 hardly gives you serious performance
|
||
increase.</font></font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p><font size="4" style="font-size: 14pt">One can add more than
|
||
single message in one call to the batch. When doing it please
|
||
remember – messages should be appropriately aligned for this
|
||
feature to work correctly. Required alignment and aligned size of the
|
||
message should be obtained from <a href="#MessageMetadata">MessageMetadata</a>
|
||
interface, for example:</font></p>
|
||
<p><font size="4" style="font-size: 14pt"><i>unsigned aligned =
|
||
meta->getAlignedLength(&status);</i></font></p>
|
||
<p><font size="4" style="font-size: 14pt">Later that size will be
|
||
useful when allocating an array of messages and working with it:</font></p>
|
||
<p><font size="4" style="font-size: 14pt"><i>unsigned char* data =
|
||
new unsigned char[aligned * N]; // N is desired number of messages</i></font></p>
|
||
<p><font size="4" style="font-size: 14pt"><i>for (int n = 0; n <
|
||
N; ++n) fillNextMessage(&data[aligned * n], meta);</i></font></p>
|
||
<p><font size="4" style="font-size: 14pt"><i>batch->add(&status,
|
||
N, data);</i></font></p>
|
||
<p style="font-variant: normal; font-style: normal"><font size="4" style="font-size: 14pt">After
|
||
it batch may be executed or next portion of messages added to it.</font></p>
|
||
<p><br/>
|
||
<br/>
|
||
|
||
</p>
|
||
<p><font size="4" style="font-size: 14pt">Blobs in general are not
|
||
compatible with batches – batch is efficient when one needs to pass
|
||
a lot of small data to the server in single step, blobs are treated
|
||
as large objects and therefore in general it makes no sense to use
|
||
them in batches. But on practice it often happens that blobs are not
|
||
too big – and in this case use of traditional blob API (create
|
||
blob, pass segments to the server, close blob, pass blobs ID in the
|
||
message) kills performance, specially when used over WAN. Therefore
|
||
in firebird batch supports passing blobs to server inline, together
|
||
with other messages. To use that feature first of all <a href="#Batch_Blob_Policy">blob
|
||
usage policy</a> for a batch to be created should be set (as an
|
||
option in <a href="#Batch_PB">parameters block</a>):</font></p>
|
||
<p><font size="4" style="font-size: 14pt"><i>pb->insertInt(&status,
|
||
IBatch::BLOB_IDS, IBatch::BLOB_IDS_ENGINE);</i></font></p>
|
||
<p style="font-variant: normal; font-style: normal"><font size="4" style="font-size: 14pt">In
|
||
this example temporal blob IDs needed to keep a link between blob and
|
||
a message where it’s used will be generated by firebird engine –
|
||
that’s the simplest and rather common usage. Imagine that the
|
||
message is described as follows:</font></p>
|
||
<p style="font-variant: normal"><font size="4" style="font-size: 14pt"><i>FB_MESSAGE(Msg,
|
||
ThrowStatusWrapper,</i></font></p>
|
||
<p><font size="4" style="font-size: 14pt"><i>(FB_VARCHAR(5), id)</i></font></p>
|
||
<p><font size="4" style="font-size: 14pt"><i>(FB_VARCHAR(10), name)</i></font></p>
|
||
<p><font size="4" style="font-size: 14pt"><i>(FB_BLOB, desc)</i></font></p>
|
||
<p><font size="4" style="font-size: 14pt"><i>) project(&status,
|
||
master);</i></font></p>
|
||
<p style="font-variant: normal; font-style: normal"><font size="4" style="font-size: 14pt">In
|
||
that case to send a message containing blob to the server one can do
|
||
something like this:</font></p>
|
||
<p><font size="4" style="font-size: 14pt"><i>project->id =
|
||
++idCounter;</i></font></p>
|
||
<p><font size="4" style="font-size: 14pt"><i>project->name.set(currentName);</i></font></p>
|
||
<p><font size="4" style="font-size: 14pt"><i>batch->addBlob(&status,
|
||
descriptionSize, descriptionText, &project->desc);</i></font></p>
|
||
<p><font size="4" style="font-size: 14pt"><i>batch->add(&status,
|
||
1, project.getData());</i></font></p>
|
||
<p style="margin-bottom: 0cm; font-variant: normal; font-style: normal">
|
||
<font size="4" style="font-size: 14pt">If some blob happened to be
|
||
big enough not to fit into your existing buffer you may instead
|
||
reallocating buffer use appendBlobData() method. It appends more data
|
||
to last added blob. </font>
|
||
</p>
|
||
<p style="font-variant: normal"><font size="4" style="font-size: 14pt"><i>batch->addBlob(&status,
|
||
descriptionSize, descriptionText, &project→desc, bpbLength,
|
||
bpb);</i></font></p>
|
||
<p style="font-variant: normal; font-style: normal"><font size="4" style="font-size: 14pt">After
|
||
adding first part of blob get next portion of data into
|
||
descriptionText, update descriptionSize and:</font></p>
|
||
<p style="font-variant: normal"><font size="4" style="font-size: 14pt"><i>batch->appendBlobData(&status,
|
||
descriptionSize, descriptionText);</i></font></p>
|
||
<p><font size="4" style="font-size: 14pt">This may be done in a loop
|
||
but take care not to overflow internal batch buffers – it’s size
|
||
is controlled by <a href="#Batch_PB">BUFFER_BYTES_SIZE</a> option
|
||
when creating batch interface but can’t exceed 256Mb (default is
|
||
16Mb). If you need to process such big blob (for example on the
|
||
background of a lot of small one – this can explain use of batch)
|
||
just use standard blob API and <a href="#Batch::registerBlob">registerBlob</a>
|
||
method of <a href="#Batch">Batch</a> interface.</font></p>
|
||
<p style="font-variant: normal; font-style: normal"><font size="4" style="font-size: 14pt">One
|
||
more possible choice of blob policy is BLOB_IDS_USER. Usage at the
|
||
first look does not change much – before calling addBlob() correct
|
||
and unique per batch execution ID should be placed to the memory
|
||
referenced by last parameter. Certainly same ID should be passed in
|
||
the data message to the blob. Taking into an account that generation
|
||
of blob IDs by engine is very fast such policy may seem useless but
|
||
imagine a case when you get blobs and other data in relatively
|
||
independent streams (blocks in a file for example) and some good IDs
|
||
are already present in them. In such case use of user-supplied blob
|
||
IDs can greatly simplify your code.</font></p>
|
||
<p><font size="4" style="font-size: 14pt">Please take into an account
|
||
– unlike blobs created using regular <a href="#Attachment">createBlob</a>()
|
||
blobs created by <a href="#Batch">Batch</a> interface are by default
|
||
stream, not segmented. Segmented blobs provide nothing interesting
|
||
compared with stream one and therefore not recommended to be used in
|
||
new development, we support that format only for backward
|
||
compatibility reasons. If you really need segmented blobs this
|
||
default may be overridden by calling:</font></p>
|
||
<p><font size="4" style="font-size: 14pt"><i>batch->setDefaultBpb(&status,</i></font>
|
||
<font size="4" style="font-size: 14pt"><i>bpbLength, bpb);</i></font></p>
|
||
<p style="font-variant: normal; font-style: normal"><font size="4" style="font-size: 14pt">Certainly
|
||
passed BPB may contain any other blob creation parameters too. As you
|
||
may have already noticed you may also pass BPB directly to addBlob()
|
||
but if most of blobs you are going to add have same non-default
|
||
format use of setDefaultBpb() is slightly more efficient. Returning
|
||
to segmented blobs – call to addBlob() will add first segment to
|
||
the blob, following calls to appendBlobData() will add more segments.
|
||
Do not forget that segment size is limited to 64Kb – 1, an attempt
|
||
to pass more data in a single call with cause an error.</font></p>
|
||
<p><font size="4" style="font-size: 14pt">Next step when working with
|
||
existing blob streams is use of addBlobStream() method. Using it one
|
||
can add more than one blob to the batch per single call. Blob stream
|
||
is a sequence of blobs, each starts with blob header. Header should
|
||
be appropriately aligned - <a href="#Batch">Batch</a> interface
|
||
provides special call for this purpose:</font></p>
|
||
<p style="font-variant: normal"><font size="4" style="font-size: 14pt"><i>unsigned
|
||
alignment = batch->getBlobAlignment(&status);</i></font></p>
|
||
<p style="font-variant: normal; font-style: normal"><font size="4" style="font-size: 14pt">It’s
|
||
supposed that all components of blob stream in a batch should be
|
||
aligned at least at alignment boundary, including size of stream
|
||
portions passed to addBlobStream() which should be a multiple of this
|
||
alignment. Header contains 3 fields – 8-byte blob ID (must be
|
||
non-zero), 4-byte total blob size and 4 byte BPB size. Total blob
|
||
size includes BPB inside, i.e. one will always find next blob in the
|
||
stream in blob-size bytes after the header (taking into account the
|
||
alignment). BPB (if present, i.e. if BPB size is not zero) is placed
|
||
right after the header. After BPB blob data goes, it’s format
|
||
depends upon blob type – stream or segmented. In case of stream
|
||
blob it’s a plain sequence of bytes having size blob-size –
|
||
BPB-size. With segmented blob things are a bit more compicated: blob
|
||
data is a set of segments where each segment has the following format
|
||
– 2-bytes size of segment (this should be aligned at
|
||
IBatch::BLOB_SEGHDR_ALIGN boundary) followed by stored in this 2
|
||
bytes number of bytes.</font></p>
|
||
<p style="font-variant: normal; font-style: normal"><font size="4" style="font-size: 14pt">When
|
||
big blob is added to the stream it’s size is not always known in
|
||
advance. In order not to have too big buffer for that blob (remember,
|
||
size should be provided in blob header, before blob data) blob
|
||
continuation record may be used. In blob header you leave blob size
|
||
at a value known when creating that header and add continuation
|
||
record that has format absolutely same as blob header, but here blob
|
||
ID must be zero and BPB size must always be zero too. Typically you
|
||
will want to have one continuation record per addBlobStream() call.</font></p>
|
||
<p><a name="Batch::registerBlob"></a><font size="4" style="font-size: 14pt">Last
|
||
method used to work with blobs stands alone from the first three that
|
||
pass blob data inline with the rest of batch data </font>– <font size="4" style="font-size: 14pt">it’s
|
||
needed to register in a batch ID of a blob created using standard
|
||
blob API. This may be unavoidable if one needs to pass to a batch
|
||
really big blob. Do not use ID of such blob in batch directly –
|
||
that will cause invalid blob ID error during batch execution. Instead
|
||
do:</font></p>
|
||
<p><font size="4" style="font-size: 14pt"><i>batch->registerBlob(&status,
|
||
&realId, &msg->desc);</i></font></p>
|
||
<p style="margin-bottom: 0cm; font-variant: normal; font-style: normal">
|
||
<font size="4" style="font-size: 14pt">If blob policy makes firebird
|
||
engine generate blob IDs this code is enough to correctly register
|
||
existing blob in a batch. In other cases you will have to assign
|
||
correct (from batch POV) ID to msg->desc.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm; font-variant: normal; font-style: normal">
|
||
<font size="4" style="font-size: 14pt">Almost all mentioned methods
|
||
are used in 11.batch.cpp – please use it to see an alive sample of
|
||
batching in firebird.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm; font-variant: normal; font-style: normal">
|
||
<font size="4" style="font-size: 14pt">Two words about access to
|
||
batches from ISC API - one can execute prepared ISC statement in
|
||
batch mode. Main support for it is presence of two new API functions,
|
||
namely fb_get_transaction_interface & fb_get_statement_interface,
|
||
which make it possible to access appropriate interfaces identical to
|
||
existing ISC handles. An example of it is present in
|
||
12.batch_isc.cpp.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<h1><font size="4" style="font-size: 14pt">Working with events.</font></h1>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Events
|
||
interface was not completed in FB3, we expect to have something more
|
||
interesting in next version. The minimum existing support is as
|
||
follows: <a href="#Attachment">IAttachment</a> contains call
|
||
queEvents() which performs almost same functions as isc_que_events()
|
||
call. Instead the pair of parameters </font><font size="4" style="font-size: 14pt"><i>FPTR_EVENT_CALLBACK
|
||
ast</i></font> <font size="4" style="font-size: 14pt">and </font><font size="4" style="font-size: 14pt"><i>void*
|
||
arg</i></font><font size="4" style="font-size: 14pt">, required to
|
||
invoke user code when event happens in firebird engine, callback
|
||
interface IEventCallback is used. This is traditional approach which
|
||
helps to avoid non-safe casts from void* in user function. Another
|
||
important difference is that instead event identifier (a kind of
|
||
handler) this function returns reference counted interface <a href="#Events">IEvents</a>
|
||
having method cancel() used when waiting for event should be stopped.
|
||
Unlike identifier which is automatically destroyed when event arrives
|
||
interface can not be automatically destroyed – in case when event
|
||
is received right before canceling interface call to cancel() would
|
||
cause segfault when interface is already destroyed. Therefore
|
||
interface <a href="#Events">IEvents</a> must be explicitly released
|
||
after receiving an event. This may be done for example right before
|
||
queuing for an event next time:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>events->release();</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>events
|
||
= NULL;</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>events
|
||
= attachment->queEvents(&status, this, eveLen, eveBuffer);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Setting
|
||
interface pointer to NULL is useful in case of exception during
|
||
queEvents. In other aspects events handling did not change compared
|
||
with ISC API. Please use for additional details our sample
|
||
08.events.cpp. </font>
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<h1><font size="4" style="font-size: 14pt">Using services.</font></h1>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">To
|
||
begin to use services one should first of all connect to service
|
||
manager. This is done using attachServiceManager() method of
|
||
<a href="#Provider">IProvider</a>. This method returns <a href="#Service">IService</a>
|
||
interface which is used later to talk to service. To prepare SPB to
|
||
attach to service manager one can use IXpbBuilder:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>IXpbBuilder*
|
||
spb1 = utl->getXpbBuilder(&status, IXpbBuilder::SPB_ATTACH,
|
||
NULL, 0);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>spb1->insertString(&status,
|
||
isc_spb_user_name, “sysdba”);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>spb1->insertString(&status,
|
||
isc_spb_password, “masterkey”);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">and
|
||
proceed with attach:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><a href="#Service">IService</a>*
|
||
svc = prov->attachServiceManager(&status, “service_mgr”,
|
||
spb1->getBufferLength(&status), spb1->getBuffer(&status));</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Using
|
||
IService one can perform both available for services actions –
|
||
start services and query various information about started utilities
|
||
and server in general. When querying information one limitation takes
|
||
place – formats of parameter blocks, used by query() method, in
|
||
Firebird 3 are not supported by IXpbBuilder. Support will be probably
|
||
added in later versions, in Firebird 3 you will have to build and
|
||
analyze that blocks manually. Format of that blocks matches old
|
||
format (used in ISC API) one to one. </font>
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">To
|
||
start service one should first of all create appropriate SPB:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IXpbBuilder*
|
||
spb2 = utl->getXpbBuilder(&status, IXpbBuilder::SPB_START,
|
||
NULL, 0);</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">and
|
||
add required items to it. For example, to print encryption statistics
|
||
for database employee the following should be placed into SPB:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">spb2->insertTag(&status,
|
||
isc_action_svc_db_stats);</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">spb2->insertString(&status,
|
||
isc_spb_dbname, "employee");</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">spb2->insertInt(&status,
|
||
isc_spb_options, isc_spb_sts_encryption);</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">After
|
||
it service can be started using start() method of <a href="#Service">IService</a>
|
||
interface:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">svc->start(&status,
|
||
spb2->getBufferLength(&status), spb2->getBuffer(&status));</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Many
|
||
started services (including mentioned here gstat) return text
|
||
information during execution. To display it one should query started
|
||
service anout that information line by line. This is done by calling
|
||
query() method of <a href="#Service">IService</a> interface with
|
||
appropriate send and receive blocks of parameters. Send block may
|
||
contain various helper information (like timeout when querying
|
||
service) or information to be passed to stdin of service utility or
|
||
may be empty in the simplest case. Receive block must contain list of
|
||
tags you want to receive from service. For most of utilities this is
|
||
single isc_info_svc_line:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>const
|
||
unsigned char receiveItems1[] = {isc_info_svc_line};</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">To
|
||
query information one also needs a buffer for that information:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>unsigned
|
||
char results[1024];</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">After
|
||
that preliminary steps we are ready to query service in a loop (each
|
||
line returned in a single call to query()):</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>do</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>{</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>svc->query(&status,
|
||
0, NULL, sizeof(receiveItems1), receiveItems1, sizeof(results),
|
||
results);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>}
|
||
while (printInfo(results, sizeof(results)));</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">In
|
||
this example we suppose that printInfo() function returns TRUE as
|
||
long as service returns results block containing next output line
|
||
(i.e. till end of data stream from service). Format of results block
|
||
varies from service to service, and some services like gsec produce
|
||
historical formats that are not trivial for parse – but this is out
|
||
of our scope here. A minimum working sample of printInfo() is present
|
||
in example 09.service.cpp.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Same
|
||
query method is used to retrieve information about server but in this
|
||
case query function is not invoked in a loop, i.e. buffer must be big
|
||
enough to fit all information at once. This is not too hard –
|
||
typically such calls do not return much data. As in previous case
|
||
begin with receive block placing required items in it – in our
|
||
example it's isc_info_svc_server_version:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
|
||
unsigned char receiveItems2[] = {isc_info_svc_server_version};</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Existing
|
||
from previous call results buffer may be reused. No loop is needed
|
||
here:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>svc->query(&status,
|
||
0, NULL, sizeof(receiveItems2), receiveItems2, sizeof(results),
|
||
results);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>printInfo(results,
|
||
sizeof(results));</i></font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">After
|
||
finishing with services tasks do not forget to close an interface:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>svc->detach(&status);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-top: 0.43cm; margin-bottom: 0.51cm; page-break-after: avoid">
|
||
<font face="Albany, sans-serif"><font size="5" style="font-size: 18pt">Writing
|
||
plugins.</font></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">To
|
||
write a plugin means to implement some interfaces and place your
|
||
implementation into dynamic library (.dll in windows or .so in linux)
|
||
later referenced as </font><font size="4" style="font-size: 14pt"><i>plugin
|
||
module</i></font> <font size="4" style="font-size: 14pt">or just
|
||
</font><font size="4" style="font-size: 14pt"><i>module</i></font><font size="4" style="font-size: 14pt">.
|
||
In most cases single plugin is placed</font> <font size="4" style="font-size: 14pt">into</font>
|
||
<font size="4" style="font-size: 14pt">dynamic library but in common
|
||
case multiple plugins may coexist in single dynamic library. One of
|
||
that interfaces – <a href="#PluginModule">IPluginModule</a> – is
|
||
module-wide (as more or less clear from it's name), others are per
|
||
plugin. Also each plugin module should contain special exported
|
||
entrypoint firebird_plugin() which name is defined in include file
|
||
firebird/Interfaces.h as FB_PLUGIN_ENTRY_POINT.</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">In
|
||
previous part of this text we were mostly describing how to use
|
||
existing interfaces, here main attention will be paid to implementing
|
||
interfaces yourself. Certainly to do it one can and should use
|
||
already existing interfaces both generic needed for accessing
|
||
firebird databases (already described) and some more interfaces
|
||
specifically designed for plugins.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Following
|
||
text is actively using example of database encryption plugin
|
||
examples/dbcrypt/DbCrypt.cpp. It will be good idea to compile this
|
||
sample yourself and learn it when reading later.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<h1><font size="4" style="font-size: 14pt">Implementation of plugin
|
||
module.</font></h1>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Plugins
|
||
actively interact with special firebird component called </font><font size="4" style="font-size: 14pt"><i>plugin
|
||
manager</i></font><font size="4" style="font-size: 14pt">. In
|
||
particular plugin manager should be aware what plugin modules were
|
||
loaded and must be notified if operating system tries to unload one
|
||
of that modules without explicit plugin manager command (this may
|
||
happen first of all when using embedded access – when exit() is
|
||
called in a program or main firebird library </font><font size="4" style="font-size: 14pt"><i>fbclient</i></font>
|
||
<font size="4" style="font-size: 14pt">is unloaded). Primary task of
|
||
IPluginModule interface is that notification. First of all one must
|
||
decide - how to detect that module is going to be unloaded? When
|
||
dynamic library is unloaded for some reason a lot of OS-dependent
|
||
actions is performed and some of that actions may be used to detect
|
||
this fact in the program. When writing plugins distributed with
|
||
firebird we always use invocation of destructor of global variable.
|
||
The big “plus” for this method is that it is OS independent
|
||
(though something like atexit() function maybe also used
|
||
successfully). But use of destructor makes it possible to easily
|
||
concentrate almost everything related with unload detection in single
|
||
class implementing at the same time <a href="#PluginModule">IPluginModule</a>
|
||
interface.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Minimum
|
||
implementation looks as follows:</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>class
|
||
PluginModule : public IPluginModuleImpl<PluginModule,
|
||
CheckStatusWrapper></i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>{</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>private:</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>IPluginManager*
|
||
pluginManager;</i></font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>public:</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>PluginModule()</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>:
|
||
pluginManager(NULL)</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>{
|
||
}</i></font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>~PluginModule()</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>{</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>if
|
||
(pluginManager)</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>{</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>pluginManager->unregisterModule(this);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>doClean();</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>}</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>}</i></font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>void
|
||
registerMe(IPluginManager* m)</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>{</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>pluginManager
|
||
= m;</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>pluginManager->registerModule(this);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>}</i></font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>void
|
||
doClean()</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>{</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>pluginManager
|
||
= NULL;</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>}</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>};</i></font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">The
|
||
only data member is plugin manager interface <a href="#PluginManager">IPluginManager</a>.
|
||
It's passed to registerModule() function and saved in private
|
||
variable, at the same time module is registered in plugin manager by
|
||
the call to registerModule() method with own address as a single
|
||
parameter. Variable </font><font size="4" style="font-size: 14pt"><i>pluginManager
|
||
</i></font><font size="4" style="font-size: 14pt">not only stores
|
||
pointer to interface, at the same time it serves as a flag that
|
||
module is registered. When destructor of registered module is invoked
|
||
it notifies plugin manager (yes, this is what for this class exists!)
|
||
about unexpected unload by the call to unregisterModule() passing
|
||
pointer to itself. When plugin manager is going to unload module in
|
||
regular way in first of all calls doClean() method changing module
|
||
state to unregistered and this avoiding call to unregisterModule()
|
||
when OS performs actual unload.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Implementing
|
||
plugin's interface IPluginModule we met with first interface required
|
||
to implement plugins – <a href="#PluginManager">IPluginManager</a>.
|
||
It will be actively used later, the rest of internals of this class
|
||
will hardly be required to you after copying it to your program. Just
|
||
don't forget to declare global variable of this type and call
|
||
registerMe() function from FB_PLUGIN_ENTRY_POINT.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<h1><font size="4" style="font-size: 14pt">Core interface of any
|
||
plugin.</font></h1>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Let's
|
||
start implementing plugin itself. The type of main interface depends
|
||
upon plugin type (which is obvious), but all of them are based on
|
||
common reference counted interface IPluginBase which performs common
|
||
for all plugins (and very simple) tasks. Each plugin has some (also
|
||
reference counted) object which <i>owns</i> this plugin. In order to
|
||
perform smart plugin lifetime management any plugin must be able to
|
||
store that owner information and report it to plugin manager on
|
||
request. That means that each plugin must implement two trivial
|
||
methods setOwner() and getOwner() contained in IPluginBase interface.
|
||
Type-dependent methods are certainly more interesting - they are
|
||
discussed in interfaces description part.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Let's
|
||
take a look at typical part of any plugin implementation (here I
|
||
specially use non-existent type SomePlugin):</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>class
|
||
MyPlugin : public ISomePluginImpl<MyPlugin, CheckStatusWrapper></i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>{</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>public:</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>explicit
|
||
MyPlugin(<a href="#PluginConfig">IPluginConfig</a>* cnf) throw()</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>:
|
||
config(cnf), refCounter(0), owner(NULL)</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>{</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>config->addRef();</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>}</i></font></p>
|
||
<p style="margin-bottom: 0cm; font-variant: normal; font-style: normal">
|
||
<font size="4" style="font-size: 14pt">Constructor gets as parameter
|
||
plugin configuration interface. If you are going to have you plugin
|
||
configured in some way it's good idea to save this interface in your
|
||
plugin and use it later. This will let you use common for all
|
||
firebird configuration style letting users have familiar
|
||
configuration and minimize code written. Certainly when saving any
|
||
reference counted interface it's better not forget to add reference
|
||
to it. Also set reference counter to 0 and plugin owner to NULL.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>~MyPlugin()</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>{</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>config->release();</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>}</i></font></p>
|
||
<p style="margin-bottom: 0cm; font-variant: normal; font-style: normal">
|
||
<font size="4" style="font-size: 14pt">Destructor releases config
|
||
interface. Pay attention – we do not change reference counter of
|
||
our owner cause it owns us, not we own it.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>//
|
||
IRefCounted implementation</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>int
|
||
release()</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>{</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>if
|
||
(--refCounter == 0)</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>{</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>delete
|
||
this;</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>return
|
||
0;</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>}</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>return
|
||
1;</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>}</i></font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>void
|
||
addRef()</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>{</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>++refCounter;</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>}</i></font></p>
|
||
<p style="margin-bottom: 0cm; font-variant: normal; font-style: normal">
|
||
<font size="4" style="font-size: 14pt">Absolutely typical
|
||
implementation of reference counted object.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>//
|
||
IPluginBase implementation</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>void
|
||
setOwner(IReferenceCounted* o)</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>{</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>owner
|
||
= o;</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>}</i></font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>IReferenceCounted*
|
||
getOwner()</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>{</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>return
|
||
owner;</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>}</i></font></p>
|
||
<p style="margin-bottom: 0cm; font-variant: normal; font-style: normal">
|
||
<font size="4" style="font-size: 14pt">As it was promised
|
||
implementation of IPluginBase is trivial.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>//
|
||
ISomePlugin implementation</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>//
|
||
… here go various methods required for particular plugin type</i></font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>private:</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>IPluginConfig*
|
||
config;</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>FbSampleAtomic
|
||
refCounter;</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>IReferenceCounted*
|
||
owner;</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>};</i></font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">With
|
||
this sample formal part of main plugin interface implementation is
|
||
over. After adding type-specific methods (and writing probably a
|
||
lo-o-o-ot of code to make them useful) interface is ready.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<h1><font size="4" style="font-size: 14pt">Plugin's factory.</font></h1>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">One
|
||
more interface required for plugin to work is <a href="#PluginFactory">IPluginFactory</a>.
|
||
Factory creates instances of plugin and returns them to plugin
|
||
manager. Factory typically looks this way:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>class
|
||
Factory : public IPluginFactoryImpl<Factory, CheckStatusWrapper></i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>{</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>public:</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>IPluginBase*
|
||
createPlugin(CheckStatusWrapper* status, IPluginConfig*
|
||
factoryParameter)</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>{</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>MyPlugin*
|
||
p = new MyPlugin(factoryParameter);</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>p->addRef();</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>return
|
||
p;</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>}</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>};</i></font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm; font-variant: normal; font-style: normal">
|
||
<font size="4" style="font-size: 14pt">Here attention should be payed
|
||
to the fact that even in a case when code in a function may throw
|
||
exceptions (operator new may throw in a case when memory exhausted)
|
||
one need not always manually define try/catch block –
|
||
implementation of firebird interfaces does this job for you, in
|
||
implementation of IPluginFactory it's placed into template
|
||
IPluginFactoryImpl. Take into an account that default status wrappers
|
||
perform meaning-full processing only for FbException. But if you
|
||
(that definitely makes sense if you work on some big project) define
|
||
your own wrapper you can handle any type of C++ exception and pass
|
||
useful information about it from your plugin.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<h1><font size="4" style="font-size: 14pt">Plugin module
|
||
initialization entrypoint.</font></h1>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">When
|
||
plugin manager loads plugin module it invokes module initializing
|
||
routine – the only exported from plugin function
|
||
FB_PLUGIN_ENTRY_POINT. To wrote it's code one will need two global
|
||
variables – plugin module and plugin factory. In our case that is:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>PluginModule
|
||
module;</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><i>Factory
|
||
factory;</i></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">If
|
||
you module contains more than one plugin you will need a factory per
|
||
each plugin.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">For
|
||
FB_PLUGIN_ENTRY_POINT we should not forget that it should be exported
|
||
from plugin module, and it requires taking into an account some OS
|
||
specifics. We do it using macro FB_DLL_EXPORT defined in
|
||
examples/interfaces/ifaceExamples.h. If you are sure you write plugin
|
||
only for some specific OS you can make this place a bit simpler. In
|
||
minimum case the function should register module and all factories in
|
||
plugin manager:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">extern
|
||
"C" FB_DLL_EXPORT void FB_PLUGIN_ENTRY_POINT(IMaster*
|
||
master)</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">{</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IPluginManager*
|
||
pluginManager = master->getPluginManager();</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">module.registerMe(pluginManager);</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">pluginManager->registerPluginFactory(IPluginManager::TYPE_DB_CRYPT,
|
||
"fbSampleDbCrypt", &factory);</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">}</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">First
|
||
of all we call written by us not long ago PluginModule::registerMe()
|
||
function which will saves IPluginManager for future use and registers
|
||
our plugin module. Next time to register factory (or factories in
|
||
case of multiple plugins per module) takes place. We must pass
|
||
correct plugin type (valid types are enumerated in interface
|
||
IPluginManager) and a name under which plugin will be registered. In
|
||
simple case it should match with the name of dynamic library with
|
||
plugin module. Following last rule will help you avoid configuring
|
||
your plugin manually in plugins.conf.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Pay
|
||
attention - unlike applications plugins should not use
|
||
fb_get_master_interface() to obtain IMaster. Instance, passed to
|
||
FB_PLUGIN_ENTRY_POINT, should be used instead. If you ever need
|
||
master interface in your plugin take care about saving it in this
|
||
function.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-top: 0.43cm; margin-bottom: 0.51cm; page-break-after: avoid">
|
||
<font face="Albany, sans-serif"><font size="5" style="font-size: 18pt">Interfaces:
|
||
from A to Z</font></font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">In
|
||
this glossary we do not list interfaces that are not actively used
|
||
(like IRequest, needed first of all to support legacy ISC API
|
||
requests). Same reference may be made for a number of methods (like
|
||
compileRequest() in IAttachment). For interfaces / methods, having
|
||
direct analogue in old API, that analogue is provided.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<h1><font size="4" style="font-size: 14pt">Generic interfaces.</font></h1>
|
||
<p style="margin-bottom: 0cm"><a name="Attachment"></a><font size="4" style="font-size: 14pt">Attachment
|
||
interface – replaces isc_db_handle:</font></p>
|
||
<ol>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
getInfo(StatusType* status, unsigned itemsLength, const unsigned
|
||
char* items, unsigned bufferLength, unsigned char* buffer) –
|
||
replaces isc_database_info().</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ITransaction*
|
||
startTransaction(StatusType* status, unsigned tpbLength, const
|
||
unsigned char* tpb) – partially replaces isc_start_multiple(), to
|
||
start >1 transaction <a href="#Dtc">distributed transactions
|
||
coordinator</a> should be used, also possible to <a href="#Transaction">join</a>
|
||
2 transactions into single distributed transaction.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ITransaction*
|
||
reconnectTransaction(StatusType* status, unsigned length, const
|
||
unsigned char* id) – makes it possible to connect to a transaction
|
||
in limbo. Id parameter contains transaction number in network format
|
||
of given length.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IRequest*
|
||
compileRequest(StatusType* status, unsigned blrLength, const
|
||
unsigned char* blr) – support of ISC API.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
transactRequest(StatusType* status, ITransaction* transaction,
|
||
unsigned blrLength, const unsigned char* blr, unsigned inMsgLength,
|
||
const unsigned char* inMsg, unsigned outMsgLength, unsigned char*
|
||
outMsg) – support of ISC API.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IBlob*
|
||
createBlob(StatusType* status, ITransaction* transaction, ISC_QUAD*
|
||
id, unsigned bpbLength, const unsigned char* bpb) – creates new
|
||
blob, stores it's identifier in id, replaces isc_create_blob2().</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IBlob*
|
||
openBlob(StatusType* status, ITransaction* transaction, ISC_QUAD*
|
||
id, unsigned bpbLength, const unsigned char* bpb) – opens existing
|
||
blob, replaces isc_open_blob2().</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">int
|
||
getSlice(StatusType* status, ITransaction* transaction, ISC_QUAD*
|
||
id, unsigned sdlLength, const unsigned char* sdl, unsigned
|
||
paramLength, const unsigned char* param, int sliceLength, unsigned
|
||
char* slice) - support of ISC API.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
putSlice(StatusType* status, ITransaction* transaction, ISC_QUAD*
|
||
id, unsigned sdlLength, const unsigned char* sdl, unsigned
|
||
paramLength, const unsigned char* param, int sliceLength, unsigned
|
||
char* slice) - support of ISC API.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
executeDyn(StatusType* status, ITransaction* transaction, unsigned
|
||
length, const unsigned char* dyn) - support of ISC API.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IStatement*
|
||
prepare(StatusType* status, ITransaction* tra, unsigned stmtLength,
|
||
const char* sqlStmt, unsigned dialect, unsigned flags) – replaces
|
||
isc_dsql_prepare(). Additional parameter flags makes it possible to
|
||
control what information will be preloaded from engine at once (i.e.
|
||
in single network packet for remote operation).</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ITransaction*
|
||
execute(StatusType* status, ITransaction* transaction, unsigned
|
||
stmtLength, const char* sqlStmt, unsigned dialect, IMessageMetadata*
|
||
inMetadata, void* inBuffer, IMessageMetadata* outMetadata, void*
|
||
outBuffer) – executes any SQL statement except returning multiple
|
||
rows of data. Partial analogue of isc_dsql_execute2() - in and out
|
||
XSLQDAs replaced with input and output messages with appropriate
|
||
buffers.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IResultSet*
|
||
openCursor(StatusType* status, ITransaction* transaction, unsigned
|
||
stmtLength, const char* sqlStmt, unsigned dialect, IMessageMetadata*
|
||
inMetadata, void* inBuffer, IMessageMetadata* outMetadata, const
|
||
char* cursorName, unsigned cursorFlags) – executes SQL statement
|
||
potentially returning multiple rows of data. Returns <a href="#ResultSet">ResultSet</a>
|
||
interface which should be used to fetch that data. Format of output
|
||
data is defined by outMetadata parameter, leaving it NULL default
|
||
format may be used. Parameter cursorName specifies name of opened
|
||
cursor (analogue of isc_dsql_set_cursor_name()). Parameter
|
||
cursorFlags is needed to open bidirectional cursor setting it's
|
||
value to Istatement::CURSOR_TYPE_SCROLLABLE.</font></p>
|
||
<li><p><font size="4" style="font-size: 14pt">I</font><font face="Liberation Serif, serif"><font size="4" style="font-size: 14pt">Batch*
|
||
createBatch(StatusType* status, ITransaction* transaction, unsigned
|
||
stmtLength, const char* sqlStmt, unsigned dialect, IMessageMetadata*
|
||
inMetadata, unsigned</font></font> <font face="Liberation Serif, serif"><font size="4" style="font-size: 14pt">parLength,
|
||
const unsigned char* par) – prepares sqlStmt and creates <a href="#Batch">Batch</a>
|
||
interface ready to accept multiple sets of input parameters in
|
||
inMetadata format. Leaving inMetadata</font></font> <font face="Liberation Serif, serif"><font size="4" style="font-size: 14pt">NULL
|
||
makes batch use default format for sqlStmt. Parameters block may be
|
||
passed to createBatch() making it possible to adjust batch behavior.</font></font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IEvents*
|
||
queEvents(StatusType* status, IEventCallback* callback, unsigned
|
||
length, const unsigned char* events) – replaces isc_que_events()
|
||
call. Instead callback function with void* parameter callback
|
||
interface is used.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
cancelOperation(StatusType* status, int option) – replaces
|
||
fb_cancel_operation().</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
ping(StatusType* status) – check connection status. If test fails
|
||
the only operation possible with attachment is to close it.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
detach(StatusType* status) – replaces isc_detach_database(). On
|
||
success releases interface.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
dropDatabase(StatusType* status) - replaces isc_drop_database(). On
|
||
success releases interface.</font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="Batch"></a><font size="4" style="font-size: 14pt">Batch
|
||
interface – makes it possible to process multiple sets of
|
||
parameters in single statement execution.</font></p>
|
||
<ol>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
add(StatusType* status, unsigned</font> <font size="4" style="font-size: 14pt">count,
|
||
const void* inBuffer) – adds count messages from inBuffer to the
|
||
batch. Total size of messages that can be added to the batch is
|
||
limited by TAG_BUFFER_BYTES_SIZE <a href="#Batch_PB">parameter</a>
|
||
of batch creation.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
addBlob(StatusType* status, unsigned</font> <font size="4" style="font-size: 14pt">length,
|
||
const void* inBuffer, ISC_QUAD* blobId, unsigned bpbLength, const
|
||
unsigned char* bpb) – adds single blob having length bytes from
|
||
inBuffer to the batch, blob identifier is located at blobId address.
|
||
If blob should be created with non-default parameters BPB may be
|
||
passed (format matches one used in <a href="#Attachment">Attachment</a>::createBlob).Total
|
||
size of inline blobs that can be added to the batch (including
|
||
optional BPBs, blob headers, segment sizes and taking into an
|
||
accoount alignment) is limited by TAG_BUFFER_BYTES_SIZE <a href="#Batch_PB">parameter</a>
|
||
of batch creation (affects all blob-oriented methods except
|
||
registerBlob()). </font>
|
||
</p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
appendBlobData(StatusType* status, unsigned length, const void*
|
||
inBuffer) – extend last added blob: append length bytes taken from
|
||
inBuffer address to it.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
addBlobStream(StatusType* status, unsigned length, const void*
|
||
inBuffer) – adds blob data (this can be multiple objects or part
|
||
of single blob) to the batch. Header of each blob in the stream is
|
||
aligned at getBlobAlignment() boundary and contains 3 fields: first
|
||
- 8-bytes blob identifier (in ISC_QUAD format), second - 4-bytes
|
||
length of blob, third – 4-bytes length of BPB. Blob header should
|
||
not cross boundaries of buffer in this function call. BPB data is
|
||
placed right after header, blob data goes next. Length of blob
|
||
includes BPB (if it present). All data may be distributed between
|
||
multiple addBlobStream() calls. Blob data in turn may be structured
|
||
in case of segmented blob, see chapter “<a href="#Modifying data in a batch">Modifying
|
||
data in a batch</a>”.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
registerBlob(StatusType* status, const ISC_QUAD* existingBlob,
|
||
ISC_QUAD* blobId) – makes it possible to use in batch blobs added
|
||
using standard <a href="#Blob">Blob</a> interface. This function
|
||
contains 2 ISC_QUAD* parameters, it’s important not to mix them –
|
||
second parameter (existingBlob) is a pointer to blob identifier,
|
||
already added out of batch scope, third (blobId) points to blob
|
||
identifier that will be placed in a message in this batch.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt"><a href="#BatchCompletionState">IBatchCompletionState</a>*
|
||
execute(StatusType* status, ITransaction* transaction) – execute
|
||
batch with parameters passed to it in the messages. If parameter
|
||
MULTIERROR is not set in <a href="#Batch_PB">parameters block</a>
|
||
when creating the batch execution will be stopped after first error,
|
||
in MULTIERROR mode an unlimited number of errors can happen, after
|
||
an error execution is continued from the next message. This function
|
||
returns BatchCompletionState interface that contains all requested
|
||
nformation about the results of batch execution.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
cancel(StatusType* status) – clear messages and blobs buffers,
|
||
return batch to a state it had right after creation. Notice –
|
||
being reference counted interface batch does not contain any special
|
||
function to close it, please use release() for this purposes. </font>
|
||
</p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
|
||
getBlobAlignment(StatusType* status) – returns required alignment
|
||
for the data placed into the buffer of addBlobStream().</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IMessageMetadata*
|
||
getMetadata(StatusType* status) – return format of metadata used
|
||
in batch’s messages.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
setDefaultBpb(StatusType* status, unsigned parLength, const unsigned
|
||
char* par) – sets BPB which will be used for all blobs missing
|
||
non-default BPB. Must be called before adding any message or blob to
|
||
batch.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
getInfo(StatusType* status, unsigned itemsLength, const unsigned
|
||
char* items, unsigned bufferLength, unsigned char* buffer) –
|
||
requests information about batch.</font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><a name="Batch_PB"></a><font size="4" style="font-size: 14pt">Tag
|
||
for parameters block:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">VERSION1</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Tags
|
||
for clumplets in parameters block:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">TAG_MULTIERROR
|
||
(0/1) – can have >1 message with errors</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">TAG_RECORD_COUNTS
|
||
(0/1) - per-message modified records accounting</font></p>
|
||
<p style="margin-bottom: 0cm"><a name="TAG_BUFFER_BYTES_SIZE"></a><font size="4" style="font-size: 14pt">TAG_BUFFER_BYTES_SIZE
|
||
(integer) - maximum possible buffer size on server (default 16Mb,
|
||
maximum 256Mb)</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">TAG_BLOB_POLICY
|
||
- <a href="#Batch_Blob_Policy">policy</a> used to store blobs</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">TAG_DETAILED_ERRORS
|
||
(integer) - how many vectors with detailed error info are stored in
|
||
completion state (default 64, maximum 256)</font></p>
|
||
<p style="margin-bottom: 0cm"><a name="Batch_Blob_Policy"></a><font size="4" style="font-size: 14pt">Policies
|
||
used to store blobs:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">BLOB_NONE
|
||
– inline blobs can't be used (registerBlob() works anyway)</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">BLOB_ID_ENGINE
|
||
- blobs are added one by one, IDs are generated by firebird engine</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">BLOB_ID_USER
|
||
- blobs are added one by one, IDs are generated by user</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">BLOB_STREAM
|
||
- blobs are added in a stream</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Items
|
||
accepted in getInfo() call:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">INF_BUFFER_BYTES_SIZE
|
||
– actual </font><font color="#000000"><font size="4" style="font-size: 14pt">m</font></font><font size="4" style="font-size: 14pt">aximum
|
||
possible buffer size (one set by TAG_BUFFER_BYTES_SIZE)</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">INF_DATA_BYTES_SIZE
|
||
- already added messages size</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">INF_BLOBS_BYTES_SIZE
|
||
- already added blobs size</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">INF_BLOB_ALIGNMENT
|
||
- required alignment for the BLOB data (duplicates getBlobAlignment)</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="BatchCompletionState"></a><font size="4" style="font-size: 14pt">BatchCompletionState
|
||
– disposable interface, always returned by execute() method of
|
||
<a href="#Batch">Batch</a> interface. It contains more or less
|
||
(depending upon parameters passed when <a href="#Batch">Batch</a> was
|
||
created) detailed information about the results of batch execution.</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">{</font></p>
|
||
<ol>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">uint
|
||
getSize(StatusType* status) – returns the total number of
|
||
processed messages.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">int
|
||
getState(StatusType* status, uint pos) – returns the result of
|
||
execution of message number ‘pos’. On any error with the message
|
||
this is EXECUTE_FAILED constant, value returned on success depends
|
||
upon presence of RECORD_COUNTS <a href="#Batch_PB">parameter</a> of
|
||
batch creation. When it present and has non-zero value number of
|
||
records inserted, updated or deleted during particular message
|
||
processing is returned, else SUCCESS_NO_INFO constant is returned.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">uint
|
||
findError(StatusType* status, uint pos) – finds next (starting
|
||
with pos) message which processing caused an error. When such
|
||
message is missing NO_MORE_ERRORS constant is returned. Number of
|
||
status vectors, returned in this interface, is limited by the value
|
||
of DETAILED_ERRORS <a href="#Batch_PB">parameter</a> of batch
|
||
creation.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
getStatus(StatusType* status, IStatus* to, uint pos) – returns
|
||
detailed information (full status vector) about an error that took
|
||
place when processing ‘pos’ message. In order to distinguish
|
||
between errors (in <a href="#Batch">Batch</a>::execute() or in
|
||
<a href="#BatchCompletionState">BatchCompletionState</a>::getStatus())
|
||
that status is returned in separate ‘to’ parameter unlike errors
|
||
in this call that are placed into ‘status’ parameter.</font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Special
|
||
values returned by getState():</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">EXECUTE_FAILED
|
||
- error happened when processing this message</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">SUCCESS_NO_INFO
|
||
- record update info was not collected</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Special
|
||
value returned by findError():</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">NO_MORE_ERRORS
|
||
– no more messages with errors in this batch</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="Blob"></a><font size="4" style="font-size: 14pt">Blob
|
||
interface – replaces isc_blob_handle:</font></p>
|
||
<ol>
|
||
<li value="1"><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
getInfo(StatusType* status, unsigned itemsLength, const unsigned
|
||
char* items, unsigned bufferLength, unsigned char* buffer) –
|
||
replaces isc_blob_info().</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">int
|
||
getSegment(StatusType* status, unsigned bufferLength, void* buffer,
|
||
unsigned* segmentLength) – replaces isc_get_segment(). Unlike it
|
||
never returns isc_segstr_eof and isc_segment errors (that are
|
||
actually not errors), instead returns <a href="#Completion codes">completion
|
||
codes</a> IStatus::RESULT_NO_DATA and IStatus::RESULT_SEGMENT,
|
||
normal return is IStatus::RESULT_OK.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
putSegment(StatusType* status, unsigned length, const void* buffer)
|
||
– replaces isc_put_segment().</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
cancel(StatusType* status) – replaces isc_cancel_blob(). On
|
||
success releases interface.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
close(StatusType* status) – replaces isc_close_blob(). On success
|
||
releases interface.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">int
|
||
seek(StatusType* status, int mode, int offset) – replaces
|
||
isc_seek_blob().</font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="Config"></a><font size="4" style="font-size: 14pt">Config
|
||
interface – generic configuration file interface:</font></p>
|
||
<ol>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IConfigEntry*
|
||
find(StatusType* status, const char* name) – find entry by name.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IConfigEntry*
|
||
findValue(StatusType* status, const char* name, const char* value) –
|
||
find entry by name and value.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IConfigEntry*
|
||
findPos(StatusType* status, const char* name, unsigned pos) – find
|
||
entry by name and position. If configuration file contains lines:</font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Db=DBA</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Db=DBB</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Db=DBC</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">call
|
||
to findPos(status, “Db”, 2) will return entry with value DBB.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="ConfigManager"></a><font size="4" style="font-size: 14pt">ConfigManager
|
||
interface – generic interface to access various configuration
|
||
objects:</font></p>
|
||
<ol>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
|
||
char* getDirectory(unsigned code) – returns location of
|
||
appropriate directory in current firebird instance. See codes for
|
||
this call a <a href="#Directory codes">few lines later</a>.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IFirebirdConf*
|
||
getFirebirdConf() - returns interface to access default
|
||
configuration values (from firebird.conf).</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IFirebirdConf*
|
||
getDatabaseConf(const char* dbName) - returns interface to access
|
||
db-specific configuration (takes into an account firebird.conf and
|
||
appropriate part of databases.conf).</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IConfig*
|
||
getPluginConfig(const char* configuredPlugin) – returns interface
|
||
to access named plugin configuration.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
|
||
char* getInstallDirectory() - returns directory where firebird is
|
||
installed.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
|
||
char* getRootDirectory() - returns root directory of current
|
||
instance, in single-instance case usually matches install directory.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
|
||
char* getDefaultSecurityDb() - returns default (i.e. not taking into
|
||
an account configuration files) pathname of security database, used
|
||
first of all internally to enable correct access to security
|
||
database on multi-provider server with zero configuration.</font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><a name="Directory codes"></a><font size="4" style="font-size: 14pt">Directory
|
||
codes:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">DIR_BIN
|
||
– bin (utilities like isql, gbak, gstat)</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">DIR_SBIN
|
||
– sbin (fbguard and firebird server)</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">DIR_CONF
|
||
– configuration files (firebird.conf, databases.conf, plugins.conf)</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">DIR_LIB
|
||
– lib (fbclient, ib_util)</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">DIR_INC
|
||
– include (ibase.h, firebird/Interfaces.h)</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">DIR_DOC
|
||
- documentation</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">DIR_UDF
|
||
– UDF (ib_udf, fbudf)</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">DIR_SAMPLE
|
||
- samples</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">DIR_SAMPLEDB
|
||
– samples database (employee.fdb)</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">DIR_INTL
|
||
– international libraries (fbintl)</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">DIR_MISC
|
||
– miscellaneous files (like uninstall manifest and something else)</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">DIR_SECDB
|
||
– where security database is stored (securityN.fdb)</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">DIR_MSG
|
||
– where messages file is stored (firebird.msg)</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">DIR_LOG
|
||
– where log file is stored (firebird.log)</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">DIR_GUARD
|
||
– where guardian lock is stored (fb_guard)</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">DIR_PLUGINS
|
||
– plugins directory ([lib]Engine13.{dll|so})</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="ConfigEntry"></a><font size="4" style="font-size: 14pt">ConfigEntry
|
||
interface – represents an entry (Key = Values with probably
|
||
sub-entries) in firebird configuration file:</font></p>
|
||
<ol>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
|
||
char* getName() - returns key name.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
|
||
char* getValue() - returns value as character string.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ISC_INT64
|
||
getIntValue() - treats value as integer and returns it.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_BOOLEAN
|
||
getBoolValue() - treats value as boolean and returns it.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IConfig*
|
||
getSubConfig(StatusType* status) – treats sub-entries as separate
|
||
configuration file and returns Config interface for it.</font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="DecFloat16"></a><a name="DecFloat34"></a>
|
||
<font size="4" style="font-size: 14pt">DecFloat16 / DecFloat34 –
|
||
interfaces that help to work with DECFLOAT (16 & 34 respectively)
|
||
datatypes. They have almost same set of methods with FB_DEC16
|
||
parameter replaced by FB_DEC34 for DecFloat34:</font></p>
|
||
<ol>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
toBcd(const FB_DEC16* from, int* sign, unsigned char* bcd, int* exp)
|
||
– convert decimal float value to BCD.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
toString(StatusType* status, const FB_DEC16* from, unsigned
|
||
bufferLength, char* buffer) – convert decimal float value to
|
||
string.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
fromBcd(int sign, const unsigned char* bcd, int exp, FB_DEC16* to) –
|
||
make decimal float value from BCD.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
fromString(StatusType* status, const char* from, FB_DEC16* to) –
|
||
make decimal float value from string.</font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="Dtc"></a><font size="4" style="font-size: 14pt"><font color="#000000">Dtc
|
||
</font>interface – distributed transactions coordinator. Used to
|
||
start distributed (working with 2 or more attachments) transaction.
|
||
Unlike pre-FB3 approach where distributed transaction must be started
|
||
in this way from the most beginning FB3's distributed transactions
|
||
coordinator makes it also possible to join already started
|
||
transactions into single distributed transaction.</font></p>
|
||
<ol>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ITransaction*
|
||
join(StatusType* status, ITransaction* one, ITransaction* two) –
|
||
joins 2 independent transactions into distributed transaction. On
|
||
success both transactions passed to join() are released and pointers
|
||
to them should not be used any more.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IDtcStart*
|
||
startBuilder(StatusType* status) – returns <a href="#DtcStart">DtcStart</a>
|
||
interface.</font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="DtcStart"></a><font size="4" style="font-size: 14pt">DtcStart
|
||
interface – replaces array of struct TEB (passed to
|
||
isc_start_multiple() in ISC API). This interface accumulates
|
||
attachments (and probably appropriate TPBs) for which dustributed
|
||
transaction should be started.</font></p>
|
||
<ol>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
addAttachment(StatusType* status, IAttachment* att) – adds
|
||
attachment, transaction for it will be started with default TPB.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
addWithTpb(StatusType* status, IAttachment* att, unsigned length,
|
||
const unsigned char* tpb) - adds attachment and TPB which will be
|
||
used to start transaction for this attachment.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ITransaction*
|
||
start(StatusType* status) – start distributed transaction for
|
||
accumulated attachments. On successful return DtcStart interface is
|
||
disposed automatically.</font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="EventCallback"></a><font size="4" style="font-size: 14pt">EventCallback
|
||
interface – replaces callback function used in isc_que_events()
|
||
call. Should be implemented by user to monitor events with
|
||
IAttachment::queEvents() method.</font></p>
|
||
<ol>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
eventCallbackFunction(unsigned length, const unsigned char* events)
|
||
– is called each time event happens.</font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="Events"></a><font size="4" style="font-size: 14pt">Events
|
||
interface – replaces event identifier when working with events
|
||
monitoring.</font></p>
|
||
<ol>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
cancel(StatusType* status) - cancels events monitoring started by
|
||
IAttachment::queEvents().</font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FirebirdConf
|
||
interface – access to main firebird configuration. Used for both
|
||
default configuration, set by firebird.conf, and per-database
|
||
configuration, adjusted by databases.conf. In order to speed up
|
||
access to configuration values calls accessing actual values use
|
||
integer key instead symbolic parameter name. Key is stable during
|
||
server run (i.e. plugin can get it once and than use to get
|
||
configuration value for different databases). </font>
|
||
</p>
|
||
<ol>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
|
||
getKey(const char* name) – get key for parameter name. ~0 (all
|
||
bits are 1) is returned in a case when there is no such parameter.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ISC_INT64
|
||
asInteger(unsigned key) – return value of integer parameter.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
|
||
char* asString(unsigned key) - return value of string parameter.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_BOOLEAN
|
||
asBoolean(unsigned key) - return value of boolean parameter.
|
||
Standard abbreviations (1/true/t/yes/y) are treated as “true”,
|
||
all other cases – false.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
|
||
getVersion(StatusType* status) – get version of configuration
|
||
manager associated with this interface. Different versions of
|
||
configuration manager may coexist on same server for example when
|
||
old DB engine is in use on modern server. Pay attention – keys
|
||
(see getKey()) from different versions do not match and when used
|
||
inappropriately will always return 0/nullptr/false.</font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="Int128"></a><font size="4" style="font-size: 14pt">Int128
|
||
interfaces that help to work with 128-bit integers (used as base type
|
||
for numeric and decimal with precision > 18).</font></p>
|
||
<ol>
|
||
<li value="1"><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
toString(StatusType* status, const FB_I128* from, int scale,
|
||
unsigned bufferLength, char* buffer) – convert 128-bit integer
|
||
value to string taking scale into an account.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
fromString(StatusType* status, int scale, const char* from, FB_I128*
|
||
to) – make 128-bit integer value from string taking scale into an
|
||
account.</font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="Master"></a><font size="4" style="font-size: 14pt">Master
|
||
interface – main interface from which start all operations with
|
||
firebird API.</font></p>
|
||
<ol>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IStatus*
|
||
getStatus() - get instance if <a href="#Status">Status</a>
|
||
interface.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IProvider*
|
||
getDispatcher() - get instance of <a href="#Provider">Provider</a>
|
||
interface, implemented by yValve (main provider instance).</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IPluginManager*
|
||
getPluginManager() - get instance of <a href="#PluginManager">PluginManager</a>
|
||
interface.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ITimerControl*
|
||
getTimerControl() - get instance of <a href="#TimerControl">TimerControl</a>
|
||
interface.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IDtc*
|
||
getDtc() - get instance of <a href="#Dtc">Dtc</a> interface.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IUtil*
|
||
getUtilInterface() - get instance of <a href="#Util">Util</a>
|
||
interface.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IConfigManager*
|
||
getConfigManager() - get instance of <a href="#ConfigManager">ConfigManager</a>
|
||
interface.</font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="MessageMetadata"></a><font size="4" style="font-size: 14pt">MessageMetadata
|
||
interface – partial analogue of XSQLDA (does not contain message
|
||
data, only message format info is present). Used in a calls related
|
||
with execution of SQL statements.</font></p>
|
||
<ol>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
|
||
getCount(StatusType* status) – returns number of fields/parameters
|
||
in a message. In all calls, containing index parameter, it's value
|
||
should be: 0 <= index < getCount().</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
|
||
char* getField(StatusType* status, unsigned index) – returns field
|
||
name.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
|
||
char* getRelation(StatusType* status, unsigned index) – returns
|
||
relation name (from which given field is selected).</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
|
||
char* getOwner(StatusType* status, unsigned index) - returns
|
||
relation's owner name.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
|
||
char* getAlias(StatusType* status, unsigned index) - returns field
|
||
alias.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
|
||
getType(StatusType* status, unsigned index) - returns field SQL
|
||
type.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_BOOLEAN
|
||
isNullable(StatusType* status, unsigned index) - returns true if
|
||
field is nullable.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">int
|
||
getSubType(StatusType* status, unsigned index) - returns blof field
|
||
subtype (0 – binary, 1 – text, etc.).</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
|
||
getLength(StatusType* status, unsigned index) - returns maximum
|
||
field length.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">int
|
||
getScale(StatusType* status, unsigned index) - returns scale factor
|
||
for numeric field.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
|
||
getCharSet(StatusType* status, unsigned index) - returns character
|
||
set for character field and text blob.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
|
||
getOffset(StatusType* status, unsigned index) - returns offset of
|
||
field data in message buffer (use it to access data in message
|
||
buffer).</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
|
||
getNullOffset(StatusType* status, unsigned index) - returns offset
|
||
of null indicator for a field in message buffer.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IMetadataBuilder*
|
||
getBuilder(StatusType* status) - returns <a href="#MessageMetadata">MetadataBuilder</a>
|
||
interface initialized with this message metadata.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
|
||
getMessageLength(StatusType* status) - returns length of message
|
||
buffer (use it to allocate memory for the buffer).</font></p>
|
||
<li><p><font face="Liberation Serif, serif"><font size="4" style="font-size: 14pt">unsigned
|
||
getAlignment(StatusType* status) – returns alignment required for
|
||
message buffer.</font></font></p>
|
||
<li><p><font face="Liberation Serif, serif"><font size="4" style="font-size: 14pt">unsigned</font></font>
|
||
<font face="Liberation Serif, serif"><font size="4" style="font-size: 14pt">getAlignedLength(StatusType*
|
||
status) – returns length of message buffer taking into an account
|
||
alignment requirements (use it to allocate memory for an array of
|
||
buffers and navigate through that array).</font></font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="MetadataBuilder"></a><font size="4" style="font-size: 14pt">MetadataBuilder
|
||
interface – makes it possible to coerce datatypes in existing
|
||
message or construct metadata from the beginning.</font></p>
|
||
<ol>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
setType(StatusType* status, unsigned index, unsigned type) – set
|
||
SQL type of a field.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
setSubType(StatusType* status, unsigned index, int subType) – set
|
||
blof field subtype.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
setLength(StatusType* status, unsigned index, unsigned length) –
|
||
set maximum length of character field.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
setCharSet(StatusType* status, unsigned index, unsigned charSet) –
|
||
set character set for character field and text blob.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
setScale(StatusType* status, unsigned index, unsigned scale) – set
|
||
scale factor for numeric field </font>
|
||
</p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
truncate(StatusType* status, unsigned count) – truncate message to
|
||
contain not more than count fields.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
moveNameToIndex(StatusType* status, const char* name, unsigned
|
||
index) – reorganize fields in a message – move field “name”
|
||
to given position.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
remove(StatusType* status, unsigned index) – remove field.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
|
||
addField(StatusType* status) – add field.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IMessageMetadata*
|
||
getMetadata(StatusType* status) – get <a href="#10. MessageMetadata">MessageMetadata</a>
|
||
interface built by this builder.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font face="Liberation Serif, serif"><font size="4" style="font-size: 14pt">void
|
||
setField(StatusType* status, uint index, const string field) – set
|
||
name of a field / column.</font></font></p>
|
||
<li><p style="margin-bottom: 0cm"><font face="Liberation Serif, serif"><font size="4" style="font-size: 14pt">void
|
||
setRelation(StatusType* status, uint index, const string relation) –
|
||
set name of the relation from which the field was selected.</font></font></p>
|
||
<li><p style="margin-bottom: 0cm"><font face="Liberation Serif, serif"><font size="4" style="font-size: 14pt">void
|
||
setOwner(StatusType* status, uint index, const string owner) – set
|
||
name of that relation owner.</font></font></p>
|
||
<li><p style="margin-bottom: 0cm"><font face="Liberation Serif, serif"><font size="4" style="font-size: 14pt">void
|
||
setAlias(StatusType* status, uint index, const string alias) – set
|
||
alias name of the field in related statement.</font></font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="OffsetsCallback"></a><font size="4" style="font-size: 14pt">OffsetsCallback
|
||
interface:</font></p>
|
||
<ol>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">setOffset(StatusType*
|
||
status, unsigned index, unsigned offset, unsigned nullOffset) –
|
||
notifies that offsets for field/parameter number “index” should
|
||
be set to passed values. Should be implemented by user when
|
||
implementing <a href="#MessageMetadata">MessageMetadata</a>
|
||
interface and using <a href="#Util">Util</a>::setOffsets().</font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="PluginConfig"></a><font size="4" style="font-size: 14pt">PluginConfig
|
||
interface – passed to plugin's factory when plugin instance (with
|
||
particular configuration) to be created.</font></p>
|
||
<ol>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
|
||
char* getConfigFileName() - recommended file name where
|
||
configuration for plugin is expected to be stored.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IConfig*
|
||
getDefaultConfig(StatusType* status) – plugin configuration loaded
|
||
with default rules.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IFirebirdConf*
|
||
getFirebirdConf(StatusType* status) – master firebird
|
||
configuration taking into an account per-database settings for a
|
||
database with which will work new instance of plugin.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
setReleaseDelay(StatusType* status, ISC_UINT64 microSeconds) –
|
||
used by plugin to configure recommended delay during which plugin
|
||
module will not be unloaded by plugin manager after release of last
|
||
plugin instance from that module.</font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="PluginFactory"></a><font size="4" style="font-size: 14pt">PluginFactory
|
||
interface – should be implemented by plugin author when writing
|
||
plugin.</font></p>
|
||
<ol>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IPluginBase*
|
||
createPlugin(StatusType* status, IPluginConfig* factoryParameter) –
|
||
creates new instance of plugin with passed recommended
|
||
configuration.</font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="PluginManager"></a><font size="4" style="font-size: 14pt">PluginManager
|
||
interface – API of plugin manager.</font></p>
|
||
<ol>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
registerPluginFactory(unsigned pluginType, const char* defaultName,
|
||
IPluginFactory* factory) – registers named factory of plugins of
|
||
given type.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
registerModule(IPluginModule* cleanup) – registers plugin module.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
unregisterModule(IPluginModule* cleanup) – unregisters plugin
|
||
module (in case of unexpected unload by OS).</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IPluginSet*
|
||
getPlugins(StatusType* status, unsigned pluginType, const char*
|
||
namesList, IFirebirdConf* firebirdConf) – returns PluginSet
|
||
interface providing access to list of plugins of given type. Names
|
||
of plugins to be included are taken from namesList, when missing
|
||
(NULL) – from configuration setting for given pluginType. If
|
||
firebirdConf parameter is specified it is used for all configuration
|
||
purporses (including getting list of plugins and passing to
|
||
<a href="#PluginFactory">PluginFactory</a>::createPlugin() method),
|
||
if missing (NULL) – default configuration (from firebird.conf) is
|
||
used.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IConfig*
|
||
getConfig(StatusType* status, const char* filename) – returns
|
||
Config interface for given configuration file name. Can be used by
|
||
plugins to access configuration files with standard format but
|
||
non-default name.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
releasePlugin(IPluginBase* plugin) – release given plugin. Should
|
||
be used for plugins instead simple release() due to need to perform
|
||
additional actions with plugin owner before actual release.</font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Constants
|
||
defined by PluginManager interface (plugin types):</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">TYPE_PROVIDER</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">TYPE_AUTH_SERVER</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">TYPE_AUTH_CLIENT</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">TYPE_AUTH_USER_MANAGEMENT</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">TYPE_EXTERNAL_ENGINE</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">TYPE_TRACE</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">TYPE_WIRE_CRYPT</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">TYPE_DB_CRYPT</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">TYPE_KEY_HOLDER</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="PluginModule"></a><font size="4" style="font-size: 14pt">PluginModule
|
||
interface – represents plugin module (dynamic library). Should be
|
||
implemented by plugin author in each plugin module (one instance per
|
||
module).</font></p>
|
||
<ol>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
doClean() - called by plugin manager before normal unload of plugin
|
||
module.</font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">PluginSet
|
||
interface – represents set of plugins of given type. Typically used
|
||
by internal firebird code but recommended for use in plugins loading
|
||
other plugins.</font></p>
|
||
<ol>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
|
||
char* getName() - get name of current plugin in a set.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
|
||
char* getModuleName() - get name of a module of current plugin in a
|
||
set (in simple case matches plugin name).</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IPluginBase*
|
||
getPlugin(StatusType* status) – get an instance of current plugin,
|
||
returned interface should be casted to main interface of plugin of
|
||
requested in <a href="#PluginManager">PluginManager</a>::getPlugins()
|
||
type. Returns NULL if set does not contain any more plugins.
|
||
Reference counter of plugin, returned by this function, is
|
||
incremented on return – do not forget to use releasePlugin()
|
||
method of <a href="#PluginManager">PluginManager</a> for plugins
|
||
returned by this method.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
next(StatusType* status) – make set to switch to next plugin from
|
||
the list.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
set(StatusType* status, const char* list) – reset interface: make
|
||
it work with list of plugins provided by list parameter. Type of
|
||
plugins remains unchanged.</font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="Provider"></a><font size="4" style="font-size: 14pt">Provider
|
||
interface – main interface to start database / service access.</font></p>
|
||
<ol>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IAttachment*
|
||
attachDatabase(StatusType* status, const char* fileName, unsigned
|
||
dpbLength, const unsigned char* dpb) – replaces
|
||
isc_attach_database().</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IAttachment*
|
||
createDatabase(StatusType* status, const char* fileName, unsigned
|
||
dpbLength, const unsigned char* dpb) – replaces
|
||
isc_create_database().</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IService*
|
||
attachServiceManager(StatusType* status, const char* service,
|
||
unsigned spbLength, const unsigned char* spb) – replaces
|
||
isc_service_attach().</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
shutdown(StatusType* status, unsigned timeout, const int reason) –
|
||
replaces fb_shutdown().</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
setDbCryptCallback(StatusType* status, ICryptKeyCallback*
|
||
cryptCallback) – sets database encryption callback interface that
|
||
will be used for following database and service attachments. See …
|
||
for details.</font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="ResultSet"></a><font size="4" style="font-size: 14pt">ResultSet
|
||
interface – replaces (with extended functionality) some functions
|
||
of isc_stmt_handle. This interface is returned by openCursor() call
|
||
in <a href="#Attachment">IAttachment</a> or <a href="#Statement">IStatement</a>.
|
||
All fetch calls except fetchNext() work only for bidirectional
|
||
(opened with CURSOR_TYPE_SCROLLABLE flag) result set.</font></p>
|
||
<ol>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">int
|
||
fetchNext(StatusType* status, void* message) – fetch next record,
|
||
replaces isc_dsql_fetch(). This method (and other fetch methods)
|
||
returns <a href="#Completion codes">completion code</a>
|
||
Status::RESULT_NO_DATA when EOF is reached, Status::RESULT_OK on
|
||
success.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">int
|
||
fetchPrior(StatusType* status, void* message) – fetch previous
|
||
record.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">int
|
||
fetchFirst(StatusType* status, void* message) – fetch first
|
||
record.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">int
|
||
fetchLast(StatusType* status, void* message) – fetch last record.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">int
|
||
fetchAbsolute(StatusType* status, int position, void* message) –
|
||
fetch record by it's absolute position in result set.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">int
|
||
fetchRelative(StatusType* status, int offset, void* message) –
|
||
fetch record by position relative to current.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_BOOLEAN
|
||
isEof(StatusType* status) – check for EOF.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_BOOLEAN
|
||
isBof(StatusType* status) – check for BOF.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IMessageMetadata*
|
||
getMetadata(StatusType* status) – get metadata for messages in
|
||
result set, specially useful when result set is opened by
|
||
<a href="#Attachment">IAttachment</a>::openCursor() call with NULL
|
||
output metadata format parameter (this is the only way to obtain
|
||
message format in this case).</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
close(StatusType* status) – close result set, releases interface
|
||
on success.</font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="Service"></a><font size="4" style="font-size: 14pt">Service
|
||
interface – replaces isc_svc_handle.</font></p>
|
||
<ol>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
detach(StatusType* status) – close attachment to services manager,
|
||
on success releases interface. Replaces isc_service_detach().</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
query(StatusType* status, unsigned sendLength, const unsigned char*
|
||
sendItems, unsigned receiveLength, const unsigned char*
|
||
receiveItems, unsigned bufferLength, unsigned char* buffer) – send
|
||
and request information to/from service, with different receiveItems
|
||
may be used for both running services and to obtain various
|
||
server-wide information. Replaces isc_service_query().</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
start(StatusType* status, unsigned spbLength, const unsigned char*
|
||
spb) – start utility in services manager. Replaces
|
||
isc_service_start().</font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="Statement"></a><font size="4" style="font-size: 14pt">Statement
|
||
interface – replaces (partially) isc_stmt_handle.</font></p>
|
||
<ol>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
getInfo(StatusType* status, unsigned itemsLength, const unsigned
|
||
char* items, unsigned bufferLength, unsigned char* buffer) –
|
||
replaces isc_dsql_sql_info().</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
|
||
getType(StatusType* status) – statement type, currently can be
|
||
found only in firebird sources in dsql/dsql.h.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
|
||
char* getPlan(StatusType* status, FB_BOOLEAN detailed) – returns
|
||
statement execution plan.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ISC_UINT64
|
||
getAffectedRecords(StatusType* status) – returns number of records
|
||
affected by statement.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IMessageMetadata*
|
||
getInputMetadata(StatusType* status) – returns parameters
|
||
metadata.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IMessageMetadata*
|
||
getOutputMetadata(StatusType* status) – returns output values
|
||
metadata.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ITransaction*
|
||
execute(StatusType* status, ITransaction* transaction,
|
||
IMessageMetadata* inMetadata, void* inBuffer, IMessageMetadata*
|
||
outMetadata, void* outBuffer) – executes any SQL statement except
|
||
returning multiple rows of data. Partial analogue of
|
||
isc_dsql_execute2() - in and out XSLQDAs replaced with input and
|
||
output messages with appropriate buffers.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font face="Liberation Serif, serif"><font size="4" style="font-size: 14pt">IResultSet*
|
||
openCursor(StatusType* status, ITransaction* transaction,
|
||
IMessageMetadata* inMetadata, void* inBuffer, IMessageMetadata*
|
||
outMetadata, unsigned flags) – executes SQL statement potentially
|
||
returning multiple rows of data. Returns <a href="#ResultSet">ResultSet</a>
|
||
interface which should be used to fetch that data. Format of output
|
||
data is defined by outMetadata parameter, leaving it NULL default
|
||
format may be used. Parameter flags is needed to open bidirectional
|
||
cursor setting it's value to Istatement::CURSOR_TYPE_SCROLLABLE.</font></font></p>
|
||
<li><p style="margin-bottom: 0cm"><font face="Liberation Serif, serif"><font size="4" style="font-size: 14pt">IBatch*
|
||
createBatch(StatusType* status, IMessageMetadata* inMetadata, uint
|
||
parLength, const uchar* par) – creates <a href="#Batch">Batch</a>
|
||
interface to SQL statement with input parameters making it possible
|
||
to execute that statement with multiple sets of parameters. Format
|
||
of input data is defined by inMetadata parameter, leaving it NULL
|
||
makes batch use default format from this interface. Parameters block
|
||
may be passed to createBatch() making it possible to adjust batch
|
||
behavior.</font></font></p>
|
||
<li><p style="margin-bottom: 0cm"><font face="Liberation Serif, serif"><font size="4" style="font-size: 14pt">void
|
||
setCursorName(StatusType* status, const char* name) – replaces
|
||
isc_dsql_set_cursor_name(). </font></font>
|
||
</p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
free(StatusType* status) – free statement, releases interface on
|
||
success.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
|
||
getFlags(StatusType* status) – returns <a href="#Values returned by getFlags">flags</a>
|
||
describing how this statement should be executed, simplified
|
||
replacement of getType() method.</font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Constants
|
||
defined by Statement interface:</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IAttachment::prepare()
|
||
flags:</font></p>
|
||
<p style="margin-left: 0.96cm; text-indent: -0.02cm; margin-bottom: 0cm; page-break-before: auto; page-break-after: auto">
|
||
<font size="4" style="font-size: 14pt">PREPARE_PREFETCH_NONE –
|
||
constant to pass no flags, 0 value.</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">The
|
||
following flags may be OR-ed to get desired set of flags:</font></p>
|
||
<ol>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">PREPARE_PREFETCH_TYPE</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">PREPARE_PREFETCH_INPUT_PARAMETERS</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">PREPARE_PREFETCH_OUTPUT_PARAMETERS</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">PREPARE_PREFETCH_LEGACY_PLAN</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">PREPARE_PREFETCH_DETAILED_PLAN</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">PREPARE_PREFETCH_AFFECTED_RECORDS</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">PREPARE_PREFETCH_FLAGS
|
||
(flags returned by getFlags() method)</font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Frequently
|
||
used combinations of flags:</font></p>
|
||
<ol>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">PREPARE_PREFETCH_METADATA</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">PREPARE_PREFETCH_ALL
|
||
</font>
|
||
</p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="Values returned by getFlags"></a>
|
||
<font size="4" style="font-size: 14pt">Values returned by getFlags()
|
||
method: </font>
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FLAG_HAS_CURSOR
|
||
– use openCursor() to execute this statement, not execute()</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FLAG_REPEAT_EXECUTE
|
||
– when prepared statement may be executed many times with different
|
||
parameters</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="Flags passed to openCursor"></a>
|
||
<font size="4" style="font-size: 14pt">Flags passed to openCursor():</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">CURSOR_TYPE_SCROLLABLE
|
||
– open bidirectional cursor.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="Status"></a><font size="4" style="font-size: 14pt">Status
|
||
interface – replaces ISC_STATUS_ARRAY. Functionality is extended –
|
||
Status has separate access to errors and warnings vectors, can hold
|
||
vectors of unlimited length, itself stores strings used in vectors
|
||
avoiding need in circular strings buffer. In C++ Status is always
|
||
used under status wrapper, C++ API provides two different <a href="#Status Wrapper">wrappers</a>
|
||
having different behavior when error is returned from API call.
|
||
Interface is on purpose minimized (methods like convert it to text
|
||
are moved to <a href="#Util">Util</a> interface) in order to simplify
|
||
it's implementation by users when needed.</font></p>
|
||
<ol>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
init() - cleanup interface, set it to initial state.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
|
||
getState() - get current state of interface, returns <a href="#returned by getState">state
|
||
flags</a>, may be OR-ed.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
setErrors2(unsigned length, const intptr_t* value) – set contents
|
||
of errors vector with length explicitly specified in a call.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
setWarnings2(unsigned length, const intptr_t* value) – set
|
||
contents of warnings vector with length explicitly specified in a
|
||
call.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
setErrors(const intptr_t* value) – set contents of errors vector,
|
||
length is defined by value context.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
setWarnings(const intptr_t* value) – set contents of warnings
|
||
vector, length is defined by value context.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
|
||
intptr_t* getErrors() - get errors vector.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
|
||
intptr_t* getWarnings() - get warnings vector.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IStatus*
|
||
clone() - create clone of current interface.</font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Constants
|
||
defined by Status interface:</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="returned by getState"></a><font size="4" style="font-size: 14pt">Flags
|
||
set in the value, returned by getState() method:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">STATE_WARNINGS</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">STATE_ERRORS</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="Completion codes"></a><font size="4" style="font-size: 14pt">Completion
|
||
codes:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">RESULT_ERROR</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">RESULT_OK</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">RESULT_NO_DATA</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">RESULT_SEGMENT</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="Timer"></a><font size="4" style="font-size: 14pt">Timer
|
||
interface – user timer. Callback interface which should be
|
||
implemented by user to use firebird timer.</font></p>
|
||
<ol>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
handler() - method is called when timer rings (or when server is
|
||
shutting down).</font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="TimerControl"></a><font size="4" style="font-size: 14pt">TimerControl
|
||
interface – very simple and not too precise implementation of
|
||
timer. Arrived here because existing timers are very much OS
|
||
dependent and may be used in programs that require to be portable and
|
||
do not need really high precision timer. Particularly execution of
|
||
given timer may be delayed if another one has not completed at the
|
||
moment when given timer should alarm.</font></p>
|
||
<ol>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
start(StatusType* status, ITimer* timer, ISC_UINT64 microSeconds) –
|
||
start <a href="#Timer">ITimer</a> to alarm after given delay (in
|
||
microseconds, 10</font><sup><font size="4" style="font-size: 14pt">-6</font></sup>
|
||
<font size="4" style="font-size: 14pt">seconds). Timer will be waked
|
||
up only once after this call.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
stop(StatusType* status, ITimer* timer) – stop <a href="#Timer">ITimer</a>.
|
||
It's not an error to stop not started timer thus avoiding problems
|
||
with races between stop() and timer alarm.</font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="Transaction"></a><font size="4" style="font-size: 14pt">Transaction
|
||
interface – replaces isc_tr_handle.</font></p>
|
||
<ol>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
getInfo(StatusType* status, unsigned itemsLength, const unsigned
|
||
char* items, unsigned bufferLength, unsigned char* buffer) –
|
||
replaces isc_transaction_info().</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
prepare(StatusType* status, unsigned msgLength, const unsigned char*
|
||
message) – replaces isc_prepare_transaction2(), with zero
|
||
msgLength behaves like isc_prepare_transaction() automatically
|
||
generating appropriate message.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
commit(StatusType* status) – replaces isc_commit_transaction().</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
commitRetaining(StatusType* status) – replaces
|
||
isc_commit_retaining().</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
rollback(StatusType* status) – replaces
|
||
isc_rollback_transaction().</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
rollbackRetaining(StatusType* status) – replaces
|
||
isc_rollback_retaining().</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
disconnect(StatusType* status) – replaces
|
||
fb_disconnect_transaction().</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ITransaction*
|
||
join(StatusType* status, ITransaction* transaction) – joins
|
||
current transaction and passed as parameter transaction into single
|
||
distributed transaction (using <a href="#Dtc">Dtc</a>). On success
|
||
both current transaction and passed as parameter transaction are
|
||
released and should not be used any more.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ITransaction*
|
||
validate(StatusType* status, IAttachment* attachment) – this
|
||
method is used to support distributed transactions coordinator.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ITransaction*
|
||
enterDtc(StatusType* status) – this method is used to support
|
||
distributed transactions coordinator.</font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="VersionCallback"></a><font size="4" style="font-size: 14pt">VersionCallback
|
||
interface – callback for <a href="#Util">Util</a>::getFbVersion().</font></p>
|
||
<ol>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
callback(StatusType* status, const char* text) – called by
|
||
firebird engine for each line in multiline version report. Makes it
|
||
possible to print that lines one by one, place them into message box
|
||
in any GUI, etc.</font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="Util"></a><font size="4" style="font-size: 14pt">Util
|
||
interface – various helper methods required here or there.</font></p>
|
||
<ol>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
getFbVersion(StatusType* status, IAttachment* att, IVersionCallback*
|
||
callback) – produce long and beautiful report about firebird
|
||
version used. It may be seen in ISQL when invoked with -Z switch.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
loadBlob(StatusType* status, ISC_QUAD* blobId, IAttachment* att,
|
||
ITransaction* tra, const char* file, FB_BOOLEAN txt) – load blob
|
||
from file.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
dumpBlob(StatusType* status, ISC_QUAD* blobId, IAttachment* att,
|
||
ITransaction* tra, const char* file, FB_BOOLEAN txt) – save blob
|
||
to file.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
getPerfCounters(StatusType* status, IAttachment* att, const char*
|
||
countersSet, ISC_INT64* counters) – get statistics for given
|
||
attachment.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IAttachment*
|
||
executeCreateDatabase(StatusType* status, unsigned stmtLength, const
|
||
char* creatDBstatement, unsigned dialect, FB_BOOLEAN*
|
||
stmtIsCreateDb) – execute “CREATE DATABASE ...” statement –
|
||
ISC trick with NULL statement handle does not work with interfaces.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
decodeDate(ISC_DATE date, unsigned* year, unsigned* month, unsigned*
|
||
day) – replaces isc_decode_sql_date().</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
decodeTime(ISC_TIME time, unsigned* hours, unsigned* minutes,
|
||
unsigned* seconds, unsigned* fractions) – replaces
|
||
isc_decode_sql_time().</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ISC_DATE
|
||
encodeDate(unsigned year, unsigned month, unsigned day) – replaces
|
||
isc_encode_sql_date().</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ISC_TIME
|
||
encodeTime(unsigned hours, unsigned minutes, unsigned seconds,
|
||
unsigned fractions) – replaces isc_encode_sql_time().</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
|
||
formatStatus(char* buffer, unsigned bufferSize, IStatus* status) –
|
||
replaces fb_interpret(). Size of buffer, passed into this method,
|
||
should not be less than 50 bytes.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
|
||
getClientVersion() – returns integer, containing major version in
|
||
byte 0 and minor version in byte 1.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font color="#000000"><font size="4" style="font-size: 14pt">IXpbBuilder*
|
||
getXpbBuilder(StatusType* status, unsigned kind, const unsigned
|
||
char* buf, unsigned len) – returns <a href="#XpbBuilder">XpbBuilder</a>
|
||
interface. Valid <a href="#Valid builder types">kinds</a> are
|
||
enumerated in <a href="#XpbBuilder">XpbBuilder</a>.</font></font></p>
|
||
<li><p style="margin-bottom: 0cm"><font color="#000000"><font size="4" style="font-size: 14pt">unsigned
|
||
setOffsets(StatusType* status, IMessageMetadata* metadata,
|
||
IOffsetsCallback* callback) – sets valid offsets in
|
||
<a href="#MessageMetadata">MessageMetadata</a>. Performs calls to
|
||
callback in <a href="#OffsetsCallback">OffsetsCallback</a> for each
|
||
field/parameter.</font></font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IDecFloat16*
|
||
getDecFloat16(StatusType* status) – access <a href="#DecFloat16">DecFloat16</a>
|
||
interface.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IDecFloat34*
|
||
getDecFloat34(StatusType* status) – access <a href="#DecFloat34">DecFloat34</a>
|
||
interface.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
decodeTimeTz(StatusType* status, const ISC_TIME_TZ* timeTz,
|
||
unsigned* hours, unsigned* minutes, unsigned* seconds, unsigned*</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">fractions,
|
||
unsigned timeZoneBufferLength, char* timeZoneBuffer) – decode time
|
||
taking time zone into an account.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
decodeTimeStampTz(StatusType* status, const ISC_TIMESTAMP_TZ*
|
||
timeStampTz, unsigned* year, unsigned* month, unsigned* day,
|
||
unsigned* hours, unsigned* minutes, unsigned* seconds, unsigned*
|
||
fractions, unsigned timeZoneBufferLength, char* timeZoneBuffer) -
|
||
decode timestamp taking time zone into an account.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
encodeTimeTz(StatusType* status, ISC_TIME_TZ* timeTz, unsigned
|
||
hours, unsigned minutes, unsigned seconds, unsigned fractions, const
|
||
char* timeZone) – encode time taking time zone into an account.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
encodeTimeStampTz(StatusType* status, ISC_TIMESTAMP_TZ* timeStampTz,
|
||
unsigned year, unsigned month, unsigned day, unsigned hours,
|
||
unsigned minutes, unsigned seconds, unsigned fractions, const char*
|
||
timeZone) – encode timestamp taking time zone into an account.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IInt128*
|
||
getInt128(Status status) – access <a href="#Int128">Int128</a>
|
||
interface.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
decodeTimeTzEx(Status status, const ISC_TIME_TZ_EX* timeTz, uint*
|
||
hours, uint* minutes, uint* seconds, uint* fractions, uint
|
||
timeZoneBufferLength, string timeZoneBuffer) – decode time taking
|
||
extended time zone into an account.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
decodeTimeStampTzEx(Status status, const ISC_TIMESTAMP_TZ_EX*
|
||
timeStampTz, uint* year, uint* month, uint* day, uint* hours, uint*
|
||
minutes, uint* seconds, uint* fractions, uint timeZoneBufferLength,
|
||
string timeZoneBuffer) – decode timestamp taking extended time
|
||
zone into an account.</font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="XpbBuilder"></a><font size="4" style="font-size: 14pt">XpbBuilder
|
||
methods:</font></p>
|
||
<ol>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
clear(StatusType* status) – reset builder to empty state.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
removeCurrent(StatusType* status) – removes current clumplet.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
insertInt(StatusType* status, unsigned char tag, int value) –
|
||
inserts a clumplet with value representing integer in network
|
||
format.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
insertBigInt(StatusType* status, unsigned char tag, ISC_INT64 value)
|
||
– inserts a clumplet with value representing integer in network
|
||
format.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
insertBytes(StatusType* status, unsigned char tag, const void*
|
||
bytes, unsigned length) - inserts a clumplet with value containing
|
||
passed bytes.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
insertTag(StatusType* status, unsigned char tag) – inserts a
|
||
clumplet without a value.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_BOOLEAN
|
||
isEof(StatusType* status) – checks that there is no current
|
||
clumplet.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
moveNext(StatusType* status) – moves to next clumplet.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
rewind(StatusType* status) – moves to first clumplet.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_BOOLEAN
|
||
findFirst(StatusType* status, unsigned char tag) – finds first
|
||
clumplet with given tag.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_BOOLEAN
|
||
findNext(StatusType* status) – finds next clumplet with given tag.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
|
||
char getTag(StatusType* status) – returns tag for current
|
||
clumplet.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
|
||
getLength(StatusType* status) – returns length of current clumplet
|
||
value.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">int
|
||
getInt(StatusType* status) – returns value of current clumplet as
|
||
integer.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ISC_INT64
|
||
getBigInt(StatusType* status) – returns value of current clumplet
|
||
as 64-bit integer.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
|
||
char* getString(StatusType* status) – returns value of current
|
||
clumplet as pointer to zero-terminated string (pointer is valid till
|
||
next call to this method).</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
|
||
unsigned char* getBytes(StatusType* status) – returns value of
|
||
current clumplet as pointer to unsigned char.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
|
||
getBufferLength(StatusType* status) – returns length of parameters
|
||
block.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
|
||
unsigned char* getBuffer(StatusType* status) – returns pointer to
|
||
parameters block.</font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Constants
|
||
defined by XpbBuilder interface:</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="Valid builder types"></a><font size="4" style="font-size: 14pt">Valid
|
||
builder types:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">BATCH
|
||
(IBatch parameters block)</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">BPB
|
||
(BLOB parameters block)</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">DPB
|
||
(database attachment parameters block)</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">SPB_ATTACH
|
||
(service attachment parameters block)</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">SPB_START
|
||
(start service parameters)</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">SPB_SEND
|
||
(send items in <a href="#Service">IService</a>::query())</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">SPB_RECEIVE
|
||
(receive items in <a href="#Service">IService</a>::query())</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">SPB_RESPONSE
|
||
(response from <a href="#Service">IService</a>::query())</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">TPB
|
||
(transaction parameters block)</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<h1><font size="4" style="font-size: 14pt">Plugin, encrypting data
|
||
transferred over the wire.</font></h1>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Algorithms
|
||
performing encryption of data for different purposes are well known
|
||
for many years. The only “little” typical problem remaining is
|
||
where to get the top secret key to be used by that algorithm. Luckily
|
||
for network traffic encryption there is one good solution – unique
|
||
encryption key should be generated by authentication plugin. At least
|
||
default SRP plugin can produce such a key. And that key is resistant
|
||
to attacks, including man-in-the-middle. Therefore was chosen a
|
||
method of providing keys for wire crypt plugin: get it from
|
||
authentication plugin. (In case when used authentication plugin can
|
||
not provide a key a pseudo-plugin may be added in AuthClient and
|
||
AuthServer lists to produce keys, something like two asymmetric
|
||
private/public pairs.) </font>
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">CryptKey
|
||
interface is used to store a key provided by authentication plugin
|
||
and pass it to wire crypt plugin. This interface should be used as
|
||
follows – when server or client authentication plugin is ready to
|
||
provide a key it asks <a href="#ServerBlock">ServerBlock</a> or
|
||
<a href="#ClientBlock">ClientBlock</a> to produce new CryptKey
|
||
interface and stores a key in it. Appropriate for <a href="#WireCryptPlugin">WireCryptPlugin</a>
|
||
type of key will be selected by firebird and passed to that
|
||
interface.</font></p>
|
||
<ol>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
setSymmetric(StatusType* status, const char* type, unsigned
|
||
keyLength, const void* key) – make it store symmetric key of given
|
||
type.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
setAsymmetric(StatusType* status, const char* type, unsigned
|
||
encryptKeyLength, const void* encryptKey, unsigned decryptKeyLength,
|
||
const void* decryptKey) – make it store pair of asymmetric keys of
|
||
given type.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
|
||
void* getEncryptKey(unsigned* length) – get a key for encryption.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
|
||
void* getDecryptKey(unsigned* length) – get a key for decryption
|
||
(in case of symmetric key produces same result as getEncryptKey()).</font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="WireCryptPlugin"></a><font size="4" style="font-size: 14pt">WireCryptPlugin
|
||
interface is main interface of network crypt plugin. Like any other
|
||
such interface it should be implemented by author of the plugin.</font></p>
|
||
<ol>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
|
||
char* getKnownTypes(StatusType* status) – returns
|
||
whitespace/tab/comma separated list of acceptable keys.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
setKey(StatusType* status, ICryptKey* key) – plugin should use a
|
||
key passed to it by this call.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
encrypt(StatusType* status, unsigned length, const void* from, void*
|
||
to) – encrypts a packet to be sent over the wire.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
decrypt(StatusType* status, unsigned length, const void* from, void*
|
||
to) – decrypts a packet received from network.</font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<h1><font size="4" style="font-size: 14pt">Server side of
|
||
authentication plugin.</font></h1>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Authentication
|
||
plugin contains two required parts – client and server and may also
|
||
contain related third part - user manager. During authentication
|
||
process firebird client invokes client plugin and sends generated by
|
||
it data to server, next server invokes server plugin and sends
|
||
generated by it data to client. This process repeats as long as both
|
||
plugins return AUTH_MORE_DATA code. AUTH_SUCCESS returned at server
|
||
side means successful authentication, AUTH_FAILED at any side –
|
||
immediate abort of iterative process and failure reported to client,
|
||
AUTH_CONTINUE means that next plugin from the list of configured
|
||
authentication plugins should be tried.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">There
|
||
is no dedicated sample of authentication plugins but in firebird
|
||
sources in directory src/auth one can find AuthDbg plugin using which
|
||
one can learn on trivial example (no complex calculations like in Srp
|
||
and no calls to crazy WinAPI functions like in AuthSspi) how client
|
||
and server sides perform authentication handshake. </font>
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Auth
|
||
interface does not contain methods, only some constants defining
|
||
codes return from authenticate() method of <a href="#Client">Client</a>
|
||
and <a href="#Server">Server</a>.</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">AUTH_FAILED</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">AUTH_SUCCESS</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">AUTH_MORE_DATA</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">AUTH_CONTINUE</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="Writer"></a><font size="4" style="font-size: 14pt">Writer
|
||
interface – writes authentication parameters block.</font></p>
|
||
<ol>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
reset() - clear target block.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
add(StatusType* status, const char* name) – add login name.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
setType(StatusType* status, const char* value) – set type of added
|
||
login (user, group, etc).</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
setDb(StatusType* status, const char* value) – set security
|
||
database in which authentication was done.</font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="ServerBlock"></a><font size="4" style="font-size: 14pt">ServerBlock
|
||
interface is used by server side of authentication plugin to exchange
|
||
data with client.</font></p>
|
||
<ol>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
|
||
char* getLogin() - get login name passed from client.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
|
||
unsigned char* getData(unsigned* length) – get authentication data
|
||
passed from client.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
putData(StatusType* status, unsigned length, const void* data) –
|
||
pass authentication data to client.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ICryptKey*
|
||
newKey(StatusType* status) – create new wire crypt key and add it
|
||
to the list of available for wire crypt plugins.</font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="Server"></a><font size="4" style="font-size: 14pt">Server
|
||
interface is main interface of server side of authentication plugin. </font>
|
||
</p>
|
||
<ol>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">int
|
||
authenticate(StatusType* status, IServerBlock* sBlock, IWriter*
|
||
writerInterface) – perform single authentication step. Data
|
||
exchange with client is performed using sBlock interface. When some
|
||
authentication item is produced it should be added to authentication
|
||
block using writerInterface. Possible return values are defined in
|
||
<a href="#Auth">Auth</a> interface.</font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<h1><font size="4" style="font-size: 14pt">Client side of
|
||
authentication plugin.</font></h1>
|
||
<p style="margin-bottom: 0cm"><a name="ClientBlock"></a><font size="4" style="font-size: 14pt">ClientBlock
|
||
interface is used by client side of authentication plugin to exchange
|
||
data with server.</font></p>
|
||
<ol>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
|
||
char* getLogin() - get login name if it is present in DPB.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
|
||
char* getPassword() - get password if it is present in DPB.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
|
||
unsigned char* getData(unsigned* length) – get authentication data
|
||
passed from server.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
putData(StatusType* status, unsigned length, const void* data) –
|
||
pass authentication data to server.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ICryptKey*
|
||
newKey(StatusType* status) - create new wire crypt key and add it to
|
||
the list of available for wire crypt plugins.</font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="Client"></a><font size="4" style="font-size: 14pt">Client
|
||
interface is main interface of client side of authentication plugin.</font></p>
|
||
<ol>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">int
|
||
authenticate(StatusType* status, IClientBlock* cBlock)1. – perform
|
||
single authentication step. Data exchange with server is performed
|
||
using cBlock interface. Possible return values are defined in Auth
|
||
interface. AUTH_SUCCESS is treated by client side as AUTH_MORE_DATA
|
||
(i.e. client sends generated data to server and waits for an answer
|
||
from it).</font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<h1><font size="4" style="font-size: 14pt">User management plugin.</font></h1>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">This
|
||
plugin is actively related with server side of authentication – it
|
||
prepares users' list for authentication plugin. Not each
|
||
authentication plugin requires user manager – some may access list
|
||
of users created using non-firebird software (AuthSspi for example).
|
||
Record describing user consists of a number of fields and operation
|
||
which should be performed like add user, modify user, list user(s),
|
||
etc. Plugin must interpret commands received in <a href="#User">User</a>
|
||
interface.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="UserField"></a><font size="4" style="font-size: 14pt">UserField
|
||
interface is not used as standalone interface, it's base for
|
||
CharUserField and IntUserField. </font>
|
||
</p>
|
||
<ol>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">int
|
||
entered() - returns non-zero if a value for a field was entered
|
||
(assigned).</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">int
|
||
specified() - return non-zero if NULL value was assigned to the
|
||
field.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
setEntered(StatusType* status, int newValue) – sets entered flag
|
||
to 0/non-zero value for a field. There is no method to assign NULL
|
||
for a field cause it's never needed. NULLs if used are assigned by
|
||
the code implementing interfaces and therefore having full access to
|
||
internals of them.</font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="CharUserField"></a><font size="4" style="font-size: 14pt">CharUserField
|
||
interface:</font></p>
|
||
<ol>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
|
||
char* get() - get field's value as C-string (\0 terminated).</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
set(StatusType* status, const char* newValue) – assigns value to
|
||
the field. Sets entered flag to true.</font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="IntUserField"></a><font size="4" style="font-size: 14pt">IntUserField
|
||
interface:</font></p>
|
||
<ol>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">int
|
||
get() - get field's value.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
set(StatusType* status, int newValue) – assigns value to the
|
||
field. Sets entered flag to true.</font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="User"></a><font size="4" style="font-size: 14pt">User
|
||
interface is a list of methods accessing fields included into record
|
||
about the user. </font>
|
||
</p>
|
||
<ol>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
|
||
operation() - code of operation (see <a href="#Constants defined by User interface">list</a>
|
||
below).</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ICharUserField*
|
||
userName() - login name.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ICharUserField*
|
||
password() - password. Always empty when listing users.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ICharUserField*
|
||
firstName() - this and 2 next are components of full user name.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ICharUserField*
|
||
lastName()</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ICharUserField*
|
||
middleName()</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ICharUserField*
|
||
comment() - comment (from SQL operator COMMENT ON USER IS …).</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ICharUserField*
|
||
attributes() - tags in a form tag1=val1, tag2=val2, …, tagN=valN.
|
||
Val may be empty – than means that tag will be deleted.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IIntUserField*
|
||
active() - changes ACTIVE/INACTIVE setting for user.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IIntUserField*
|
||
admin() - sets/drops admin rights for the user.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
clear(StatusType* status) – sets all fields to not entered and not
|
||
specified.</font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="Constants defined by User interface"></a>
|
||
<font size="4" style="font-size: 14pt">Constants defined by User
|
||
interface – valid codes of operation.</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">OP_USER_ADD
|
||
– create user</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">OP_USER_MODIFY
|
||
– alter user</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">OP_USER_DELETE
|
||
– drop user</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">OP_USER_DISPLAY
|
||
– show user</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">OP_USER_SET_MAP
|
||
– turn on mapping of windows admins to role rdb$admin</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">OP_USER_DROP_MAP
|
||
– turn off mapping of windows admins to role rdb$admin</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="ListUsers"></a><font size="4" style="font-size: 14pt">ListUsers
|
||
interface is callback used by authentication plugin when list users
|
||
operation is requested. Plugin fills <a href="#User">User</a>
|
||
interface for all items in list of users one by one and for each user
|
||
calls list() method of this interface.</font></p>
|
||
<ol>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
list(StatusType* status, IUser* user) – callback function.
|
||
Implementation can do what it wants with received data. For example,
|
||
it may put data from user parameter into output stream of listing
|
||
service or place into special tables from SEC$ group.</font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="LogonInfo"></a><font size="4" style="font-size: 14pt">LogonInfo
|
||
interface contains data passed to user mamngement plugin to attach to
|
||
security database with valid credentials. Pres</font></p>
|
||
<ol>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
|
||
char* name() - returns current attachment's login name.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
|
||
char* role() - returns current attachment's active role.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
|
||
char* networkProtocol() - returns current attachment's network
|
||
protocol. Currently not used by plugins.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
|
||
char* remoteAddress() - returns current attachment's remote address.
|
||
Currently not used by plugins.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
|
||
unsigned char* authBlock(unsigned* length) – returns current
|
||
attachment's authentication block. When not NULL overrides login
|
||
name.</font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="Management"></a><font size="4" style="font-size: 14pt">Management
|
||
interface is main interface of user management plugin.</font></p>
|
||
<ol>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
start(StatusType* status, ILogonInfo* logonInfo) – starts plugin,
|
||
if needed it attaches to security database to manage may be (it's
|
||
plugin-dependent solution use it or not) using credentials from
|
||
logonInfo. </font>
|
||
</p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">int
|
||
execute(StatusType* status, IUser* user, IListUsers* callback) –
|
||
executes a command provided by operation() method of user parameter.
|
||
If needed callback interface will be used. Parameter callback may
|
||
have NULL value for commands not requiring users' listing.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
commit(StatusType* status) – commits changes done by calls to
|
||
execute() method.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
rollback(StatusType* status) – rollbacks changes done by calls to
|
||
execute() method.</font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<h1><font size="4" style="font-size: 14pt">Database encryption
|
||
plugin.</font></h1>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">An
|
||
ability to encrypt database was present in firebird since interbase
|
||
times but appropriate places in the code were commented.
|
||
Implementation was suspicious – crypt key was always sent from the
|
||
client in DPB, no attempt was made to hide it from the world and no
|
||
way was suggested to encrypt existing database. FB3 solves most of
|
||
the problems except probably the worst one – how to manage crypt
|
||
keys. We suggest a kind of solution but it requires efforts in
|
||
plugins, i.e. there is no beautiful way to work with keys like it is
|
||
for wire crypt plugins.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Before
|
||
starting with own db crypt plugin one should take into an account the
|
||
following. We see two main usages of database encryption – first,
|
||
it may be needed to avoid data loss if database server is physically
|
||
stolen, and second, it may be used to protect data in database which
|
||
is sailed together with special application accessing that data.
|
||
Requirements for this usages are quite different. In first case we
|
||
may trust database server that it is not modified to steal keys
|
||
passed to security plugin – i.e. we expect that key will not be
|
||
sent to inappropriate server. In second case server may be modified
|
||
in some way to steal keys (if they are passed from application to
|
||
plugin via server code) or even data (as the last resort to dump
|
||
blocks from the cache where they are in non-encrypted form).
|
||
Therefore your plugin should make sure that it's running with not
|
||
modified firebird binaries and your application before sending a key
|
||
to plugin should make sure it's really required plugin, may be asking
|
||
a kind of digital signature from it. Making sure that network line is
|
||
encrypted (parsing output of <a href="#Util">Util</a>::getFbVersion())
|
||
or using some own encryption of a key is also very good idea in case
|
||
when network access to the server is used. All this job should be
|
||
done in plugin (and application working with it) i.e. database block
|
||
encryption algorithm by itself may happen to be easiest part of db
|
||
crypt plugin, specially when some standard library is used for it.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="CryptKeyCallback"></a><font size="4" style="font-size: 14pt">CryptKeyCallback
|
||
interface should be provided by a side sending crypt key to db crypt
|
||
plugin or key holder plugin.</font></p>
|
||
<ol>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
|
||
callback(unsigned dataLength, const void* data, unsigned
|
||
bufferLength, void* buffer) – when performing callback information
|
||
is passed in both directions. The source of a key receives
|
||
dataLength bytes of data and may send up to bufferLength bytes into
|
||
buffer returning actual number of bytes placed into buffer.</font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="DbCryptInfo"></a><font size="4" style="font-size: 14pt">DbCryptInfo
|
||
interface is passed to DbCryptPlugin by engine. Plugin may save this
|
||
interface and use when needed to obtain additional informatio about
|
||
database.</font></p>
|
||
<ol>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">const
|
||
char* getDatabaseFullPath(StatusType* status) – returns full
|
||
(including path) name of primary database file.</font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="DbCryptPlugin"></a><font size="4" style="font-size: 14pt">DbCryptPlugin
|
||
interface is main interface of database crypt plugin.</font></p>
|
||
<ol>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
setKey(StatusType* status, unsigned length, IKeyHolderPlugin**
|
||
sources, const char* keyName) – is used to provide to db crypt
|
||
plugin information about encryption key. Firebird never passes keys
|
||
for this type of plugin directly. Instead array of <a href="#KeyHolderPlugin">KeyHolderPlugins</a>
|
||
of given length is passed to crypt plugin which must get from one of
|
||
it <a href="#CryptKeyCallback">CryptKeyCallback</a> interface and
|
||
get a key using it. Parameter keyName is a name of a key like it was
|
||
entered in “ALTER DATABASE ENCRYPT …” operator.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
encrypt(StatusType* status, unsigned length, const void* from, void*
|
||
to) – encrypts data before writing block to database file.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
decrypt(StatusType* status, unsigned length, const void* from, void*
|
||
to) – decrypts data after reading block from database file.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
setInfo(StatusType* status, IDbCryptInfo* info) – in this method
|
||
crypt plugin typically saves informational interface for future use.</font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<h1><font size="4" style="font-size: 14pt">Key holder for database
|
||
encryption plugin.</font></h1>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">This
|
||
type of plugin is needed to delineate functionality – db crypt
|
||
plugin is dealing with actual encryption, key holder solves questions
|
||
related with providing it a key in secure way. Plugin may be received
|
||
from application or loaded in some other way (up to using flash
|
||
device inserted into server at firebird startup time).</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="KeyHolderPlugin"></a><font size="4" style="font-size: 14pt">KeyHolderPlugin
|
||
interface is main interface of database crypt key holder plugin.</font></p>
|
||
<ol>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">int
|
||
keyCallback(StatusType* status, ICryptKeyCallback* callback) – is
|
||
used to pass attachment's <a href="#CryptKeyCallback">CryptKeyCallback</a>
|
||
interface (if provided by user with <a href="#Provider">Provider</a>::setDbCryptCallback()
|
||
call). This call is always performed at database attach moment, and
|
||
some holders may reject attachment if satisfactory key was not
|
||
provided. Return value of 0 means that key holder can not provide a
|
||
key to crypt plugin, non-zero – can.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ICryptKeyCallback*
|
||
keyHandle(StatusType* status, const char* keyName) – is intended
|
||
to be called by <a href="#DbCryptPlugin">DbCryptPlugin</a> directly
|
||
to obtain callback interface for named key from key holder. This
|
||
makes it possible for open source firebird code to never touch
|
||
actual keys avoiding ability to steal a key changing firebird code.
|
||
After getting <a href="#CryptKeyCallback">CryptKeyCallback</a>
|
||
interface crypt plugin starts data exchange using it. Key holder can
|
||
(for example) check digital signature of crypt plugin before sending
|
||
a key to it in order to avoid use of modified crypt plugin able to
|
||
steal secret key.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_BOOLEAN
|
||
useOnlyOwnKeys(StatusType* status) – informs firebird engine
|
||
whether a key, provided by key holder, can be used in other
|
||
attachments. Makes sense only for SuperServer – only it can share
|
||
database crypt keys between attachments. Returning FB_TRUE from this
|
||
method enforces firebird to make sure that this particular key
|
||
holder (and therefore in turn attachment related to it) provides
|
||
correct crypt key for any other attachment to this database.</font></p>
|
||
<li><p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ICryptKeyCallback*
|
||
chainHandle(StatusType* status) – support of a chain of key
|
||
holders. In some cases key has to pass through more than single key
|
||
holder before it reaches db crypt plugin. This is needed (for
|
||
example) to support execute statement in encrypted database. This is
|
||
just a sample – chains are also used in some other cases. Callback
|
||
interface, returned by this method, may differ from one returned by
|
||
keyHandle() function (see above). Typically is should be able to
|
||
duplicate one-to-one keys, received by KeyHolderPlugin when
|
||
keyCallback() function is invoked.</font></p>
|
||
</ol>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<h1><font size="4" style="font-size: 14pt">Non-interface objects used
|
||
by API (C++ specific header Message.h).</font></h1>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Following
|
||
3 classes are used to represent date, time and timestamp (datetime)
|
||
when using FB_MESSAGE macro. Members of data structure, representing
|
||
static message, correspondint to fields of types FB_DATE / FB_TIME /
|
||
FB_TIMESTAMP will have a type of one of this classes. Knowing methods
|
||
/ members (which are enough self-descriptive to avoid describing them
|
||
here) of this classes is needed to access date and time fields in
|
||
static messages.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="FbDate"></a><font size="4" style="font-size: 14pt">class
|
||
FbDate methods:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
decode(IUtil* util, unsigned* year, unsigned* month, unsigned* day)</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
|
||
getYear(IUtil* util) </font>
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
|
||
getMonth(IUtil* util)</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
|
||
getDay(IUtil* util)</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
encode(IUtil* util, unsigned year, unsigned month, unsigned day)</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><a name="FbTime"></a><font size="4" style="font-size: 14pt">class
|
||
FbTime methods:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
decode(IUtil* util, unsigned* hours, unsigned* minutes, unsigned*
|
||
seconds, unsigned* fractions)</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
|
||
getHours(IUtil* util)</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
|
||
getMinutes(IUtil* util)</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
|
||
getSeconds(IUtil* util)</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
|
||
getFractions(IUtil* util)</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
encode(IUtil* util, unsigned hours, unsigned minutes, unsigned
|
||
seconds, unsigned fractions)</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">class
|
||
FbTimestamp members:</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FbDate
|
||
date;</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FbTime
|
||
time;</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">Following
|
||
two templates are used in static messages to represent CHAR(N) and
|
||
VARCHAR(N) fields. </font>
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">template
|
||
<unsigned N></font></p>
|
||
<p style="margin-bottom: 0cm"><a name="FbChar"></a><font size="4" style="font-size: 14pt">struct
|
||
FbChar</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">{</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">char
|
||
str[N];</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">};</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">template
|
||
<unsigned N></font></p>
|
||
<p style="margin-bottom: 0cm"><a name="FbVarChar"></a><font size="4" style="font-size: 14pt">struct
|
||
FbVarChar</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">{</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ISC_USHORT
|
||
length;</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">char
|
||
str[N];</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
|
||
set(const char* s);</font></p>
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">};</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
<hr/>
|
||
|
||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">This
|
||
document is currently missing 2 types of plugins – ExternalEngine
|
||
and Trace. Information about them will be made available in next
|
||
release of it.</font></p>
|
||
<p style="margin-bottom: 0cm"><br/>
|
||
|
||
</p>
|
||
</body>
|
||
</html>
|