From a9cef6d9aeaabc08d8f104230a38345340edf7a2 Mon Sep 17 00:00:00 2001 From: Alex Peshkoff Date: Fri, 29 May 2020 15:43:59 +0300 Subject: [PATCH] Implemented CORE-6320: Replace Util methods to get interface pointer by legacy handle with plain functions --- builds/posix/firebird.vers | 3 +- doc/Using_OO_API.html | 2440 +++++++++++--------- examples/interfaces/12.batch_isc.cpp | 9 +- src/include/firebird/FirebirdInterface.idl | 2 - src/include/firebird/IdlFbInterfaces.h | 64 - src/include/ibase.h | 2 + src/yvalve/YObjects.h | 2 - src/yvalve/why.cpp | 89 +- 8 files changed, 1430 insertions(+), 1181 deletions(-) diff --git a/builds/posix/firebird.vers b/builds/posix/firebird.vers index 612993ed2b..b81d308fd1 100644 --- a/builds/posix/firebird.vers +++ b/builds/posix/firebird.vers @@ -347,7 +347,8 @@ fb_get_master_interface fb_get_database_handle fb_get_transaction_handle -#fb_get_statement_interface +fb_get_transaction_interface +fb_get_statement_interface fb_database_crypt_callback fb_dsql_set_timeout diff --git a/doc/Using_OO_API.html b/doc/Using_OO_API.html index 7ca41ac2ce..9204377162 100644 --- a/doc/Using_OO_API.html +++ b/doc/Using_OO_API.html @@ -3,10 +3,12 @@ - + - - + + + + @@ -15,15 +17,16 @@ -

+ +

Firebird interfaces.

-

Firebird's +

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 @@ -48,10 +51,10 @@ 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.

-


+


-

Typically +

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 plugins @@ -65,20 +68,20 @@ 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.

-


+


-

Firebird +

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.

-


+


-

This +

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 @@ -92,15 +95,15 @@ counted pointers, not used other RAII holders, not used templates 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.

-


+


-

+

Accessing databases.

Creating database and attaching to existing database.

-

First +

First of all we need to get access to IMaster interface. IMaster is primary Firebird interface, required to access all the rest of interfaces. Therefore there is a special way of accessing it – the @@ -110,12 +113,12 @@ 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:

-

static +

static IMaster* master = fb_get_master_interface();

-


+


-

For +

For a lot of methods, used in Firebird API, first parameter is IStatus interface. It's a logical replacement of ISC_STATUS_ARRAY, but works separately with errors and warnings (not mixing them in same array), @@ -124,28 +127,28 @@ 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:

-

IStatus* +

IStatus* st = master->getStatus();

-

If +

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.

-


+


-

Now +

Now we are going to deal with first interface, directly related to database calls. This is IProvider – 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:

-

IProvider* +

IProvider* prov = master->getDispatcher();

-


+


-

When +

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. @@ -163,28 +166,28 @@ instance of IXpbBuilder you must know one more generic-use interface of firebird API – IUtil. It's a kind of placeholder for the calls that do not fit well in other places. So we do

-

IUtil* +

IUtil* utl = master->getUtilInterface();

-

IXpbBuilder* +

IXpbBuilder* dpb = utl->getXpbBuilder(&status, IXpbBuilder::DPB, NULL, 0);

-

This +

This creates empty parameters' block builder of DPB type. Now adding required parameter to it is trivial:

-

dpb->insertInt(&status, +

dpb->insertInt(&status, isc_dpb_page_size, 4 * 1024);

-

will +

will make firebird to create new database with pagesize equal to 4Kb and meaning of

-

dpb->insertString(&status, +

dpb->insertString(&status, isc_dpb_user_name, “sysdba”);

-

dpb->insertString(&status, +

dpb->insertString(&status, isc_dpb_password, “masterkey”);

-

is +

is (I hope) obvious.

-


+


-

The +

The following is C++ specific: We are almost ready to call createDatabase() method of IProvider, but before it a few words about concept of Status Wrapper should be said. Status wrapper is @@ -193,19 +196,19 @@ 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 ThrowStatusWrapper, which raises C++ exception each time an error is returned in IStatus.

-

ThrowStatusWrapper +

ThrowStatusWrapper status(st);

-


+


-

Now +

Now we may create new empty database:

-

IAttachment* +

IAttachment* att = prov->createDatabase(&status, "fbtests.fdb", dpb->getBufferLength(&status), dpb->getBuffer(&status));

-

printf("Database +

printf("Database fbtests.fdb created\n");

-

Pay +

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 @@ -214,64 +217,64 @@ 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.

-


+


-

Detaching +

Detaching from just created database is trivial:

-

att->detach(&status);

-


+

att->detach(&status);

+


-

Now +

Now it remains to enclose all operators into try 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:

-

catch +

catch (const FbException& error)

-

{

-

char +

{

+

char buf[256];

-

utl->formatStatus(buf, +

utl->formatStatus(buf, sizeof(buf), error.getStatus());

-

fprintf(stderr, +

fprintf(stderr, "%s\n", buf);

-

}

-

Pay +

}

+

Pay attention that here we use one more function from IUtil – formatStatus(). It returns in buffer text, describing an error (warning), stored in IStatus parameter.

-


+


-

To +

To attach to existing database just use attachDatabase() method of IProvider instead createDatabase(). All parameters are the same for both methods.

-

att +

att = prov->attachDatabase(&status, "fbtests.fdb", 0, NULL);

-

This +

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.

-


+


-

Our +

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.

-


+


Working with transactions.

-

Only +

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 @@ -281,56 +284,56 @@ not discuss distributed transactions (supported by IDtc interface) to avoid unneeded to most users overcomplication. Starting of non-distributed transaction is very simple and done via attachment interface:

-

ITransaction* +

ITransaction* tra = att->startTransaction(&status, 0, NULL);

-

In +

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 IXpbBuilder, add required items to it:

-

IXpbBuilder* +

IXpbBuilder* tpb = utl->getXpbBuilder(&status, IXpbBuilder::TPB, NULL, 0);

-

tpb->insertTag(&status, +

tpb->insertTag(&status, isc_tpb_read_committed);

-

and +

and pass resulting TPB to startTransaction():

-

ITransaction* +

ITransaction* tra = att->startTransaction(&status, tpb->getBufferLength(&status), tpb->getBuffer(&status));

-


+


-

Transaction +

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:

-

tra->commit(&status);

-


+

tra->commit(&status);

+


-

You +

You may take a look at how to start and commit transaction in examples 01.create.cpp and 01.create.pas.

-


+


Executing SQL operator without input parameters and returned rows.

-

With +

With started transaction we are ready to execute our first SQL operators. Used for it execute() method in IAttachment 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:

-

att->execute(&status, +

att->execute(&status, tra, 0, "create table dates_table (d1 date)", SQL_DIALECT_V6, NULL, NULL, NULL, NULL);

-

tra->commitRetaining(&status);

-

att->execute(&status, +

tra->commitRetaining(&status);

+

att->execute(&status, tra, 0, "insert into dates_table values (CURRENT_DATE)", SQL_DIALECT_V6, NULL, NULL, NULL, NULL);

-

As +

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 @@ -339,18 +342,18 @@ 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 IAttachment interface.

-


+


-

You +

You may take a look at how to start and commit transaction in examples 01.create.cpp and 01.create.pas.

-


+


Executing SQL operator with input parameters.

-

There +

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 @@ -358,26 +361,26 @@ 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.

-


+


-

To +

To prepare SQL statement for execution use prepare() method of IAttachment interface:

-

IStatement* +

IStatement* stmt = att->prepare(&status, tra, 0, “UPDATE department SET budget = ? * budget + budget WHERE dept_no = ?”,

-

SQL_DIALECT_V6, +

SQL_DIALECT_V6, IStatement::PREPARE_PREFETCH_METADATA);

-

If +

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.

-


+


-

In +

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) @@ -387,129 +390,132 @@ 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:

    -
  • build +

  • +

    build using IMetadataBuilder interface,

    -
  • have +

  • +

    have your own implementation of this interface.

-


+


-

Getting +

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:

-

IMessageMetadata* +

IMessageMetadata* meta = stmt->getInputMetadata(&status);

-


+


-

Or +

Or we can build message metadata ourself. First of all we need builder interface for it:

-

IMetadataBuilder* +

IMetadataBuilder* builder = master->getMetadataBuilder(&status, 2);

-

Second +

Second parameter is expected number of fields in the message, it can be changed later, i.e. that's just an optimization.

-

Now +

Now it's necessary to set individual fields characteristics in the builder. An absolute minimum is field types and length for string fields:

-

builder->setType(&status, +

builder->setType(&status, 0, SQL_DOUBLE + 1);

-

builder->setType(&status, +

builder->setType(&status, 1, SQL_TEXT + 1);

-

builder->setLength(&status, +

builder->setLength(&status, 1, 3);

-

+

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:

-

IMessageMetadata* +

IMessageMetadata* meta = builder->getMetadata(&status);

-


+


-

+

Here we do not discuss in details own implementation of IMessageMetadata. If one cares there is a sample 05.user_metadata.cpp.

-

So +

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:

-

char* +

char* buffer = new char[meta->getMessageLength(&status)];

-

To +

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:

-

double* +

double* percent_inc = (double*) &buffer[meta->getOffset(&status, 0)];

-

char* +

char* dept_no = &buffer[meta->getOffset(&status, 1)];

-

Also +

Also let's do not forget to set to NOT NULL null flags:

-

short* +

short* flag = (short*)&buffer[meta->getNullOffset(&status, 0)];

-

*flag +

*flag = 0;

-

flag +

flag = (short*) &buffer[meta->getNullOffset(&status, 1)];

-

*flag +

*flag = 0;

-


+


-

After +

After finishing with offsets we are ready to execute statement with some parameters values:

-

getInputValues(dept_no, +

getInputValues(dept_no, percent_inc);

-

and +

and may execute prepared statement:

-

stmt->execute(&status, +

stmt->execute(&status, tra, meta, buffer, NULL, NULL);

-

Two +

Two more NULLs in the end of parameters stand for output message and is used typically for EXECUTE PROCEDURE statement.

-


+


-

If +

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 IAttachment interface:

-

att->execute(&status, +

att->execute(&status, tra, 0, "UPDATE department SET budget = ? * budget + budget WHERE dept_no = ?", SQL_DIALECT_V6, meta, buffer, NULL, NULL);

-

In +

In that case you do not need to use IStatement at all.

-


+


-

An +

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.

-


+


Opening cursor and fetching data from it.

-

The +

The only way to get rows of data, returned by SELECT operator, in OO API is to use IResultSet interface. This interface is returned by openCursor() method in both IAttachment and @@ -523,46 +529,46 @@ 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:

-

const +

const char* sql = "select * from ..."; // some select statement

-


+


-

IResultSet* +

IResultSet* curs = att->openCursor(&status, tra, 0, sql, SQL_DIALECT_V6, NULL, NULL, NULL, NULL, 0);

-

IMessageMetadata* +

IMessageMetadata* meta = curs->getMetadata(&status);

-

Later +

Later this metadata may be used to allocate buffer for data and parse fetched rows.

-


+


-

As +

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.

-

IStatement* +

IStatement* stmt = att->prepare(&status, tra, 0, sql, SQL_DIALECT_V6, Istatement::PREPARE_PREFETCH_METADATA);

-

IMessageMetadata* +

IMessageMetadata* meta = stmt->getOutputMetadata(&status);

-

IResultSet* +

IResultSet* curs = stmt->openCursor(&status, tra, NULL, NULL, NULL, 0);

-


+


-

We +

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:

-

unsigned +

unsigned char* buffer = new unsigned char[meta->getMessageLength(&status)];

-


+


-

IResultSet +

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 @@ -575,45 +581,45 @@ 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:

-

while +

while (curs->fetchNext(&status, buffer) == IStatus::RESULT_OK)

-

{

-

// +

{

+

// row processing

-

}

-


+

}

+


-

What +

What is done during row processing depends upon your needs. To access particular field field's offset should be used:

-

unsigned +

unsigned char* field_N_ptr = buffer + meta->getOffset(&status, n);

-

+

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:

-

vary* +

vary* v_ptr = (vary*) (buffer + meta->getOffset(&status, n));

-

Now +

Now we may print the value of a field:

-

printf(“field +

printf(“field %s value is %*.*s\n”, meta->getField(&status, n), v_ptr->vary_length, v_ptr->vary_length, v_ptr->vary_string);

-


+


-

If +

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.

-


+


Using FB_MESSAGE macro for static messages.

-

Working +

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 @@ -622,37 +628,37 @@ 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.

-


+


-

FB_MESSAGE +

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:

-

FB_BIGINT

-

FB_BLOB

-

FB_BOOLEAN

-

FB_CHAR(len)

-

FB_DATE

-

FB_DECFIXED(scale)

-

FB_DECFLOAT16

-

FB_DECFLOAT34

-

FB_DOUBLE

-

FB_FLOAT

-

FB_INTEGER

-

FB_INTL_CHAR(len, +

FB_BIGINT

+

FB_BLOB

+

FB_BOOLEAN

+

FB_CHAR(len)

+

FB_DATE

+

FB_DECFIXED(scale)

+

FB_DECFLOAT16

+

FB_DECFLOAT34

+

FB_DOUBLE

+

FB_FLOAT

+

FB_INTEGER

+

FB_INTL_CHAR(len, charSet)

-

FB_INTL_VARCHAR(len, +

FB_INTL_VARCHAR(len, charSet)

-

FB_SCALED_BIGINT(scale)

-

FB_SCALED_INTEGER(scale)

-

FB_SCALED_SMALLINT(scale)

-

FB_SMALLINT

-

FB_TIME

-

FB_TIMESTAMP

-

FB_VARCHAR(len)

-

In +

FB_SCALED_BIGINT(scale)

+

FB_SCALED_INTEGER(scale)

+

FB_SCALED_SMALLINT(scale)

+

FB_SMALLINT

+

FB_TIME

+

FB_TIMESTAMP

+

FB_VARCHAR(len)

+

In generated by preprocessor structure integer and float types are matched with appropriate C types, date and time – with classes FbDate and FbTime (all @@ -666,52 +672,52 @@ field/parameter value and nameN for NULL indicator. Message constructor has 2 parameters – pointer to status wrapper and master interface:

-

FB_MESSAGE(Output, +

FB_MESSAGE(Output, ThrowStatusWrapper,

-

(FB_SMALLINT, +

(FB_SMALLINT, relationId)

-

(FB_CHAR(31), +

(FB_CHAR(31), relationName)

-

(FB_VARCHAR(100), +

(FB_VARCHAR(100), description)

-

) +

) output(&status, master);

-


+


-

For +

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:

-

rs +

rs = att->openCursor(&status, tra, 0, sqlText,

-

SQL_DIALECT_V6, +

SQL_DIALECT_V6, NULL, NULL, output.getMetadata(), NULL, 0);

-

and +

and used to work with values of individual fields:

-

while +

while (rs->fetchNext(&status, output.getData()) == IStatus::RESULT_OK)

-

{

-

printf("%4d +

{

+

printf("%4d %31.31s %*.*s\n", output->relationId, output->relationName.str,

-

output->descriptionNull +

output->descriptionNull ? 0 : output->description.length,

-

output->descriptionNull +

output->descriptionNull ? 0 : output->description.length, output->description.str);

-

}

-


+

}

+


-

An +

An example of using macro FB_MESSAGE to work with messages is in the sample 06.fb_message.cpp.

-


+


Working with blobs.

-

For +

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 IAttachment has 2 @@ -722,144 +728,144 @@ 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.

-


+


-

To +

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:

-

ISC_QUAD* +

ISC_QUAD* blobPtr = (ISC_QUAD*) &buffer[metadata->getOffset(&status, blobFieldNumber)];

-

ISC_SHORT* +

ISC_SHORT* blobNullPtr = (ISC_SHORT*) &buffer[metadata->getNullOffset(&status, blobFieldNumber)];

-


+


-

If +

If you use static messages and FB_MESSAGE macro blob field is declared as having FB_BLOB type:

-

FB_MESSAGE(Msg, +

FB_MESSAGE(Msg, ThrowStatusWrapper,

-

(FB_BLOB, +

(FB_BLOB, b)

-

) +

) message(&status, master);

-

ISC_QUAD* +

ISC_QUAD* blobPtr = &message->b;

-

ISC_SHORT* +

ISC_SHORT* blobNullPtr = &message->bNull;

-


+


-

To +

To create new blob invoke createBlob() method:

-

IBlob* +

IBlob* blob = att->createBlob(status, tra, blobPtr, 0, NULL);

-

Last +

Last two parameters are required only if you want to use blob filters or use stream blob, that's out of scope here.

-

Blob +

Blob interface is ready to accept data into blob. Use putSegment() method to send data to engine:

-

void* +

void* segmentData;

-

unsigned +

unsigned segmentLength;

-

while +

while (userFunctionProvidingBlobData(&segmentData, &segmentLength))

-

blob->putSegment(&status, +

blob->putSegment(&status, segmentLength, segmentData);

-

After +

After sending some data to blob do not forget to close blob interface:

-

blob->close(&status);

-

Make +

blob->close(&status);

+

Make sure that null flag is not set (not required if you nullified all message buffer before creating blob):

-

*blobNullPtr +

*blobNullPtr = 0;

-

and +

and message, containing blob, may be used in insert or update statement. After execution of that statement new blob will be stored in database.

-


+


-

To +

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:

-

IBlob* +

IBlob* blob = att->openBlob(status, tra, blobPtr, 0, NULL);

-

Blob +

Blob interface is ready to provide blob data. Use getSegment() method to receive data from engine:

-

char +

char buffer[BUFSIZE];

-

unsigned +

unsigned actualLength;

-

for(;;)

-

{

-

switch +

for(;;)

+

{

+

switch (blob->getSegment(&status, sizeof(buffer), buffer, &actualLength))

-

{

-

case +

{

+

case IStatus::RESULT_OK:

-

userFunctionAcceptingBlobData(buffer, +

userFunctionAcceptingBlobData(buffer, actualLength, true);

-

continue;

-

case +

continue;

+

case IStatus::RESULT_SEGMENT:

-

userFunctionAcceptingBlobData(buffer, +

userFunctionAcceptingBlobData(buffer, actualLength, false);

-

continue;

-

default:

-

break;

-

}

-

}

-

Last +

continue;

+

default:

+

break;

+

}

+

}

+

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.

-

After +

After finishing with blob do not forget to close it:

-

blob->close(&status);

-


+

blob->close(&status);

+


Modifying data in a batch.

-

Since +

Since version 4 firebird supports batch execution of statements with input parameters – that means sending more than single set of parameters when executing statement. Batch interface is designed (first of all) in order to satisfy JDBC requirements for prepared statement’s batch processing but has some serious differences:

-

- +

- like all operations with data in firebird it’s oriented on messages, not single field;

-

- +

- as an important extension out batch interface supports inline use of blobs (specially efficient when working with small blobs);

-

- +

- execute() method returns not plain array of integers but special BatchCompletionState 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.

-


+


-

Batch +

Batch (exactly like ResultSet) may be created in 2 ways – using Statement or Attachment interface, in both cases createBatch() method of appropriate @@ -873,67 +879,67 @@ Possible tags are described in batch interface. The simplest (and recommended) way to create parameters block for batch creation is to use appropriate XpbBuilder interface:

-

IXpbBuilder* +

IXpbBuilder* pb = utl->getXpbBuilder(&status, IXpbBuilder::BATCH, NULL, 0);

-

pb->insertInt(&status, +

pb->insertInt(&status, IBatch::RECORD_COUNTS, 1);

-

Use +

Use of such parameters block directs batch to account number of updated records on per-message basis.

-

To +

To create batch interface with desired parameters pass parameters block to createBatch() call:

-

IBatch* +

IBatch* batch = att->createBatch(&status, tra, 0, sqlStmtText, SQL_DIALECT_V6, NULL,

-

pb->getBufferLength(&status), +

pb->getBufferLength(&status), pb->getBuffer(&status));

-

In +

In this sample batch interface is created with default format of messages cause NULL is passed instead input metadata format.

-


+


-

In +

In order to proceed with created batch interface we need to know format of messages in it. It can be obtained using getMetadata() method:

-

IMessageMetadata* +

IMessageMetadata* meta = batch->getMetadata(&status);

-

Certainly +

Certainly if you have passed your own format of messages to the batch you may simply use it.

-

+

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:

-

unsigned +

unsigned char* data = new unsigned char[meta->getMessageLength(&status)];

-

+

Now we can add some messages full of data to the batch:

-

fillNextMessage(data, +

fillNextMessage(data, meta);

-

batch->add(&status, +

batch->add(&status, 1, data);

-

fillNextMessage(data, +

fillNextMessage(data, meta);

-

batch->add(&status, +

batch->add(&status, 1, data);

-

+

An alternative way of working with messages (using FB_MESSAGE macro) is present in the sample of using batch interface 11.batch.cpp.

-


+


-

+

Finally batch should be executed:

-

IBatchCompletionState* +

IBatchCompletionState* cs = batch->execute(&status, tra);

-

We +

We requested accounting of the number of modified (inserted, updated or deleted) records per message. To print it we must use BatchCompletionState interface. @@ -959,13 +965,13 @@ is in print_cs() function in sample 11.batch.cpp.

-

batch->cancel(&status);

-

+

batch->cancel(&status);

+

Being reference counted Batch does not have special method to close it – standard release() call:

-

batch->release();

-

+

batch->release();

+

Described methods help to implement all what one needs for JDBC-style prepared statement batch operations. @@ -1033,7 +1039,7 @@ something like this:

descriptionSize, descriptionText, &project->desc);

batch->add(&status, 1, project.getData());

-

+

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 @@ -1132,33 +1138,34 @@ that will cause invalid blob ID error during batch execution. Instead do:

batch->registerBlob(&status, &realId, &msg->desc);

-

+

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.

-


+


-

+

Almost all mentioned methods are used in 11.batch.cpp – please use it to see an alive sample of batching in firebird.

-


+


-

+

Two words about access to batches from ISC API - one can execute prepared ISC statement in -batch mode. Main support for it is present in Util interface, namely -getTransactionByHandle & getStatementByHandle methods, which make -it possible to access appropriate interfaces identical to existing -ISC handles. An example of it is present in 12.batch_isc.cpp.

-


+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.

+


Working with events.

-

Events +

Events interface was not completed in FB3, we expect to have something more interesting in next version. The minimum existing support is as follows: IAttachment contains call @@ -1179,43 +1186,43 @@ cause segfault when interface is already destroyed. Therefore interface IEvents must be explicitly released after receiving an event. This may be done for example right before queuing for an event next time:

-

events->release();

-

events +

events->release();

+

events = NULL;

-

events +

events = attachment->queEvents(&status, this, eveLen, eveBuffer);

-

Setting +

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.

-


+


Using services.

-

To +

To begin to use services one should first of all connect to service manager. This is done using attachServiceManager() method of IProvider. This method returns IService interface which is used later to talk to service. To prepare SPB to attach to service manager one can use IXpbBuilder:

-

IXpbBuilder* +

IXpbBuilder* spb1 = utl->getXpbBuilder(&status, IXpbBuilder::SPB_ATTACH, NULL, 0);

-

spb1->insertString(&status, +

spb1->insertString(&status, isc_spb_user_name, “sysdba”);

-

spb1->insertString(&status, +

spb1->insertString(&status, isc_spb_password, “masterkey”);

-

and +

and proceed with attach:

-

IService* +

IService* svc = prov->attachServiceManager(&status, “service_mgr”, spb1->getBufferLength(&status), spb1->getBuffer(&status));

-


+


-

Using +

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 @@ -1225,32 +1232,32 @@ 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.

-


+


-

To +

To start service one should first of all create appropriate SPB:

-

IXpbBuilder* +

IXpbBuilder* spb2 = utl->getXpbBuilder(&status, IXpbBuilder::SPB_START, NULL, 0);

-

and +

and add required items to it. For example, to print encryption statistics for database employee the following should be placed into SPB:

-

spb2->insertTag(&status, +

spb2->insertTag(&status, isc_action_svc_db_stats);

-

spb2->insertString(&status, +

spb2->insertString(&status, isc_spb_dbname, "employee");

-

spb2->insertInt(&status, +

spb2->insertInt(&status, isc_spb_options, isc_spb_sts_encryption);

-

After +

After it service can be started using start() method of IService interface:

-

svc->start(&status, +

svc->start(&status, spb2->getBufferLength(&status), spb2->getBuffer(&status));

-


+


-

Many +

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 @@ -1261,23 +1268,23 @@ 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:

-

const +

const unsigned char receiveItems1[] = {isc_info_svc_line};

-

To +

To query information one also needs a buffer for that information:

-

unsigned +

unsigned char results[1024];

-

After +

After that preliminary steps we are ready to query service in a loop (each line returned in a single call to query()):

-

do

-

{

-

svc->query(&status, +

do

+

{

+

svc->query(&status, 0, NULL, sizeof(receiveItems1), receiveItems1, sizeof(results), results);

-

} +

} while (printInfo(results, sizeof(results)));

-

In +

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 @@ -1285,39 +1292,39 @@ 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.

-


+


-

Same +

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:

-

const +

const unsigned char receiveItems2[] = {isc_info_svc_server_version};

-

Existing +

Existing from previous call results buffer may be reused. No loop is needed here:

-

svc->query(&status, +

svc->query(&status, 0, NULL, sizeof(receiveItems2), receiveItems2, sizeof(results), results);

-

printInfo(results, +

printInfo(results, sizeof(results));

-


+


-

After +

After finishing with services tasks do not forget to close an interface:

-

svc->detach(&status);

-


+

svc->detach(&status);

+


-

+

Writing plugins.

-

To +

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 plugin @@ -1331,26 +1338,26 @@ 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.

-

In +

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.

-


+


-

Following +

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.

-


+


Implementation of plugin module.

-

Plugins +

Plugins actively interact with special firebird component called plugin manager. In particular plugin manager should be aware what plugin modules were @@ -1371,66 +1378,66 @@ 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 IPluginModule interface.

-


+


-

Minimum +

Minimum implementation looks as follows:

-


+


-

class +

class PluginModule : public IPluginModuleImpl<PluginModule, CheckStatusWrapper>

-

{

-

private:

-

IPluginManager* +

{

+

private:

+

IPluginManager* pluginManager;

-


+


-

public:

-

PluginModule()

-

: +

public:

+

PluginModule()

+

: pluginManager(NULL)

-

{ +

{ }

-


+


-

~PluginModule()

-

{

-

if +

~PluginModule()

+

{

+

if (pluginManager)

-

{

-

pluginManager->unregisterModule(this);

-

doClean();

-

}

-

}

-


+

{

+

pluginManager->unregisterModule(this);

+

doClean();

+

}

+

}

+


-

void +

void registerMe(IPluginManager* m)

-

{

-

pluginManager +

{

+

pluginManager = m;

-

pluginManager->registerModule(this);

-

}

-


+

pluginManager->registerModule(this);

+

}

+


-

void +

void doClean()

-

{

-

pluginManager +

{

+

pluginManager = NULL;

-

}

-

};

-


+

}

+

};

+


-

The +

The only data member is plugin manager interface IPluginManager. It's passed to registerModule() function and saved in private variable, at the same time module is registered in plugin manager by @@ -1445,22 +1452,22 @@ 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.

-


+


-

Implementing +

Implementing plugin's interface IPluginModule we met with first interface required to implement plugins – IPluginManager. 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.

-


+


Core interface of any plugin.

-

Let's +

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 @@ -1472,24 +1479,24 @@ 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.

-


+


-

Let's +

Let's take a look at typical part of any plugin implementation (here I specially use non-existent type SomePlugin):

-

class +

class MyPlugin : public ISomePluginImpl<MyPlugin, CheckStatusWrapper>

-

{

-

public:

-

explicit +

{

+

public:

+

explicit MyPlugin(IPluginConfig* cnf) throw()

-

: +

: config(cnf), refCounter(0), owner(NULL)

-

{

-

config->addRef();

-

}

-

+

{

+

config->addRef();

+

}

+

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 @@ -1498,122 +1505,122 @@ 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.

-


+


-

~MyPlugin()

-

{

-

config->release();

-

}

-

+

~MyPlugin()

+

{

+

config->release();

+

}

+

Destructor releases config interface. Pay attention – we do not change reference counter of our owner cause it owns us, not we own it.

-


+


-

// +

// IRefCounted implementation

-

int +

int release()

-

{

-

if +

{

+

if (--refCounter == 0)

-

{

-

delete +

{

+

delete this;

-

return +

return 0;

-

}

-

return +

}

+

return 1;

-

}

-


+

}

+


-

void +

void addRef()

-

{

-

++refCounter;

-

}

-

+

{

+

++refCounter;

+

}

+

Absolutely typical implementation of reference counted object.

-


+


-

// +

// IPluginBase implementation

-

void +

void setOwner(IReferenceCounted* o)

-

{

-

owner +

{

+

owner = o;

-

}

-


+

}

+


-

IReferenceCounted* +

IReferenceCounted* getOwner()

-

{

-

return +

{

+

return owner;

-

}

-

+

}

+

As it was promised implementation of IPluginBase is trivial.

-


+


-

// +

// ISomePlugin implementation

-

// +

// … here go various methods required for particular plugin type

-


+


-

private:

-

IPluginConfig* +

private:

+

IPluginConfig* config;

-

FbSampleAtomic +

FbSampleAtomic refCounter;

-

IReferenceCounted* +

IReferenceCounted* owner;

-

};

-


+

};

+


-

With +

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.

-


+


Plugin's factory.

-

One +

One more interface required for plugin to work is IPluginFactory. Factory creates instances of plugin and returns them to plugin manager. Factory typically looks this way:

-

class +

class Factory : public IPluginFactoryImpl<Factory, CheckStatusWrapper>

-

{

-

public:

-

IPluginBase* +

{

+

public:

+

IPluginBase* createPlugin(CheckStatusWrapper* status, IPluginConfig* factoryParameter)

-

{

-

MyPlugin* +

{

+

MyPlugin* p = new MyPlugin(factoryParameter);

-

p->addRef();

-

return +

p->addRef();

+

return p;

-

}

-

};

-


+

}

+

};

+


-

+

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) @@ -1625,27 +1632,27 @@ 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.

-


+


Plugin module initialization entrypoint.

-

When +

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:

-

PluginModule +

PluginModule module;

-

Factory +

Factory factory;

-

If +

If you module contains more than one plugin you will need a factory per each plugin.

-


+


-

For +

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 @@ -1653,20 +1660,20 @@ 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:

-

extern +

extern "C" void FB_DLL_EXPORT FB_PLUGIN_ENTRY_POINT(IMaster* master)

-

{

-

IPluginManager* +

{

+

IPluginManager* pluginManager = master->getPluginManager();

-


+


-

module.registerMe(pluginManager);

-

pluginManager->registerPluginFactory(IPluginManager::TYPE_DB_CRYPT, +

module.registerMe(pluginManager);

+

pluginManager->registerPluginFactory(IPluginManager::TYPE_DB_CRYPT, "DbCrypt_example", &factory);

-

}

-

First +

}

+

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 @@ -1676,88 +1683,100 @@ 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.

-


+


-

Pay +

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.

-


+


-


+


-

+

Interfaces: from A to Z

-

In +

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.

-


+


Generic interfaces.

-

Attachment +

Attachment interface – replaces isc_db_handle:

    -
  1. void +

  2. +

    void getInfo(StatusType* status, unsigned itemsLength, const unsigned char* items, unsigned bufferLength, unsigned char* buffer) – replaces isc_database_info().

    -
  3. ITransaction* +

  4. +

    ITransaction* startTransaction(StatusType* status, unsigned tpbLength, const unsigned char* tpb) – partially replaces isc_start_multiple(), to start >1 transaction distributed transactions coordinator should be used, also possible to join 2 transactions into single distributed transaction.

    -
  5. ITransaction* +

  6. +

    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.

    -
  7. IRequest* +

  8. +

    IRequest* compileRequest(StatusType* status, unsigned blrLength, const unsigned char* blr) – support of ISC API.

    -
  9. void +

  10. +

    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.

    -
  11. IBlob* +

  12. +

    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().

    -
  13. IBlob* +

  14. +

    IBlob* openBlob(StatusType* status, ITransaction* transaction, ISC_QUAD* id, unsigned bpbLength, const unsigned char* bpb) – opens existing blob, replaces isc_open_blob2().

    -
  15. int +

  16. +

    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.

    -
  17. void +

  18. +

    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.

    -
  19. void +

  20. +

    void executeDyn(StatusType* status, ITransaction* transaction, unsigned length, const unsigned char* dyn) - support of ISC API.

    -
  21. IStatement* +

  22. +

    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).

    -
  23. ITransaction* +

  24. +

    ITransaction* execute(StatusType* status, ITransaction* transaction, unsigned stmtLength, const char* sqlStmt, unsigned dialect, IMessageMetadata* inMetadata, void* inBuffer, IMessageMetadata* outMetadata, void* @@ -1765,7 +1784,8 @@ interface – replaces isc_db_handle:

    rows of data. Partial analogue of isc_dsql_execute2() - in and out XSLQDAs replaced with input and output messages with appropriate buffers.

    -
  25. IResultSet* +

  26. +

    IResultSet* openCursor(StatusType* status, ITransaction* transaction, unsigned stmtLength, const char* sqlStmt, unsigned dialect, IMessageMetadata* inMetadata, void* inBuffer, IMessageMetadata* outMetadata, const @@ -1777,7 +1797,8 @@ interface – replaces isc_db_handle:

    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.

    -
  27. IBatch* +

  28. +

    IBatch* createBatch(StatusType* status, ITransaction* transaction, unsigned stmtLength, const char* sqlStmt, unsigned dialect, IMessageMetadata* inMetadata, unsigned parLength, @@ -1786,38 +1807,45 @@ interface – replaces isc_db_handle:

    inMetadata format. Leaving inMetadata
    NULL makes batch use default format for sqlStmt. Parameters block may be passed to createBatch() making it possible to adjust batch behavior.

    -
  29. IEvents* +

  30. +

    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.

    -
  31. void +

  32. +

    void cancelOperation(StatusType* status, int option) – replaces fb_cancel_operation().

    -
  33. void +

  34. +

    void ping(StatusType* status) – check connection status. If test fails the only operation possible with attachment is to close it.

    -
  35. void +

  36. +

    void detach(StatusType* status) – replaces isc_detach_database(). On success releases interface.

    -
  37. void +

  38. +

    void dropDatabase(StatusType* status) - replaces isc_drop_database(). On success releases interface.

-


+


-

Batch +

Batch interface – makes it possible to process multiple sets of parameters in single statement execution.

    -
  1. void +

  2. +

    void add(StatusType* status, unsigned 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 BUFFER_BYTES_SIZE parameter of batch creation.

    -
  3. void +

  4. +

    void addBlob(StatusType* status, unsigned length, const void* inBuffer, ISC_QUAD* blobId, unsigned bpbLength, const unsigned char* bpb) – adds single blob having length bytes from @@ -1830,11 +1858,13 @@ parameters in single statement execution.

    of batch creation (affects all blob-oriented methods except registerBlob()).

    -
  5. void +

  6. +

    void appendBlobData(StatusType* status, unsigned length, const void* inBuffer) – extend last added blob: append length bytes taken from inBuffer address to it.

    -
  7. void +

  8. +

    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 @@ -1847,7 +1877,8 @@ parameters in single statement execution.

    multiple addBlobStream() calls. Blob data in turn may be structured in case of segmented blob, see chapter “Modifying data in a batch”.

    -
  9. void +

  10. +

    void registerBlob(StatusType* status, const ISC_QUAD* existingBlob, ISC_QUAD* blobId) – makes it possible to use in batch blobs added using standard Blob interface. This function @@ -1855,7 +1886,8 @@ parameters in single statement execution.

    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.

    -
  11. IBatchCompletionState* +

  12. +

    IBatchCompletionState* execute(StatusType* status, ITransaction* transaction) – execute batch with parameters passed to it in the messages. If parameter MULTIERROR is not set in parameters block @@ -1864,64 +1896,70 @@ parameters in single statement execution.

    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.

    -
  13. void +

  14. +

    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.

    -
  15. unsigned +

  16. +

    unsigned getBlobAlignment(StatusType* status) – returns required alignment for the data placed into the buffer of addBlobStream().

    -
  17. IMessageMetadata* +

  18. +

    IMessageMetadata* getMetadata(StatusType* status) – return format of metadata used in batch’s messages.

    -
  19. void +

  20. +

    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.

-

Tag +

Tag for parameters block:

-

VERSION1

-

Tags +

VERSION1

+

Tags for clumplets in parameters block:

-

MULTIERROR +

MULTIERROR (0/1) – can have >1 message with errors

-

RECORD_COUNTS +

RECORD_COUNTS (0/1) - per-message modified records accounting

-

BUFFER_BYTES_SIZE +

BUFFER_BYTES_SIZE (integer) - maximum possible buffer size (default 10Mb, maximum 40Mb)

-

BLOB_IDS +

BLOB_IDS - policy used to store blobs

-

DETAILED_ERRORS +

DETAILED_ERRORS (integer) - how many vectors with detailed error info are stored in completion state (default 64, maximum 256)

-

Policies +

Policies used to store blobs:

-

BLOB_IDS_NONE +

BLOB_IDS_NONE – inline blobs can't be used (registerBlob() works anyway)

-

BLOB_IDS_ENGINE +

BLOB_IDS_ENGINE - blobs are added one by one, IDs are generated by firebird engine

-

BLOB_IDS_USER +

BLOB_IDS_USER - blobs are added one by one, IDs are generated by user

-

BLOB_IDS_STREAM +

BLOB_IDS_STREAM - blobs are added in a stream, IDs are generated by user

-


+


-

BatchCompletionState +

BatchCompletionState – disposable interface, always returned by execute() method of Batch interface. It contains more or less (depending upon parameters passed when Batch was created) detailed information about the results of batch execution.

-

{

+

{

    -
  1. uint +

  2. +

    uint getSize(StatusType* status) – returns the total number of processed messages.

    -
  3. int +

  4. +

    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 @@ -1929,14 +1967,16 @@ created) detailed information about the results of batch execution.

    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.

    -
  5. uint +

  6. +

    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 parameter of batch creation.

    -
  7. void +

  8. +

    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 @@ -1945,193 +1985,218 @@ created) detailed information about the results of batch execution.

    that status is returned in separate ‘to’ parameter unlike errors in this call that are placed into ‘status’ parameter.

-

Special +

Special values returned by getState():

-

EXECUTE_FAILED +

EXECUTE_FAILED - error happened when processing this message

-

SUCCESS_NO_INFO +

SUCCESS_NO_INFO - record update info was not collected

-

Special +

Special value returned by findError():

-

NO_MORE_ERRORS +

NO_MORE_ERRORS – no more messages with errors in this batch

-


+


-

Blob +

Blob interface – replaces isc_blob_handle:

    -
  1. void +

  2. +

    void getInfo(StatusType* status, unsigned itemsLength, const unsigned char* items, unsigned bufferLength, unsigned char* buffer) – replaces isc_blob_info().

    -
  3. int +

  4. +

    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 completion codes IStatus::RESULT_NO_DATA and IStatus::RESULT_SEGMENT, normal return is IStatus::RESULT_OK.

    -
  5. void +

  6. +

    void putSegment(StatusType* status, unsigned length, const void* buffer) – replaces isc_put_segment().

    -
  7. void +

  8. +

    void cancel(StatusType* status) – replaces isc_cancel_blob(). On success releases interface.

    -
  9. void +

  10. +

    void close(StatusType* status) – replaces isc_close_blob(). On success releases interface.

    -
  11. int +

  12. +

    int seek(StatusType* status, int mode, int offset) – replaces isc_seek_blob().

-


+


-


+


-

Config +

Config interface – generic configuration file interface:

    -
  1. IConfigEntry* +

  2. +

    IConfigEntry* find(StatusType* status, const char* name) – find entry by name.

    -
  3. IConfigEntry* +

  4. +

    IConfigEntry* findValue(StatusType* status, const char* name, const char* value) – find entry by name and value.

    -
  5. IConfigEntry* +

  6. +

    IConfigEntry* findPos(StatusType* status, const char* name, unsigned pos) – find entry by name and position. If configuration file contains lines:

-

Db=DBA

-

Db=DBB

-

Db=DBC

-

call +

Db=DBA

+

Db=DBB

+

Db=DBC

+

call to findPos(status, “Db”, 2) will return entry with value DBB.

-


+


-


+


-

ConfigManager +

ConfigManager interface – generic interface to access various configuration objects:

    -
  1. const +

  2. +

    const char* getDirectory(unsigned code) – returns location of appropriate directory in current firebird instance. See codes for this call a few lines later.

    -
  3. IFirebirdConf* +

  4. +

    IFirebirdConf* getFirebirdConf() - returns interface to access default configuration values (from firebird.conf).

    -
  5. IFirebirdConf* +

  6. +

    IFirebirdConf* getDatabaseConf(const char* dbName) - returns interface to access db-specific configuration (takes into an account firebird.conf and appropriate part of databases.conf).

    -
  7. IConfig* +

  8. +

    IConfig* getPluginConfig(const char* configuredPlugin) – returns interface to access named plugin configuration.

    -
  9. const +

  10. +

    const char* getInstallDirectory() - returns directory where firebird is installed.

    -
  11. const +

  12. +

    const char* getRootDirectory() - returns root directory of current instance, in single-instance case usually matches install directory.

    -
  13. const +

  14. +

    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.

-

Directory +

Directory codes:

-

DIR_BIN +

DIR_BIN – bin (utilities like isql, gbak, gstat)

-

DIR_SBIN +

DIR_SBIN – sbin (fbguard and firebird server)

-

DIR_CONF +

DIR_CONF – configuration files (firebird.conf, databases.conf, plugins.conf)

-

DIR_LIB +

DIR_LIB – lib (fbclient, ib_util)

-

DIR_INC +

DIR_INC – include (ibase.h, firebird/Interfaces.h)

-

DIR_DOC +

DIR_DOC - documentation

-

DIR_UDF +

DIR_UDF – UDF (ib_udf, fbudf)

-

DIR_SAMPLE +

DIR_SAMPLE - samples

-

DIR_SAMPLEDB +

DIR_SAMPLEDB – samples database (employee.fdb)

-

DIR_HELP +

DIR_HELP – qli help (help.fdb)

-

DIR_INTL +

DIR_INTL – international libraries (fbintl)

-

DIR_MISC +

DIR_MISC – miscellaneous files (like uninstall manifest and something else)

-

DIR_SECDB +

DIR_SECDB – where security database is stored (securityN.fdb)

-

DIR_MSG +

DIR_MSG – where messages file is stored (firebird.msg)

-

DIR_LOG +

DIR_LOG – where log file is stored (firebird.log)

-

DIR_GUARD +

DIR_GUARD – where guardian lock is stored (fb_guard)

-

DIR_PLUGINS +

DIR_PLUGINS – plugins directory ([lib]Engine13.{dll|so})

-


+


-


+


-

ConfigEntry +

ConfigEntry interface – represents an entry (Key = Values with probably sub-entries) in firebird configuration file:

    -
  1. const +

  2. +

    const char* getName() - returns key name.

    -
  3. const +

  4. +

    const char* getValue() - returns value as character string.

    -
  5. ISC_INT64 +

  6. +

    ISC_INT64 getIntValue() - treats value as integer and returns it.

    -
  7. FB_BOOLEAN +

  8. +

    FB_BOOLEAN getBoolValue() - treats value as boolean and returns it.

    -
  9. IConfig* +

  10. +

    IConfig* getSubConfig(StatusType* status) – treats sub-entries as separate configuration file and returns Config interface for it.

-


+


-

+

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:

    -
  1. void +

  2. +

    void toBcd(const FB_DEC16* from, int* sign, unsigned char* bcd, int* exp) – convert decimal float value to BCD.

    -
  3. void +

  4. +

    void toString(StatusType* status, const FB_DEC16* from, unsigned bufferLength, char* buffer) – convert decimal float value to string.

    -
  5. void +

  6. +

    void fromBcd(int sign, const unsigned char* bcd, int exp, FB_DEC16* to) – make decimal float value from BCD.

    -
  7. void +

  8. +

    void fromString(StatusType* status, const char* from, FB_DEC16* to) – make decimal float value from string.

-


+


-


+


-

Dtc +

Dtc 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 @@ -2139,75 +2204,82 @@ 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.

    -
  1. ITransaction* +

  2. +

    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.

    -
  3. IDtcStart* +

  4. +

    IDtcStart* startBuilder(StatusType* status) – returns DtcStart interface.

-


+


-


+


-

DtcStart +

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.

    -
  1. void +

  2. +

    void addAttachment(StatusType* status, IAttachment* att) – adds attachment, transaction for it will be started with default TPB.

    -
  3. void +

  4. +

    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.

    -
  5. ITransaction* +

  6. +

    ITransaction* start(StatusType* status) – start distributed transaction for accumulated attachments. On successful return DtcStart interface is disposed automatically.

-


+


-


+


-

EventCallback +

EventCallback interface – replaces callback function used in isc_que_events() call. Should be implemented by user to monitor events with IAttachment::queEvents() method.

    -
  1. void +

  2. +

    void eventCallbackFunction(unsigned length, const unsigned char* events) – is called each time event happens.

-


+


-


+


-

Events +

Events interface – replaces event identifier when working with events monitoring.

    -
  1. void +

  2. +

    void cancel(StatusType* status) - cancels events monitoring started by IAttachment::queEvents().

-


+


-


+


-

FirebirdConf +

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 @@ -2217,18 +2289,23 @@ server run (i.e. plugin can get it once and than use to get configuration value for different databases).

    -
  1. unsigned +

  2. +

    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.

    -
  3. ISC_INT64 +

  4. +

    ISC_INT64 asInteger(unsigned key) – return value of integer parameter.

    -
  5. const +

  6. +

    const char* asString(unsigned key) - return value of string parameter.

    -
  7. FB_BOOLEAN +

  8. +

    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.

    -
  9. unsigned +

  10. +

    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 @@ -2236,252 +2313,302 @@ configuration value for different databases). (see getKey()) from different versions do not match and when used inappropriately will always return 0/nullptr/false.

-


+


-


+


-

Int128 +

Int128 interfaces that help to work with 128-bit integers (used as base type for numeric and decimal with precision > 18).

    -
  1. void +

  2. +

    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.

    -
  3. void +

  4. +

    void fromString(StatusType* status, int scale, const char* from, FB_I128* to) – make 128-bit integer value from string taking scale into an account.

-


+


-


+


-

Master +

Master interface – main interface from which start all operations with firebird API.

    -
  1. IStatus* +

  2. +

    IStatus* getStatus() - get instance if Status interface.

    -
  3. IProvider* +

  4. +

    IProvider* getDispatcher() - get instance of Provider interface, implemented by yValve (main provider instance).

    -
  5. IPluginManager* +

  6. +

    IPluginManager* getPluginManager() - get instance of PluginManager interface.

    -
  7. ITimerControl* +

  8. +

    ITimerControl* getTimerControl() - get instance of TimerControl interface.

    -
  9. IDtc* +

  10. +

    IDtc* getDtc() - get instance of Dtc interface.

    -
  11. IUtil* +

  12. +

    IUtil* getUtilInterface() - get instance of Util interface.

    -
  13. IConfigManager* +

  14. +

    IConfigManager* getConfigManager() - get instance of ConfigManager interface.

-


+


-


+


-

MessageMetadata +

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.

    -
  1. unsigned +

  2. +

    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().

    -
  3. const +

  4. +

    const char* getField(StatusType* status, unsigned index) – returns field name.

    -
  5. const +

  6. +

    const char* getRelation(StatusType* status, unsigned index) – returns relation name (from which given field is selected).

    -
  7. const +

  8. +

    const char* getOwner(StatusType* status, unsigned index) - returns relation's owner name.

    -
  9. const +

  10. +

    const char* getAlias(StatusType* status, unsigned index) - returns field alias.

    -
  11. unsigned +

  12. +

    unsigned getType(StatusType* status, unsigned index) - returns field SQL type.

    -
  13. FB_BOOLEAN +

  14. +

    FB_BOOLEAN isNullable(StatusType* status, unsigned index) - returns true if field is nullable.

    -
  15. int +

  16. +

    int getSubType(StatusType* status, unsigned index) - returns blof field subtype (0 – binary, 1 – text, etc.).

    -
  17. unsigned +

  18. +

    unsigned getLength(StatusType* status, unsigned index) - returns maximum field length.

    -
  19. int +

  20. +

    int getScale(StatusType* status, unsigned index) - returns scale factor for numeric field.

    -
  21. unsigned +

  22. +

    unsigned getCharSet(StatusType* status, unsigned index) - returns character set for character field and text blob.

    -
  23. unsigned +

  24. +

    unsigned getOffset(StatusType* status, unsigned index) - returns offset of field data in message buffer (use it to access data in message buffer).

    -
  25. unsigned +

  26. +

    unsigned getNullOffset(StatusType* status, unsigned index) - returns offset of null indicator for a field in message buffer.

    -
  27. IMetadataBuilder* +

  28. +

    IMetadataBuilder* getBuilder(StatusType* status) - returns MetadataBuilder interface initialized with this message metadata.

    -
  29. unsigned +

  30. +

    unsigned getMessageLength(StatusType* status) - returns length of message buffer (use it to allocate memory for the buffer).

    -
  31. unsigned +

  32. +

    unsigned getAlignment(StatusType* status) – returns alignment required for message buffer.

    -
  33. unsigned +

  34. +

    unsigned 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).

-


+


-


+


-

MetadataBuilder +

MetadataBuilder interface – makes it possible to coerce datatypes in existing message or construct metadata from the beginning.

    -
  1. void +

  2. +

    void setType(StatusType* status, unsigned index, unsigned type) – set SQL type of a field.

    -
  3. void +

  4. +

    void setSubType(StatusType* status, unsigned index, int subType) – set blof field subtype.

    -
  5. void +

  6. +

    void setLength(StatusType* status, unsigned index, unsigned length) – set maximum length of character field.

    -
  7. void +

  8. +

    void setCharSet(StatusType* status, unsigned index, unsigned charSet) – set character set for character field and text blob.

    -
  9. void +

  10. +

    void setScale(StatusType* status, unsigned index, unsigned scale) – set scale factor for numeric field

    -
  11. void +

  12. +

    void truncate(StatusType* status, unsigned count) – truncate message to contain not more than count fields.

    -
  13. void +

  14. +

    void moveNameToIndex(StatusType* status, const char* name, unsigned index) – reorganize fields in a message – move field “name” to given position.

    -
  15. void +

  16. +

    void remove(StatusType* status, unsigned index) – remove field.

    -
  17. unsigned +

  18. +

    unsigned addField(StatusType* status) – add field.

    -
  19. IMessageMetadata* +

  20. +

    IMessageMetadata* getMetadata(StatusType* status) – get MessageMetadata interface built by this builder.

    -
  21. void +

  22. +

    void setField(StatusType* status, uint index, const string field) – set name of a field / column.

    -
  23. void +

  24. +

    void setRelation(StatusType* status, uint index, const string relation) – set name of the relation from which the field was selected.

    -
  25. void +

  26. +

    void setOwner(StatusType* status, uint index, const string owner) – set name of that relation owner.

    -
  27. void +

  28. +

    void setAlias(StatusType* status, uint index, const string alias) – set alias name of the field in related statement.

-


+


-


+


-

OffsetsCallback +

OffsetsCallback interface:

    -
  1. setOffset(StatusType* +

  2. +

    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 MessageMetadata interface and using Util::setOffsets().

-


+


-


+


-

PluginConfig +

PluginConfig interface – passed to plugin's factory when plugin instance (with particular configuration) to be created.

    -
  1. const +

  2. +

    const char* getConfigFileName() - recommended file name where configuration for plugin is expected to be stored.

    -
  3. IConfig* +

  4. +

    IConfig* getDefaultConfig(StatusType* status) – plugin configuration loaded with default rules.

    -
  5. IFirebirdConf* +

  6. +

    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.

    -
  7. void +

  8. +

    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.

-


+


-


+


-

PluginFactory +

PluginFactory interface – should be implemented by plugin author when writing plugin.

    -
  1. IPluginBase* +

  2. +

    IPluginBase* createPlugin(StatusType* status, IPluginConfig* factoryParameter) – creates new instance of plugin with passed recommended configuration.

-


+


-


+


-

PluginManager +

PluginManager interface – API of plugin manager.

    -
  1. void +

  2. +

    void registerPluginFactory(unsigned pluginType, const char* defaultName, IPluginFactory* factory) – registers named factory of plugins of given type.

    -
  3. void +

  4. +

    void registerModule(IPluginModule* cleanup) – registers plugin module.

    -
  5. void +

  6. +

    void unregisterModule(IPluginModule* cleanup) – unregisters plugin module (in case of unexpected unload by OS).

    -
  7. IPluginSet* +

  8. +

    IPluginSet* getPlugins(StatusType* status, unsigned pluginType, const char* namesList, IFirebirdConf* firebirdConf) – returns PluginSet interface providing access to list of plugins of given type. Names @@ -2492,62 +2619,68 @@ interface – API of plugin manager.

    PluginFactory::createPlugin() method), if missing (NULL) – default configuration (from firebird.conf) is used.

    -
  9. IConfig* +

  10. +

    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.

    -
  11. void +

  12. +

    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.

-


+


-

Constants +

Constants defined by PluginManager interface (plugin types):

-

TYPE_PROVIDER

-

TYPE_AUTH_SERVER

-

TYPE_AUTH_CLIENT

-

TYPE_AUTH_USER_MANAGEMENT

-

TYPE_EXTERNAL_ENGINE

-

TYPE_TRACE

-

TYPE_WIRE_CRYPT

-

TYPE_DB_CRYPT

-

TYPE_KEY_HOLDER

-


+

TYPE_PROVIDER

+

TYPE_AUTH_SERVER

+

TYPE_AUTH_CLIENT

+

TYPE_AUTH_USER_MANAGEMENT

+

TYPE_EXTERNAL_ENGINE

+

TYPE_TRACE

+

TYPE_WIRE_CRYPT

+

TYPE_DB_CRYPT

+

TYPE_KEY_HOLDER

+


-


+


-

PluginModule +

PluginModule interface – represents plugin module (dynamic library). Should be implemented by plugin author in each plugin module (one instance per module).

    -
  1. void +

  2. +

    void doClean() - called by plugin manager before normal unload of plugin module.

-


+


-


+


-

PluginSet +

PluginSet interface – represents set of plugins of given type. Typically used by internal firebird code but recommended for use in plugins loading other plugins.

    -
  1. const +

  2. +

    const char* getName() - get name of current plugin in a set.

    -
  3. const +

  4. +

    const char* getModuleName() - get name of a module of current plugin in a set (in simple case matches plugin name).

    -
  5. IPluginBase* +

  6. +

    IPluginBase* getPlugin(StatusType* status) – get an instance of current plugin, returned interface should be casted to main interface of plugin of requested in PluginManager::getPlugins() @@ -2556,151 +2689,179 @@ other plugins.

    incremented on return – do not forget to use releasePlugin() method of PluginManager for plugins returned by this method.

    -
  7. void +

  8. +

    void next(StatusType* status) – make set to switch to next plugin from the list.

    -
  9. void +

  10. +

    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.

-


+


-


+


-

Provider +

Provider interface – main interface to start database / service access.

    -
  1. IAttachment* +

  2. +

    IAttachment* attachDatabase(StatusType* status, const char* fileName, unsigned dpbLength, const unsigned char* dpb) – replaces isc_attach_database().

    -
  3. IAttachment* +

  4. +

    IAttachment* createDatabase(StatusType* status, const char* fileName, unsigned dpbLength, const unsigned char* dpb) – replaces isc_create_database().

    -
  5. IService* +

  6. +

    IService* attachServiceManager(StatusType* status, const char* service, unsigned spbLength, const unsigned char* spb) – replaces isc_service_attach().

    -
  7. void +

  8. +

    void shutdown(StatusType* status, unsigned timeout, const int reason) – replaces fb_shutdown().

    -
  9. void +

  10. +

    void setDbCryptCallback(StatusType* status, ICryptKeyCallback* cryptCallback) – sets database encryption callback interface that will be used for following database and service attachments. See … for details.

-


+


-


+


-

ResultSet +

ResultSet interface – replaces (with extended functionality) some functions of isc_stmt_handle. This interface is returned by openCursor() call in IAttachment or IStatement. All fetch calls except fetchNext() work only for bidirectional (opened with CURSOR_TYPE_SCROLLABLE flag) result set.

    -
  1. int +

  2. +

    int fetchNext(StatusType* status, void* message) – fetch next record, replaces isc_dsql_fetch(). This method (and other fetch methods) returns completion code Status::RESULT_NO_DATA when EOF is reached, Status::RESULT_OK on success.

    -
  3. int +

  4. +

    int fetchPrior(StatusType* status, void* message) – fetch previous record.

    -
  5. int +

  6. +

    int fetchFirst(StatusType* status, void* message) – fetch first record.

    -
  7. int +

  8. +

    int fetchLast(StatusType* status, void* message) – fetch last record.

    -
  9. int +

  10. +

    int fetchAbsolute(StatusType* status, int position, void* message) – fetch record by it's absolute position in result set.

    -
  11. int +

  12. +

    int fetchRelative(StatusType* status, int offset, void* message) – fetch record by position relative to current.

    -
  13. FB_BOOLEAN +

  14. +

    FB_BOOLEAN isEof(StatusType* status) – check for EOF.

    -
  15. FB_BOOLEAN +

  16. +

    FB_BOOLEAN isBof(StatusType* status) – check for BOF.

    -
  17. IMessageMetadata* +

  18. +

    IMessageMetadata* getMetadata(StatusType* status) – get metadata for messages in result set, specially useful when result set is opened by IAttachment::openCursor() call with NULL output metadata format parameter (this is the only way to obtain message format in this case).

    -
  19. void +

  20. +

    void close(StatusType* status) – close result set, releases interface on success.

-


+


-


+


-

Service +

Service interface – replaces isc_svc_handle.

    -
  1. void +

  2. +

    void detach(StatusType* status) – close attachment to services manager, on success releases interface. Replaces isc_service_detach().

    -
  3. void +

  4. +

    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().

    -
  5. void +

  6. +

    void start(StatusType* status, unsigned spbLength, const unsigned char* spb) – start utility in services manager. Replaces isc_service_start().

-


+


-


+


-

Statement +

Statement interface – replaces (partially) isc_stmt_handle.

    -
  1. void +

  2. +

    void getInfo(StatusType* status, unsigned itemsLength, const unsigned char* items, unsigned bufferLength, unsigned char* buffer) – replaces isc_dsql_sql_info().

    -
  3. unsigned +

  4. +

    unsigned getType(StatusType* status) – statement type, currently can be found only in firebird sources in dsql/dsql.h.

    -
  5. const +

  6. +

    const char* getPlan(StatusType* status, FB_BOOLEAN detailed) – returns statement execution plan.

    -
  7. ISC_UINT64 +

  8. +

    ISC_UINT64 getAffectedRecords(StatusType* status) – returns number of records affected by statement.

    -
  9. IMessageMetadata* +

  10. +

    IMessageMetadata* getInputMetadata(StatusType* status) – returns parameters metadata.

    -
  11. IMessageMetadata* +

  12. +

    IMessageMetadata* getOutputMetadata(StatusType* status) – returns output values metadata.

    -
  13. ITransaction* +

  14. +

    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.

    -
  15. IResultSet* +

  16. +

    IResultSet* openCursor(StatusType* status, ITransaction* transaction, IMessageMetadata* inMetadata, void* inBuffer, IMessageMetadata* outMetadata, unsigned flags) – executes SQL statement potentially @@ -2709,7 +2870,8 @@ interface – replaces (partially) isc_stmt_handle.

    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.

    -
  17. IBatch* +

  18. +

    IBatch* createBatch(StatusType* status, IMessageMetadata* inMetadata, uint parLength, const uchar* par) – creates Batch interface to SQL statement with input parameters making it possible @@ -2718,80 +2880,92 @@ interface – replaces (partially) isc_stmt_handle.

    makes batch use default format from this interface. Parameters block may be passed to createBatch() making it possible to adjust batch behavior.

    -
  19. void +

  20. +

    void setCursorName(StatusType* status, const char* name) – replaces isc_dsql_set_cursor_name().

    -
  21. void +

  22. +

    void free(StatusType* status) – free statement, releases interface on success.

    -
  23. unsigned +

  24. +

    unsigned getFlags(StatusType* status) – returns flags describing how this statement should be executed, simplified replacement of getType() method.

-


+


-


+


-

Constants +

Constants defined by Statement interface:

-


+


-

IAttachment::prepare() +

IAttachment::prepare() flags:

-

+

PREPARE_PREFETCH_NONE – constant to pass no flags, 0 value.

-

The +

The following flags may be OR-ed to get desired set of flags:

    -
  1. PREPARE_PREFETCH_TYPE

    -
  2. PREPARE_PREFETCH_INPUT_PARAMETERS

    -
  3. PREPARE_PREFETCH_OUTPUT_PARAMETERS

    -
  4. PREPARE_PREFETCH_LEGACY_PLAN

    -
  5. PREPARE_PREFETCH_DETAILED_PLAN

    -
  6. PREPARE_PREFETCH_AFFECTED_RECORDS

    -
  7. PREPARE_PREFETCH_FLAGS +

  8. +

    PREPARE_PREFETCH_TYPE

    +
  9. +

    PREPARE_PREFETCH_INPUT_PARAMETERS

    +
  10. +

    PREPARE_PREFETCH_OUTPUT_PARAMETERS

    +
  11. +

    PREPARE_PREFETCH_LEGACY_PLAN

    +
  12. +

    PREPARE_PREFETCH_DETAILED_PLAN

    +
  13. +

    PREPARE_PREFETCH_AFFECTED_RECORDS

    +
  14. +

    PREPARE_PREFETCH_FLAGS (flags returned by getFlags() method)

-

Frequently +

Frequently used combinations of flags:

    -
  1. PREPARE_PREFETCH_METADATA

    -
  2. PREPARE_PREFETCH_ALL +

  3. +

    PREPARE_PREFETCH_METADATA

    +
  4. +

    PREPARE_PREFETCH_ALL

-


+


-

+

Values returned by getFlags() method:

-

FLAG_HAS_CURSOR +

FLAG_HAS_CURSOR – use openCursor() to execute this statement, not execute()

-

FLAG_REPEAT_EXECUTE +

FLAG_REPEAT_EXECUTE – when prepared statement may be executed many times with different parameters

-


+


-

+

Flags passed to openCursor():

-

CURSOR_TYPE_SCROLLABLE +

CURSOR_TYPE_SCROLLABLE – open bidirectional cursor.

-


+


-


+


-

Status +

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 @@ -2802,73 +2976,83 @@ Interface is on purpose minimized (methods like convert it to text are moved to Util interface) in order to simplify it's implementation by users when needed.

    -
  1. void +

  2. +

    void init() - cleanup interface, set it to initial state.

    -
  3. unsigned +

  4. +

    unsigned getState() - get current state of interface, returns state flags, may be OR-ed.

    -
  5. void +

  6. +

    void setErrors2(unsigned length, const intptr_t* value) – set contents of errors vector with length explicitly specified in a call.

    -
  7. void +

  8. +

    void setWarnings2(unsigned length, const intptr_t* value) – set contents of warnings vector with length explicitly specified in a call.

    -
  9. void +

  10. +

    void setErrors(const intptr_t* value) – set contents of errors vector, length is defined by value context.

    -
  11. void +

  12. +

    void setWarnings(const intptr_t* value) – set contents of warnings vector, length is defined by value context.

    -
  13. const +

  14. +

    const intptr_t* getErrors() - get errors vector.

    -
  15. const +

  16. +

    const intptr_t* getWarnings() - get warnings vector.

    -
  17. IStatus* +

  18. +

    IStatus* clone() - create clone of current interface.

-


+


-

Constants +

Constants defined by Status interface:

-


+


-

Flags +

Flags set in the value, returned by getState() method:

-

STATE_WARNINGS

-

STATE_ERRORS

-


+

STATE_WARNINGS

+

STATE_ERRORS

+


-

Completion +

Completion codes:

-

RESULT_ERROR

-

RESULT_OK

-

RESULT_NO_DATA

-

RESULT_SEGMENT

-


+

RESULT_ERROR

+

RESULT_OK

+

RESULT_NO_DATA

+

RESULT_SEGMENT

+


-


+


-

Timer +

Timer interface – user timer. Callback interface which should be implemented by user to use firebird timer.

    -
  1. void +

  2. +

    void handler() - method is called when timer rings (or when server is shutting down).

-


+


-


+


-

TimerControl +

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 @@ -2876,284 +3060,331 @@ 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.

    -
  1. void +

  2. +

    void start(StatusType* status, ITimer* timer, ISC_UINT64 microSeconds) – start ITimer to alarm after given delay (in microseconds, 10-6 seconds). Timer will be waked up only once after this call.

    -
  3. void +

  4. +

    void stop(StatusType* status, ITimer* timer) – stop ITimer. It's not an error to stop not started timer thus avoiding problems with races between stop() and timer alarm.

-


+


-

Transaction +

Transaction interface – replaces isc_tr_handle.

    -
  1. void +

  2. +

    void getInfo(StatusType* status, unsigned itemsLength, const unsigned char* items, unsigned bufferLength, unsigned char* buffer) – replaces isc_transaction_info().

    -
  3. void +

  4. +

    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.

    -
  5. void +

  6. +

    void commit(StatusType* status) – replaces isc_commit_transaction().

    -
  7. void +

  8. +

    void commitRetaining(StatusType* status) – replaces isc_commit_retaining().

    -
  9. void +

  10. +

    void rollback(StatusType* status) – replaces isc_rollback_transaction().

    -
  11. void +

  12. +

    void rollbackRetaining(StatusType* status) – replaces isc_rollback_retaining().

    -
  13. void +

  14. +

    void disconnect(StatusType* status) – replaces fb_disconnect_transaction().

    -
  15. ITransaction* +

  16. +

    ITransaction* join(StatusType* status, ITransaction* transaction) – joins current transaction and passed as parameter transaction into single distributed transaction (using Dtc). On success both current transaction and passed as parameter transaction are released and should not be used any more.

    -
  17. ITransaction* +

  18. +

    ITransaction* validate(StatusType* status, IAttachment* attachment) – this method is used to support distributed transactions coordinator.

    -
  19. ITransaction* +

  20. +

    ITransaction* enterDtc(StatusType* status) – this method is used to support distributed transactions coordinator.

-


+


-


+


-

VersionCallback +

VersionCallback interface – callback for Util::getFbVersion().

    -
  1. void +

  2. +

    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.

-


+


-


+


-

Util +

Util interface – various helper methods required here or there.

    -
  1. void +

  2. +

    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.

    -
  3. void +

  4. +

    void loadBlob(StatusType* status, ISC_QUAD* blobId, IAttachment* att, ITransaction* tra, const char* file, FB_BOOLEAN txt) – load blob from file.

    -
  5. void +

  6. +

    void dumpBlob(StatusType* status, ISC_QUAD* blobId, IAttachment* att, ITransaction* tra, const char* file, FB_BOOLEAN txt) – save blob to file.

    -
  7. void +

  8. +

    void getPerfCounters(StatusType* status, IAttachment* att, const char* countersSet, ISC_INT64* counters) – get statistics for given attachment.

    -
  9. IAttachment* +

  10. +

    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.

    -
  11. void +

  12. +

    void decodeDate(ISC_DATE date, unsigned* year, unsigned* month, unsigned* day) – replaces isc_decode_sql_date().

    -
  13. void +

  14. +

    void decodeTime(ISC_TIME time, unsigned* hours, unsigned* minutes, unsigned* seconds, unsigned* fractions) – replaces isc_decode_sql_time().

    -
  15. ISC_DATE +

  16. +

    ISC_DATE encodeDate(unsigned year, unsigned month, unsigned day) – replaces isc_encode_sql_date().

    -
  17. ISC_TIME +

  18. +

    ISC_TIME encodeTime(unsigned hours, unsigned minutes, unsigned seconds, unsigned fractions) – replaces isc_encode_sql_time().

    -
  19. unsigned +

  20. +

    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.

    -
  21. unsigned +

  22. +

    unsigned getClientVersion() – returns integer, containing major version in byte 0 and minor version in byte 1.

    -
  23. IXpbBuilder* +

  24. +

    IXpbBuilder* getXpbBuilder(StatusType* status, unsigned kind, const unsigned char* buf, unsigned len) – returns XpbBuilder interface. Valid kinds are enumerated in XpbBuilder.

    -
  25. unsigned +

  26. +

    unsigned setOffsets(StatusType* status, IMessageMetadata* metadata, IOffsetsCallback* callback) – sets valid offsets in MessageMetadata. Performs calls to callback in OffsetsCallback for each field/parameter.

    -
  27. IDecFloat16* +

  28. +

    IDecFloat16* getDecFloat16(StatusType* status) – access DecFloat16 interface.

    -
  29. IDecFloat34* +

  30. +

    IDecFloat34* getDecFloat34(StatusType* status) – access DecFloat34 interface.

    -
  31. ITransaction* - getTransactionByHandle(StatusType* status, isc_tr_handle* hndlPtr) – - access Transaction interface by ISC API - hndl.

    -
  32. IStatement* - getStatementByHandle(StatusType* status, isc_stmt_handle* hndlPtr) – - access Statement interface by ISC API hndl.

    -
  33. void +

  34. +

    void decodeTimeTz(StatusType* status, const ISC_TIME_TZ* timeTz, unsigned* hours, unsigned* minutes, unsigned* seconds, unsigned*

    -

    fractions, +

    fractions, unsigned timeZoneBufferLength, char* timeZoneBuffer) – decode time taking time zone into an account.

    -
  35. void +

  36. +

    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.

    -
  37. void +

  38. +

    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.

    -
  39. void +

  40. +

    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.

    -
  41. IInt128* +

  42. +

    IInt128* getInt128(Status status) – access Int128 interface.

    -
  43. void +

  44. +

    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.

    -
  45. void +

  46. +

    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.

-


+


-


+


-

XpbBuilder +

XpbBuilder methods:

    -
  1. void +

  2. +

    void clear(StatusType* status) – reset builder to empty state.

    -
  3. void +

  4. +

    void removeCurrent(StatusType* status) – removes current clumplet.

    -
  5. void +

  6. +

    void insertInt(StatusType* status, unsigned char tag, int value) – inserts a clumplet with value representing integer in network format.

    -
  7. void +

  8. +

    void insertBigInt(StatusType* status, unsigned char tag, ISC_INT64 value) – inserts a clumplet with value representing integer in network format.

    -
  9. void +

  10. +

    void insertBytes(StatusType* status, unsigned char tag, const void* bytes, unsigned length) - inserts a clumplet with value containing passed bytes.

    -
  11. void +

  12. +

    void insertTag(StatusType* status, unsigned char tag) – inserts a clumplet without a value.

    -
  13. FB_BOOLEAN +

  14. +

    FB_BOOLEAN isEof(StatusType* status) – checks that there is no current clumplet.

    -
  15. void +

  16. +

    void moveNext(StatusType* status) – moves to next clumplet.

    -
  17. void +

  18. +

    void rewind(StatusType* status) – moves to first clumplet.

    -
  19. FB_BOOLEAN +

  20. +

    FB_BOOLEAN findFirst(StatusType* status, unsigned char tag) – finds first clumplet with given tag.

    -
  21. FB_BOOLEAN +

  22. +

    FB_BOOLEAN findNext(StatusType* status) – finds next clumplet with given tag.

    -
  23. unsigned +

  24. +

    unsigned char getTag(StatusType* status) – returns tag for current clumplet.

    -
  25. unsigned +

  26. +

    unsigned getLength(StatusType* status) – returns length of current clumplet value.

    -
  27. int +

  28. +

    int getInt(StatusType* status) – returns value of current clumplet as integer.

    -
  29. ISC_INT64 +

  30. +

    ISC_INT64 getBigInt(StatusType* status) – returns value of current clumplet as 64-bit integer.

    -
  31. const +

  32. +

    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).

    -
  33. const +

  34. +

    const unsigned char* getBytes(StatusType* status) – returns value of current clumplet as pointer to unsigned char.

    -
  35. unsigned +

  36. +

    unsigned getBufferLength(StatusType* status) – returns length of parameters block.

    -
  37. const +

  38. +

    const unsigned char* getBuffer(StatusType* status) – returns pointer to parameters block.

-


+


-

Constants +

Constants defined by XpbBuilder interface:

-


+


-

Valid +

Valid builder types:

-

BATCH +

BATCH (IBatch parameters block)

-

BPB +

BPB (BLOB parameters block)

-

DPB +

DPB (database attachment parameters block)

-

SPB_ATTACH +

SPB_ATTACH (service attachment parameters block)

-

SPB_START +

SPB_START (start service parameters)

-

SPB_SEND +

SPB_SEND (send items in IService::query())

-

SPB_RECEIVE +

SPB_RECEIVE (receive items in IService::query())

-

SPB_RESPONSE +

SPB_RESPONSE (response from IService::query())

-

TPB +

TPB (transaction parameters block)

-


+


Plugin, encrypting data transferred over the wire.

-

Algorithms +

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 @@ -3167,10 +3398,10 @@ 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.)

-


+


-

CryptKey +

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 @@ -3180,47 +3411,55 @@ interface and stores a key in it. Appropriate for Wir type of key will be selected by firebird and passed to that interface.

    -
  1. void +

  2. +

    void setSymmetric(StatusType* status, const char* type, unsigned keyLength, const void* key) – make it store symmetric key of given type.

    -
  3. void +

  4. +

    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.

    -
  5. const +

  6. +

    const void* getEncryptKey(unsigned* length) – get a key for encryption.

    -
  7. const +

  8. +

    const void* getDecryptKey(unsigned* length) – get a key for decryption (in case of symmetric key produces same result as getEncryptKey()).

-


+


-

WireCryptPlugin +

WireCryptPlugin interface is main interface of network crypt plugin. Like any other such interface it should be implemented by author of the plugin.

    -
  1. const +

  2. +

    const char* getKnownTypes(StatusType* status) – returns whitespace/tab/comma separated list of acceptable keys.

    -
  3. void +

  4. +

    void setKey(StatusType* status, ICryptKey* key) – plugin should use a key passed to it by this call.

    -
  5. void +

  6. +

    void encrypt(StatusType* status, unsigned length, const void* from, void* to) – encrypts a packet to be sent over the wire.

    -
  7. void +

  8. +

    void decrypt(StatusType* status, unsigned length, const void* from, void* to) – decrypts a packet received from network.

-


+


Server side of authentication plugin.

-

Authentication +

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 @@ -3231,71 +3470,80 @@ 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.

-


+


-

There +

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.

-


+


-

Auth +

Auth interface does not contain methods, only some constants defining codes return from authenticate() method of Client and Server.

-

AUTH_FAILED

-

AUTH_SUCCESS

-

AUTH_MORE_DATA

-

AUTH_CONTINUE

-


+

AUTH_FAILED

+

AUTH_SUCCESS

+

AUTH_MORE_DATA

+

AUTH_CONTINUE

+


-

Writer +

Writer interface – writes authentication parameters block.

    -
  1. void +

  2. +

    void reset() - clear target block.

    -
  3. void +

  4. +

    void add(StatusType* status, const char* name) – add login name.

    -
  5. void +

  6. +

    void setType(StatusType* status, const char* value) – set type of added login (user, group, etc).

    -
  7. void +

  8. +

    void setDb(StatusType* status, const char* value) – set security database in which authentication was done.

-


+


-

ServerBlock +

ServerBlock interface is used by server side of authentication plugin to exchange data with client.

    -
  1. const +

  2. +

    const char* getLogin() - get login name passed from client.

    -
  3. const +

  4. +

    const unsigned char* getData(unsigned* length) – get authentication data passed from client.

    -
  5. void +

  6. +

    void putData(StatusType* status, unsigned length, const void* data) – pass authentication data to client.

    -
  7. ICryptKey* +

  8. +

    ICryptKey* newKey(StatusType* status) – create new wire crypt key and add it to the list of available for wire crypt plugins.

-


+


-

Server +

Server interface is main interface of server side of authentication plugin.

    -
  1. int +

  2. +

    int authenticate(StatusType* status, IServerBlock* sBlock, IWriter* writerInterface) – perform single authentication step. Data exchange with client is performed using sBlock interface. When some @@ -3303,36 +3551,42 @@ interface is main interface of server side of authentication plugin. block using writerInterface. Possible return values are defined in Auth interface.

-


+


Client side of authentication plugin.

-

ClientBlock +

ClientBlock interface is used by client side of authentication plugin to exchange data with server.

    -
  1. const +

  2. +

    const char* getLogin() - get login name if it is present in DPB.

    -
  3. const +

  4. +

    const char* getPassword() - get password if it is present in DPB.

    -
  5. const +

  6. +

    const unsigned char* getData(unsigned* length) – get authentication data passed from server.

    -
  7. void +

  8. +

    void putData(StatusType* status, unsigned length, const void* data) – pass authentication data to server.

    -
  9. ICryptKey* +

  10. +

    ICryptKey* newKey(StatusType* status) - create new wire crypt key and add it to the list of available for wire crypt plugins.

-


+


-

Client +

Client interface is main interface of client side of authentication plugin.

    -
  1. int +

  2. +

    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 @@ -3340,11 +3594,11 @@ interface is main interface of client side of authentication plugin.

    (i.e. client sends generated data to server and waits for an answer from it).

-


+


User management plugin.

-

This +

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 @@ -3353,170 +3607,198 @@ 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 User interface.

-


+


-

UserField +

UserField interface is not used as standalone interface, it's base for CharUserField and IntUserField.

    -
  1. int +

  2. +

    int entered() - returns non-zero if a value for a field was entered (assigned).

    -
  3. int +

  4. +

    int specified() - return non-zero if NULL value was assigned to the field.

    -
  5. void +

  6. +

    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.

-


+


-

CharUserField +

CharUserField interface:

    -
  1. const +

  2. +

    const char* get() - get field's value as C-string (\0 terminated).

    -
  3. void +

  4. +

    void set(StatusType* status, const char* newValue) – assigns value to the field. Sets entered flag to true.

-


+


-

IntUserField +

IntUserField interface:

    -
  1. int +

  2. +

    int get() - get field's value.

    -
  3. void +

  4. +

    void set(StatusType* status, int newValue) – assigns value to the field. Sets entered flag to true.

-


+


-

User +

User interface is a list of methods accessing fields included into record about the user.

    -
  1. unsigned +

  2. +

    unsigned operation() - code of operation (see list below).

    -
  3. ICharUserField* +

  4. +

    ICharUserField* userName() - login name.

    -
  5. ICharUserField* +

  6. +

    ICharUserField* password() - password. Always empty when listing users.

    -
  7. ICharUserField* +

  8. +

    ICharUserField* firstName() - this and 2 next are components of full user name.

    -
  9. ICharUserField* +

  10. +

    ICharUserField* lastName()

    -
  11. ICharUserField* +

  12. +

    ICharUserField* middleName()

    -
  13. ICharUserField* +

  14. +

    ICharUserField* comment() - comment (from SQL operator COMMENT ON USER IS …).

    -
  15. ICharUserField* +

  16. +

    ICharUserField* attributes() - tags in a form tag1=val1, tag2=val2, …, tagN=valN. Val may be empty – than means that tag will be deleted.

    -
  17. IIntUserField* +

  18. +

    IIntUserField* active() - changes ACTIVE/INACTIVE setting for user.

    -
  19. IIntUserField* +

  20. +

    IIntUserField* admin() - sets/drops admin rights for the user.

    -
  21. void +

  22. +

    void clear(StatusType* status) – sets all fields to not entered and not specified.

-


+


-

+

Constants defined by User interface – valid codes of operation.

-

OP_USER_ADD +

OP_USER_ADD – create user

-

OP_USER_MODIFY +

OP_USER_MODIFY – alter user

-

OP_USER_DELETE +

OP_USER_DELETE – drop user

-

OP_USER_DISPLAY +

OP_USER_DISPLAY – show user

-

OP_USER_SET_MAP +

OP_USER_SET_MAP – turn on mapping of windows admins to role rdb$admin

-

OP_USER_DROP_MAP +

OP_USER_DROP_MAP – turn off mapping of windows admins to role rdb$admin

-


+


-

ListUsers +

ListUsers interface is callback used by authentication plugin when list users operation is requested. Plugin fills User interface for all items in list of users one by one and for each user calls list() method of this interface.

    -
  1. void +

  2. +

    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.

-


+


-

LogonInfo +

LogonInfo interface contains data passed to user mamngement plugin to attach to security database with valid credentials. Pres

    -
  1. const +

  2. +

    const char* name() - returns current attachment's login name.

    -
  3. const +

  4. +

    const char* role() - returns current attachment's active role.

    -
  5. const +

  6. +

    const char* networkProtocol() - returns current attachment's network protocol. Currently not used by plugins.

    -
  7. const +

  8. +

    const char* remoteAddress() - returns current attachment's remote address. Currently not used by plugins.

    -
  9. const +

  10. +

    const unsigned char* authBlock(unsigned* length) – returns current attachment's authentication block. When not NULL overrides login name.

-


+


-

Management +

Management interface is main interface of user management plugin.

    -
  1. void +

  2. +

    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.

    -
  3. int +

  4. +

    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.

    -
  5. void +

  6. +

    void commit(StatusType* status) – commits changes done by calls to execute() method.

    -
  7. void +

  8. +

    void rollback(StatusType* status) – rollbacks changes done by calls to execute() method.

-


+


Database encryption plugin.

-

An +

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 @@ -3526,10 +3808,10 @@ 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.

-


+


-

Before +

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 @@ -3552,39 +3834,42 @@ 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.

-


+


-

CryptKeyCallback +

CryptKeyCallback interface should be provided by a side sending crypt key to db crypt plugin or key holder plugin.

    -
  1. unsigned +

  2. +

    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.

-


+


-

DbCryptInfo +

DbCryptInfo interface is passed to DbCryptPlugin by engine. Plugin may save this interface and use when needed to obtain additional informatio about database.

    -
  1. const +

  2. +

    const char* getDatabaseFullPath(StatusType* status) – returns full (including path) name of primary database file.

-


+


-

DbCryptPlugin +

DbCryptPlugin interface is main interface of database crypt plugin.

    -
  1. void +

  2. +

    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 @@ -3593,34 +3878,38 @@ interface is main interface of database crypt plugin.

    it CryptKeyCallback interface and get a key using it. Parameter keyName is a name of a key like it was entered in “ALTER DATABASE ENCRYPT …” operator.

    -
  3. void +

  4. +

    void encrypt(StatusType* status, unsigned length, const void* from, void* to) – encrypts data before writing block to database file.

    -
  5. void +

  6. +

    void decrypt(StatusType* status, unsigned length, const void* from, void* to) – decrypts data after reading block from database file.

    -
  7. void +

  8. +

    void setInfo(StatusType* status, IDbCryptInfo* info) – in this method crypt plugin typically saves informational interface for future use.

-


+


Key holder for database encryption plugin.

-

This +

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).

-


+


-

KeyHolderPlugin +

KeyHolderPlugin interface is main interface of database crypt key holder plugin.

    -
  1. int +

  2. +

    int keyCallback(StatusType* status, ICryptKeyCallback* callback) – is used to pass attachment's CryptKeyCallback interface (if provided by user with Provider::setDbCryptCallback() @@ -3628,7 +3917,8 @@ interface is main interface of database crypt key holder plugin.

    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.

    -
  3. ICryptKeyCallback* +

  4. +

    ICryptKeyCallback* keyHandle(StatusType* status, const char* keyName) – is intended to be called by DbCryptPlugin directly to obtain callback interface for named key from key holder. This @@ -3639,7 +3929,8 @@ interface is main interface of database crypt key holder plugin.

    (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.

    -
  5. FB_BOOLEAN +

  6. +

    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 @@ -3647,7 +3938,8 @@ interface is main interface of database crypt key holder plugin.

    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.

    -
  7. ICryptKeyCallback* +

  8. +

    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 @@ -3658,12 +3950,12 @@ interface is main interface of database crypt key holder plugin.

    duplicate one-to-one keys, received by KeyHolderPlugin when keyCallback() function is invoked.

-


+


Non-interface objects used by API (C++ specific header Message.h).

-

Following +

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 / @@ -3671,99 +3963,99 @@ 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.

-


+


-

class +

class FbDate methods:

-

void +

void decode(IUtil* util, unsigned* year, unsigned* month, unsigned* day)

-

unsigned +

unsigned getYear(IUtil* util)

-

unsigned +

unsigned getMonth(IUtil* util)

-

unsigned +

unsigned getDay(IUtil* util)

-

void +

void encode(IUtil* util, unsigned year, unsigned month, unsigned day)

-


+


-

class +

class FbTime methods:

-

void +

void decode(IUtil* util, unsigned* hours, unsigned* minutes, unsigned* seconds, unsigned* fractions)

-

unsigned +

unsigned getHours(IUtil* util)

-

unsigned +

unsigned getMinutes(IUtil* util)

-

unsigned +

unsigned getSeconds(IUtil* util)

-

unsigned +

unsigned getFractions(IUtil* util)

-

void +

void encode(IUtil* util, unsigned hours, unsigned minutes, unsigned seconds, unsigned fractions)

-


+


-

class +

class FbTimestamp members:

-

FbDate +

FbDate date;

-

FbTime +

FbTime time;

-


+


-


+


-

Following +

Following two templates are used in static messages to represent CHAR(N) and VARCHAR(N) fields.

-


+


-

template +

template <unsigned N>

-

struct +

struct FbChar

-

{

-

char +

{

+

char str[N];

-

};

-


+

};

+


-

template +

template <unsigned N>

-

struct +

struct FbVarChar

-

{

-

ISC_USHORT +

{

+

ISC_USHORT length;

-

char +

char str[N];

-

void +

void set(const char* s);

-

};

-


+

};

+


-


+



-

This +

This document is currently missing 2 types of plugins – ExternalEngine and Trace. Information about them will be made available in next release of it.

-


+


diff --git a/examples/interfaces/12.batch_isc.cpp b/examples/interfaces/12.batch_isc.cpp index 6144a3c048..db1ddd197a 100644 --- a/examples/interfaces/12.batch_isc.cpp +++ b/examples/interfaces/12.batch_isc.cpp @@ -173,7 +173,8 @@ int main() raiseError(status, st); // get transaction interface - tra = utl->getTransactionByHandle(&status, &tr); + if (fb_get_transaction_interface(st, &tra, &tr)) + raiseError(status, st); // printf("\nPart 1. BLOB created using IBlob interface.\n"); @@ -184,7 +185,8 @@ int main() if (isc_dsql_prepare(st, &tr, &stmt, 0, sqlStmt1, 3, NULL)) raiseError(status, st); // and get it's interface - statemt = utl->getStatementByHandle(&status, &stmt); + if (fb_get_statement_interface(st, &statemt, &stmt)) + raiseError(status, st); // Message to store in a table FB_MESSAGE(Msg1, ThrowStatusWrapper, @@ -235,7 +237,8 @@ int main() if (isc_dsql_prepare(st, &tr, &stmt, 0, sqlStmt2, 3, NULL)) raiseError(status, st); // and get it's interface - statemt = utl->getStatementByHandle(&status, &stmt); + if (fb_get_statement_interface(st, &statemt, &stmt)) + raiseError(status, st); // Message to store in a table FB_MESSAGE(Msg2, ThrowStatusWrapper, diff --git a/src/include/firebird/FirebirdInterface.idl b/src/include/firebird/FirebirdInterface.idl index d6f5c5b247..f587f5f021 100644 --- a/src/include/firebird/FirebirdInterface.idl +++ b/src/include/firebird/FirebirdInterface.idl @@ -1113,8 +1113,6 @@ interface Util : Versioned version: // 3.0 => 4.0 Alpha1 DecFloat16 getDecFloat16(Status status); DecFloat34 getDecFloat34(Status status); - Transaction getTransactionByHandle(Status status, isc_tr_handle* hndlPtr); - Statement getStatementByHandle(Status status, isc_stmt_handle* hndlPtr); void decodeTimeTz(Status status, const ISC_TIME_TZ* timeTz, uint* hours, uint* minutes, uint* seconds, uint* fractions, uint timeZoneBufferLength, string timeZoneBuffer); void decodeTimeStampTz(Status status, const ISC_TIMESTAMP_TZ* timeStampTz, uint* year, uint* month, uint* day, diff --git a/src/include/firebird/IdlFbInterfaces.h b/src/include/firebird/IdlFbInterfaces.h index 72a1647435..a8d8cd5502 100644 --- a/src/include/firebird/IdlFbInterfaces.h +++ b/src/include/firebird/IdlFbInterfaces.h @@ -4143,8 +4143,6 @@ namespace Firebird unsigned (CLOOP_CARG *setOffsets)(IUtil* self, IStatus* status, IMessageMetadata* metadata, IOffsetsCallback* callback) throw(); IDecFloat16* (CLOOP_CARG *getDecFloat16)(IUtil* self, IStatus* status) throw(); IDecFloat34* (CLOOP_CARG *getDecFloat34)(IUtil* self, IStatus* status) throw(); - ITransaction* (CLOOP_CARG *getTransactionByHandle)(IUtil* self, IStatus* status, isc_tr_handle* hndlPtr) throw(); - IStatement* (CLOOP_CARG *getStatementByHandle)(IUtil* self, IStatus* status, isc_stmt_handle* hndlPtr) throw(); void (CLOOP_CARG *decodeTimeTz)(IUtil* self, IStatus* status, const ISC_TIME_TZ* timeTz, unsigned* hours, unsigned* minutes, unsigned* seconds, unsigned* fractions, unsigned timeZoneBufferLength, char* timeZoneBuffer) throw(); void (CLOOP_CARG *decodeTimeStampTz)(IUtil* self, IStatus* status, const ISC_TIMESTAMP_TZ* timeStampTz, unsigned* year, unsigned* month, unsigned* day, unsigned* hours, unsigned* minutes, unsigned* seconds, unsigned* fractions, unsigned timeZoneBufferLength, char* timeZoneBuffer) throw(); void (CLOOP_CARG *encodeTimeTz)(IUtil* self, IStatus* status, ISC_TIME_TZ* timeTz, unsigned hours, unsigned minutes, unsigned seconds, unsigned fractions, const char* timeZone) throw(); @@ -4281,34 +4279,6 @@ namespace Firebird return ret; } - template ITransaction* getTransactionByHandle(StatusType* status, isc_tr_handle* hndlPtr) - { - if (cloopVTable->version < 3) - { - StatusType::setVersionError(status, "IUtil", cloopVTable->version, 3); - StatusType::checkException(status); - return 0; - } - StatusType::clearException(status); - ITransaction* ret = static_cast(this->cloopVTable)->getTransactionByHandle(this, status, hndlPtr); - StatusType::checkException(status); - return ret; - } - - template IStatement* getStatementByHandle(StatusType* status, isc_stmt_handle* hndlPtr) - { - if (cloopVTable->version < 3) - { - StatusType::setVersionError(status, "IUtil", cloopVTable->version, 3); - StatusType::checkException(status); - return 0; - } - StatusType::clearException(status); - IStatement* ret = static_cast(this->cloopVTable)->getStatementByHandle(this, status, hndlPtr); - StatusType::checkException(status); - return ret; - } - template void decodeTimeTz(StatusType* status, const ISC_TIME_TZ* timeTz, unsigned* hours, unsigned* minutes, unsigned* seconds, unsigned* fractions, unsigned timeZoneBufferLength, char* timeZoneBuffer) { if (cloopVTable->version < 3) @@ -14650,8 +14620,6 @@ namespace Firebird this->setOffsets = &Name::cloopsetOffsetsDispatcher; this->getDecFloat16 = &Name::cloopgetDecFloat16Dispatcher; this->getDecFloat34 = &Name::cloopgetDecFloat34Dispatcher; - this->getTransactionByHandle = &Name::cloopgetTransactionByHandleDispatcher; - this->getStatementByHandle = &Name::cloopgetStatementByHandleDispatcher; this->decodeTimeTz = &Name::cloopdecodeTimeTzDispatcher; this->decodeTimeStampTz = &Name::cloopdecodeTimeStampTzDispatcher; this->encodeTimeTz = &Name::cloopencodeTimeTzDispatcher; @@ -14872,36 +14840,6 @@ namespace Firebird } } - static ITransaction* CLOOP_CARG cloopgetTransactionByHandleDispatcher(IUtil* self, IStatus* status, isc_tr_handle* hndlPtr) throw() - { - StatusType status2(status); - - try - { - return static_cast(self)->Name::getTransactionByHandle(&status2, hndlPtr); - } - catch (...) - { - StatusType::catchException(&status2); - return static_cast(0); - } - } - - static IStatement* CLOOP_CARG cloopgetStatementByHandleDispatcher(IUtil* self, IStatus* status, isc_stmt_handle* hndlPtr) throw() - { - StatusType status2(status); - - try - { - return static_cast(self)->Name::getStatementByHandle(&status2, hndlPtr); - } - catch (...) - { - StatusType::catchException(&status2); - return static_cast(0); - } - } - static void CLOOP_CARG cloopdecodeTimeTzDispatcher(IUtil* self, IStatus* status, const ISC_TIME_TZ* timeTz, unsigned* hours, unsigned* minutes, unsigned* seconds, unsigned* fractions, unsigned timeZoneBufferLength, char* timeZoneBuffer) throw() { StatusType status2(status); @@ -15030,8 +14968,6 @@ namespace Firebird virtual unsigned setOffsets(StatusType* status, IMessageMetadata* metadata, IOffsetsCallback* callback) = 0; virtual IDecFloat16* getDecFloat16(StatusType* status) = 0; virtual IDecFloat34* getDecFloat34(StatusType* status) = 0; - virtual ITransaction* getTransactionByHandle(StatusType* status, isc_tr_handle* hndlPtr) = 0; - virtual IStatement* getStatementByHandle(StatusType* status, isc_stmt_handle* hndlPtr) = 0; virtual void decodeTimeTz(StatusType* status, const ISC_TIME_TZ* timeTz, unsigned* hours, unsigned* minutes, unsigned* seconds, unsigned* fractions, unsigned timeZoneBufferLength, char* timeZoneBuffer) = 0; virtual 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) = 0; virtual void encodeTimeTz(StatusType* status, ISC_TIME_TZ* timeTz, unsigned hours, unsigned minutes, unsigned seconds, unsigned fractions, const char* timeZone) = 0; diff --git a/src/include/ibase.h b/src/include/ibase.h index 1e6ab1420e..2800521673 100644 --- a/src/include/ibase.h +++ b/src/include/ibase.h @@ -1136,6 +1136,8 @@ ISC_STATUS ISC_EXPORT fb_ping(ISC_STATUS*, isc_db_handle*); ISC_STATUS ISC_EXPORT fb_get_database_handle(ISC_STATUS*, isc_db_handle*, void*); ISC_STATUS ISC_EXPORT fb_get_transaction_handle(ISC_STATUS*, isc_tr_handle*, void*); +ISC_STATUS ISC_EXPORT fb_get_transaction_interface(ISC_STATUS*, void*, isc_tr_handle*); +ISC_STATUS ISC_EXPORT fb_get_statement_interface(ISC_STATUS*, void*, isc_stmt_handle*); /********************************/ /* Client information functions */ diff --git a/src/yvalve/YObjects.h b/src/yvalve/YObjects.h index 7f8c8d2744..a38c65eb3f 100644 --- a/src/yvalve/YObjects.h +++ b/src/yvalve/YObjects.h @@ -673,8 +673,6 @@ public: Firebird::IOffsetsCallback* callback); Firebird::IDecFloat16* getDecFloat16(Firebird::CheckStatusWrapper* status); Firebird::IDecFloat34* getDecFloat34(Firebird::CheckStatusWrapper* status); - Firebird::ITransaction* getTransactionByHandle(Firebird::CheckStatusWrapper* status, isc_tr_handle* hndlPtr); - Firebird::IStatement* getStatementByHandle(Firebird::CheckStatusWrapper* status, isc_stmt_handle* hndlPtr); void decodeTimeTz(Firebird::CheckStatusWrapper* status, const ISC_TIME_TZ* timeTz, unsigned* hours, unsigned* minutes, unsigned* seconds, unsigned* fractions, unsigned timeZoneBufferLength, char* timeZoneBuffer); diff --git a/src/yvalve/why.cpp b/src/yvalve/why.cpp index 739697d577..62da4bf92a 100644 --- a/src/yvalve/why.cpp +++ b/src/yvalve/why.cpp @@ -3810,6 +3810,60 @@ ISC_STATUS API_ROUTINE fb_get_transaction_handle(ISC_STATUS* userStatus, isc_tr_ } +// Get transaction interface by legacy handle +ISC_STATUS API_ROUTINE fb_get_transaction_interface(ISC_STATUS* userStatus, void* iPtr, + isc_tr_handle* hndlPtr) +{ + StatusVector status(userStatus); + CheckStatusWrapper statusWrapper(&status); + + try + { + ITransaction** tra = (ITransaction**) iPtr; + if (*tra) + (Arg::Gds(isc_random) << "Interface must be null").raise(); + + RefPtr transaction(translateHandle(transactions, hndlPtr)); + + transaction->addRef(); + *tra = transaction; + } + catch (const Exception& e) + { + e.stuffException(&statusWrapper); + } + + return status[1]; +} + + +// Get statement interface by legacy handle +ISC_STATUS API_ROUTINE fb_get_statement_interface(ISC_STATUS* userStatus, void* iPtr, + isc_stmt_handle* hndlPtr) +{ + StatusVector status(userStatus); + CheckStatusWrapper statusWrapper(&status); + + try + { + IStatement** stmt = (IStatement**) iPtr; + if (*stmt) + (Arg::Gds(isc_random) << "Interface must be null").raise(); + + RefPtr statement(translateHandle(statements, hndlPtr)); + statement->checkPrepared(isc_info_unprepared_stmt); + + *stmt = statement->getInterface(); + } + catch (const Exception& e) + { + e.stuffException(&statusWrapper); + } + + return status[1]; +} + + //------------------------------------- namespace Why { @@ -6535,39 +6589,4 @@ void Dispatcher::setDbCryptCallback(CheckStatusWrapper* status, ICryptKeyCallbac cryptCallback = callback; } -ITransaction* UtilInterface::getTransactionByHandle(CheckStatusWrapper* status, isc_tr_handle* hndlPtr) -{ - try - { - RefPtr transaction(translateHandle(transactions, hndlPtr)); - - transaction->addRef(); - return transaction; - } - catch (const Exception& e) - { - e.stuffException(status); - } - - return nullptr; -} - - -IStatement* UtilInterface::getStatementByHandle(Firebird::CheckStatusWrapper* status, isc_stmt_handle* hndlPtr) -{ - try - { - RefPtr statement(translateHandle(statements, hndlPtr)); - statement->checkPrepared(isc_info_unprepared_stmt); - - return statement->getInterface(); - } - catch (const Exception& e) - { - e.stuffException(status); - } - - return nullptr; -} - } // namespace Why