8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-22 18:43:02 +01:00

Work in progress on message-based external functions and procedures.

This commit is contained in:
asfernandes 2011-06-26 15:57:55 +00:00
parent 5a414ee680
commit 4f5dd005ac
6 changed files with 497 additions and 240 deletions

View File

@ -13,12 +13,13 @@ EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "udrcpp_example", "udrcpp_example.vcproj", "{FF0FD8DF-1E5C-486E-B395-A620376A4633}"
ProjectSection(ProjectDependencies) = postProject
{20DEBF08-EF0A-4C94-ADEB-FE9BBA14588B} = {20DEBF08-EF0A-4C94-ADEB-FE9BBA14588B}
{4FE03933-98CD-4879-A135-FD9430087A6B} = {4FE03933-98CD-4879-A135-FD9430087A6B}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "udr_engine", "udr_engine.vcproj", "{20DEBF08-EF0A-4C94-ADEB-FE9BBA14588B}"
ProjectSection(ProjectDependencies) = postProject
{15605F44-BFFD-444F-AD4C-55DC9D704465} = {15605F44-BFFD-444F-AD4C-55DC9D704465}
{4FE03933-98CD-4879-A135-FD9430087A6B} = {4FE03933-98CD-4879-A135-FD9430087A6B}
{15605F44-BFFD-444F-AD4C-55DC9D704465} = {15605F44-BFFD-444F-AD4C-55DC9D704465}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "common", "common.vcproj", "{15605F44-BFFD-444F-AD4C-55DC9D704465}"
@ -52,25 +53,33 @@ Global
{9546EF04-1326-464B-A6ED-395C60DD63CC}.Debug|x64.ActiveCfg = Debug|x64
{9546EF04-1326-464B-A6ED-395C60DD63CC}.Debug|x64.Build.0 = Debug|x64
{9546EF04-1326-464B-A6ED-395C60DD63CC}.Release|Win32.ActiveCfg = Release|Win32
{9546EF04-1326-464B-A6ED-395C60DD63CC}.Release|Win32.Build.0 = Release|Win32
{9546EF04-1326-464B-A6ED-395C60DD63CC}.Release|x64.ActiveCfg = Release|x64
{9546EF04-1326-464B-A6ED-395C60DD63CC}.Release|x64.Build.0 = Release|x64
{FF0FD8DF-1E5C-486E-B395-A620376A4633}.Debug|Win32.ActiveCfg = Debug|Win32
{FF0FD8DF-1E5C-486E-B395-A620376A4633}.Debug|Win32.Build.0 = Debug|Win32
{FF0FD8DF-1E5C-486E-B395-A620376A4633}.Debug|x64.ActiveCfg = Debug|Win32
{FF0FD8DF-1E5C-486E-B395-A620376A4633}.Debug|x64.ActiveCfg = Debug|x64
{FF0FD8DF-1E5C-486E-B395-A620376A4633}.Debug|x64.Build.0 = Debug|x64
{FF0FD8DF-1E5C-486E-B395-A620376A4633}.Release|Win32.ActiveCfg = Release|Win32
{FF0FD8DF-1E5C-486E-B395-A620376A4633}.Release|Win32.Build.0 = Release|Win32
{FF0FD8DF-1E5C-486E-B395-A620376A4633}.Release|x64.ActiveCfg = Release|Win32
{FF0FD8DF-1E5C-486E-B395-A620376A4633}.Release|x64.ActiveCfg = Release|x64
{FF0FD8DF-1E5C-486E-B395-A620376A4633}.Release|x64.Build.0 = Release|x64
{20DEBF08-EF0A-4C94-ADEB-FE9BBA14588B}.Debug|Win32.ActiveCfg = Debug|Win32
{20DEBF08-EF0A-4C94-ADEB-FE9BBA14588B}.Debug|Win32.Build.0 = Debug|Win32
{20DEBF08-EF0A-4C94-ADEB-FE9BBA14588B}.Debug|x64.ActiveCfg = Debug|Win32
{20DEBF08-EF0A-4C94-ADEB-FE9BBA14588B}.Debug|x64.ActiveCfg = Debug|x64
{20DEBF08-EF0A-4C94-ADEB-FE9BBA14588B}.Debug|x64.Build.0 = Debug|x64
{20DEBF08-EF0A-4C94-ADEB-FE9BBA14588B}.Release|Win32.ActiveCfg = Release|Win32
{20DEBF08-EF0A-4C94-ADEB-FE9BBA14588B}.Release|Win32.Build.0 = Release|Win32
{20DEBF08-EF0A-4C94-ADEB-FE9BBA14588B}.Release|x64.ActiveCfg = Release|Win32
{20DEBF08-EF0A-4C94-ADEB-FE9BBA14588B}.Release|x64.ActiveCfg = Release|x64
{20DEBF08-EF0A-4C94-ADEB-FE9BBA14588B}.Release|x64.Build.0 = Release|x64
{15605F44-BFFD-444F-AD4C-55DC9D704465}.Debug|Win32.ActiveCfg = Debug|Win32
{15605F44-BFFD-444F-AD4C-55DC9D704465}.Debug|Win32.Build.0 = Debug|Win32
{15605F44-BFFD-444F-AD4C-55DC9D704465}.Debug|x64.ActiveCfg = Debug|Win32
{15605F44-BFFD-444F-AD4C-55DC9D704465}.Debug|x64.ActiveCfg = Debug|x64
{15605F44-BFFD-444F-AD4C-55DC9D704465}.Debug|x64.Build.0 = Debug|x64
{15605F44-BFFD-444F-AD4C-55DC9D704465}.Release|Win32.ActiveCfg = Release|Win32
{15605F44-BFFD-444F-AD4C-55DC9D704465}.Release|Win32.Build.0 = Release|Win32
{15605F44-BFFD-444F-AD4C-55DC9D704465}.Release|x64.ActiveCfg = Release|Win32
{15605F44-BFFD-444F-AD4C-55DC9D704465}.Release|x64.ActiveCfg = Release|x64
{15605F44-BFFD-444F-AD4C-55DC9D704465}.Release|x64.Build.0 = Release|x64
{4FE03933-98CD-4879-A135-FD9430087A6B}.Debug|Win32.ActiveCfg = Debug|Win32
{4FE03933-98CD-4879-A135-FD9430087A6B}.Debug|Win32.Build.0 = Debug|Win32
{4FE03933-98CD-4879-A135-FD9430087A6B}.Debug|x64.ActiveCfg = Debug|x64

View File

@ -275,7 +275,7 @@ private:
class MessageImpl : public Firebird::FbMessage
{
public:
MessageImpl(unsigned aItemCount, ISC_UCHAR* aBuffer = NULL)
MessageImpl(unsigned aItemCount, void* aBuffer = NULL)
: itemCount(aItemCount * 2),
freeBuffer(!aBuffer),
items(0)
@ -289,7 +289,7 @@ public:
blrLength = 0;
blr = blrPos = new ISC_UCHAR[sizeof(HEADER) + 10 * itemCount + 2];
bufferLength = 0;
buffer = aBuffer;
buffer = (ISC_UCHAR*) aBuffer;
memcpy(blrPos, HEADER, sizeof(HEADER));
blrPos += sizeof(HEADER);
@ -564,12 +564,44 @@ inline ParamDesc<void*>::ParamDesc(MessageImpl& message, const Firebird::IParame
/***
create function wait_event (
event_name varchar(31) character set ascii not null
event_name varchar(31) character set utf8 not null
) returns integer not null
external name 'udrcpp_example!wait_event'
engine udr;
***/
FB_UDR_DECLARE_FUNCTION(wait_event)
FB_UDR_BEGIN_FUNCTION(wait_event)
FB_UDR_EXECUTE_MESSAGE_FUNCTION(
(FB_VARCHAR(31 * 4), name)
,
(FB_INTEGER, result))
{
char* s = new char[in->name.length + 1];
memcpy(s, in->name.str, in->name.length);
s[in->name.length] = '\0';
unsigned char* eveBuffer;
unsigned char* eveResult;
int eveLen = isc_event_block(&eveBuffer, &eveResult, 1, s);
delete [] s;
ISC_STATUS_ARRAY statusVector = {0};
isc_db_handle dbHandle = getIscDbHandle(context);
ISC_ULONG counter = 0;
ThrowError::check(isc_wait_for_event(statusVector, &dbHandle, eveLen, eveBuffer, eveResult),
statusVector);
isc_event_counts(&counter, eveLen, eveBuffer, eveResult);
ThrowError::check(isc_wait_for_event(statusVector, &dbHandle, eveLen, eveBuffer, eveResult),
statusVector);
isc_event_counts(&counter, eveLen, eveBuffer, eveResult);
isc_free((char*) eveBuffer);
isc_free((char*) eveResult);
out->result = counter;
}
FB_UDR_END_FUNCTION
/***
@ -581,7 +613,40 @@ create function sum_args (
external name 'udrcpp_example!sum_args'
engine udr;
***/
FB_UDR_DECLARE_FUNCTION(sum_args)
FB_UDR_BEGIN_FUNCTION(sum_args)
FB_UDR_EXECUTE_DYNAMIC_FUNCTION
{
AutoDispose<IStatus> status(master->getStatus());
const IParametersMetadata* params = metadata->getInputParameters(status);
ThrowError::check(status->get());
unsigned count = params->getCount(status);
ThrowError::check(status->get());
MessageImpl inMessage(count, in);
MessageImpl outMessage(1, out);
ParamDesc<ISC_LONG> retDesc(outMessage);
int ret = 0;
for (unsigned i = 0; i < count; ++i)
{
ParamDesc<ISC_LONG> numDesc(inMessage);
if (inMessage.isNull(numDesc))
{
outMessage.setNull(retDesc, true);
return;
}
else
ret += inMessage[numDesc];
}
outMessage[retDesc] = ret;
}
FB_UDR_END_FUNCTION
/***
@ -594,11 +659,140 @@ create procedure gen_rows (
external name 'udrcpp_example!gen_rows'
engine udr;
***/
FB_UDR_DECLARE_PROCEDURE(gen_rows)
FB_UDR_BEGIN_DECLARE_FETCH_PROCEDURE(gen_rows)
int counter;
int end;
FB_UDR_END_DECLARE_FETCH_PROCEDURE(gen_rows)
FB_UDR_BEGIN_PROCEDURE(gen_rows)
FB_UDR_EXECUTE_DYNAMIC_PROCEDURE
{
MessageImpl inMessage(2, inMsg);
ParamDesc<ISC_LONG> startDesc(inMessage);
ParamDesc<ISC_LONG> endDesc(inMessage);
counter = inMessage[startDesc];
end = inMessage[endDesc];
}
FB_UDR_FETCH_PROCEDURE
{
if (counter > end)
return false;
MessageImpl outMessage(1, out);
ParamDesc<ISC_LONG> retDesc(outMessage);
outMessage[retDesc] = counter++;
return true;
}
ISC_LONG counter;
ISC_LONG end;
FB_UDR_END_PROCEDURE
/***
create procedure gen_rows2 (
start_n integer not null,
end_n integer not null
) returns (
n integer not null
)
external name 'udrcpp_example!gen_rows2'
engine udr;
***/
FB_UDR_BEGIN_PROCEDURE(gen_rows2)
FB_UDR_EXECUTE_MESSAGE_PROCEDURE(
(FB_INTEGER, start)
(FB_INTEGER, end)
,
(FB_INTEGER, result))
{
out->result = in->start - 1;
}
FB_UDR_FETCH_PROCEDURE
{
return out->result++ < in->end;
}
FB_UDR_END_PROCEDURE
/***
create procedure inc (
count_n integer not null
) returns (
n0 integer not null,
n1 integer not null,
n2 integer not null,
n3 integer not null,
n4 integer not null
)
external name 'udrcpp_example!inc'
engine udr;
***/
// This is a sample procedure demonstrating how the scopes of variables works.
// n1 and n2 are on the Procedure scope, i.e., they're shared for each execution of the same cached
// metadata object.
// n3 and n4 are on the ResultSet scope, i.e., each procedure execution have they own instances.
FB_UDR_BEGIN_PROCEDURE(inc)
ISC_LONG n1;
// This is how a procedure (class) initializer is written.
// ResultSet variables are not accessible here.
// If there is nothing to initialize, it can be completelly suppressed.
FB_UDR_PROCEDURE(inc)()
: n1(0),
n2(0)
{
}
ISC_LONG n2;
// FB_UDR_EXECUTE_MESSAGE_PROCEDURE or FB_UDR_EXECUTE_DYNAMIC_PROCEDURE starts the ResultSet scope.
FB_UDR_EXECUTE_MESSAGE_PROCEDURE(
(FB_INTEGER, count)
,
(FB_INTEGER, n0)
(FB_INTEGER, n1)
(FB_INTEGER, n2)
(FB_INTEGER, n3)
(FB_INTEGER, n4))
// This is the ResultSet (class) initializer. If there is nothing to initialize, the comma
// should be suppressed.
,
n3(procedure->n1), // n3 will start with the next value for n1 of the last execution
n4(0)
{
out->n0 = 0;
// In the execute method, the procedure scope must be accessed using the 'procedure' pointer.
procedure->n1 = 0;
// We don't touch n2 here, so it incremented counter will be kept after each execution.
// The ResultSet scope must be accessed directly, i.e., they're member variables of the
// 'this' pointer.
++n4;
}
ISC_LONG n3;
// FB_UDR_FETCH must be always after FB_UDR_EXECUTE_MESSAGE_PROCEDURE or
// FB_UDR_EXECUTE_DYNAMIC_PROCEDURE.
FB_UDR_FETCH_PROCEDURE
{
if (out->n0++ <= in->count)
{
out->n1 = ++procedure->n1;
out->n2 = ++procedure->n2;
out->n3 = ++n3;
out->n4 = ++n4;
return true;
}
return false;
}
ISC_LONG n4;
FB_UDR_END_PROCEDURE
/***
@ -645,110 +839,9 @@ private:
bool initialized;
XSQLDA* inSqlDa;
isc_stmt_handle stmtHandle;
#if 0
IStatement* stmt;
#endif
FB_UDR_END_DECLARE_TRIGGER(replicate)
FB_UDR_BEGIN_FUNCTION(wait_event)
{
MessageImpl inMessage(1, inMsg);
ParamDesc<FbString> nameDesc(inMessage, 31);
FbString& name = inMessage[nameDesc];
char* s = new char[name.length + 1];
memcpy(s, name.str, name.length);
s[name.length] = '\0';
unsigned char* eveBuffer;
unsigned char* eveResult;
int eveLen = isc_event_block(&eveBuffer, &eveResult, 1, s);
delete [] s;
ISC_STATUS_ARRAY statusVector = {0};
isc_db_handle dbHandle = getIscDbHandle(context);
ISC_ULONG counter = 0;
ThrowError::check(isc_wait_for_event(statusVector, &dbHandle, eveLen, eveBuffer, eveResult),
statusVector);
isc_event_counts(&counter, eveLen, eveBuffer, eveResult);
ThrowError::check(isc_wait_for_event(statusVector, &dbHandle, eveLen, eveBuffer, eveResult),
statusVector);
isc_event_counts(&counter, eveLen, eveBuffer, eveResult);
isc_free((char*) eveBuffer);
isc_free((char*) eveResult);
MessageImpl outMessage(1, outMsg);
ParamDesc<ISC_LONG> retDesc(outMessage);
outMessage[retDesc] = counter;
}
FB_UDR_END_FUNCTION(wait_event)
FB_UDR_BEGIN_FUNCTION(sum_args)
{
AutoDispose<IStatus> status(master->getStatus());
const IParametersMetadata* params = metadata->getInputParameters(status);
ThrowError::check(status->get());
unsigned count = params->getCount(status);
ThrowError::check(status->get());
MessageImpl inMessage(count, inMsg);
MessageImpl outMessage(1, outMsg);
ParamDesc<ISC_LONG> retDesc(outMessage);
int ret = 0;
for (unsigned i = 0; i < count; ++i)
{
ParamDesc<ISC_LONG> numDesc(inMessage);
if (inMessage.isNull(numDesc))
{
outMessage.setNull(retDesc, true);
return;
}
ret += inMessage[numDesc];
}
outMessage[retDesc] = ret;
}
FB_UDR_END_FUNCTION(sum_args)
FB_UDR_BEGIN_PROCEDURE(gen_rows)
{
MessageImpl inMessage(2, inMsg);
ParamDesc<ISC_LONG> startDesc(inMessage);
ParamDesc<ISC_LONG> endDesc(inMessage);
counter = inMessage[startDesc];
end = inMessage[endDesc];
}
FB_UDR_FETCH_PROCEDURE(gen_rows)
{
if (counter > end)
return false;
MessageImpl outMessage(1, outMsg);
ParamDesc<ISC_LONG> retDesc(outMessage);
outMessage[retDesc] = counter++;
return true;
}
FB_UDR_END_PROCEDURE(gen_rows)
FB_UDR_TRIGGER(replicate)::FB_UDR_TRIGGER(replicate)()
: initialized(false)
{

View File

@ -0,0 +1,112 @@
/*
* The contents of this file are subject to the Initial
* Developer's Public License Version 1.0 (the "License");
* you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
* http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
*
* Software distributed under the License is distributed AS IS,
* WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the License for the specific language governing rights
* and limitations under the License.
*
* The Original Code was created by Adriano dos Santos Fernandes
* for the Firebird Open Source RDBMS project.
*
* Copyright (c) 2011 Adriano dos Santos Fernandes <adrianosf@uol.com.br>
* and all contributors signed below.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
*/
#ifndef FIREBIRD_MESSAGE_H
#define FIREBIRD_MESSAGE_H
#include "ibase.h"
#include "firebird/impl/boost/preprocessor/seq/for_each_i.hpp"
#define FB_MESSAGE(name, fields) \
FB_MESSAGE_I(name, FB_BOOST_PP_CAT(FB_MESSAGE_X fields, 0))
#define FB_MESSAGE_X(x, y) ((x, y)) FB_MESSAGE_Y
#define FB_MESSAGE_Y(x, y) ((x, y)) FB_MESSAGE_X
#define FB_MESSAGE_X0
#define FB_MESSAGE_Y0
#define FB_MESSAGE_I(name, fields) \
struct name \
{ \
/* TODO: use it */ \
static const unsigned char* BLR() \
{ \
static const unsigned char blr[] = { \
blr_version5, \
blr_begin, \
blr_message, 0, \
(2 * (FB_BOOST_PP_SEQ_SIZE(fields))) & 0xFF, \
(2 * (FB_BOOST_PP_SEQ_SIZE(fields))) >> 8, \
FB_BOOST_PP_SEQ_FOR_EACH_I(FB_MESSAGE_BLR, _, fields) \
blr_end, \
blr_eoc \
}; \
return blr; \
} \
\
static unsigned SIZE() \
{ \
return (unsigned)(size_t) (&((name*) 0)->FB_BOOST_PP_CAT( \
FB_BOOST_PP_TUPLE_ELEM(2, 1, \
FB_BOOST_PP_SEQ_ELEM(FB_BOOST_PP_DEC(FB_BOOST_PP_SEQ_SIZE(fields)), fields)), \
Null) - 0) + sizeof(ISC_SHORT); \
} \
\
FB_BOOST_PP_SEQ_FOR_EACH_I(FB_MESSAGE_FIELD, _, fields) \
};
#define FB_MESSAGE_FIELD(r, _, i, xy) \
FB_BOOST_PP_CAT(FB_TYPE_, FB_BOOST_PP_TUPLE_ELEM(2, 0, xy)) FB_BOOST_PP_TUPLE_ELEM(2, 1, xy); \
ISC_SHORT FB_BOOST_PP_CAT(FB_BOOST_PP_TUPLE_ELEM(2, 1, xy), Null);
#define FB_MESSAGE_BLR(r, _, i, xy) \
FB_BOOST_PP_CAT(FB_BLR_, FB_BOOST_PP_TUPLE_ELEM(2, 0, xy)), \
FB_BLR_FB_SMALLINT,
//// TODO: more types
#define FB_BLR_FB_SCALED_SMALLINT(scale) blr_short, (scale)
#define FB_BLR_FB_SCALED_INTEGER(scale) blr_long, (scale)
#define FB_BLR_FB_SCALED_BIGINT(scale) blr_int64, (scale)
#define FB_BLR_FB_SMALLINT FB_BLR_FB_SCALED_SMALLINT(0)
#define FB_BLR_FB_INTEGER FB_BLR_FB_SCALED_INTEGER(0)
#define FB_BLR_FB_BIGINT FB_BLR_FB_SCALED_BIGINT(0)
#define FB_BLR_FB_VARCHAR(len) blr_varying, (len) & 0xFF, (len) >> 8
#define FB_TYPE_FB_SCALED_SMALLINT(x) ISC_SHORT
#define FB_TYPE_FB_SCALED_INTEGER(x) ISC_LONG
#define FB_TYPE_FB_SCALED_BIGINT(x) ISC_INT64
#define FB_TYPE_FB_SMALLINT ISC_SHORT
#define FB_TYPE_FB_INTEGER ISC_LONG
#define FB_TYPE_FB_BIGINT ISC_INT64
#define FB_TYPE_FB_VARCHAR(len) FbVarChar<(len)>
namespace Firebird {
template <unsigned N>
struct FbVarChar
{
ISC_USHORT length;
char str[N];
void set(const char* s)
{
length = strlen(s);
memcpy(str, s, length);
}
};
} // namespace Firebird
#endif // FIREBIRD_MESSAGE_H

View File

@ -20,11 +20,12 @@
* Contributor(s): ______________________________________.
*/
#ifndef FIREBIRD_PLUGIN_UDR_CPP
#define FIREBIRD_PLUGIN_UDR_CPP
#ifndef FIREBIRD_UDR_CPP_ENGINE
#define FIREBIRD_UDR_CPP_ENGINE
#include "./ExternalEngine.h"
#include "./UdrEngine.h"
#include "./Message.h"
#ifndef JRD_IBASE_H
#include "ibase.h"
#include "iberror.h"
@ -44,29 +45,41 @@ namespace Firebird
#define FB_UDR_TRIGGER(name) Trig##name
#define FB_UDR_BEGIN_DECLARE_FUNCTION(name) \
class FB_UDR_FUNCTION(name) : public ::Firebird::Udr::Function \
#define FB_UDR_BEGIN_FUNCTION(name) \
class FB_UDR_FUNCTION(name); \
\
::Firebird::Udr::FunctionFactoryImpl<FB_UDR_FUNCTION(name)> FuncFactory##name(#name); \
\
class FB_UDR_FUNCTION(name) : public ::Firebird::Udr::Function<FB_UDR_FUNCTION(name)> \
{ \
public: \
virtual void FB_CALL execute(::Firebird::Error* error, ::Firebird::ExternalContext* context, \
UCHAR* inMsg, UCHAR* outMsg); \
private:
public:
#define FB_UDR_END_DECLARE_FUNCTION(name) \
#define FB_UDR_END_FUNCTION \
};
#define FB_UDR_DECLARE_FUNCTION(name) \
FB_UDR_BEGIN_DECLARE_FUNCTION(name) \
FB_UDR_END_DECLARE_FUNCTION(name)
#define FB_UDR_EXECUTE_DYNAMIC_FUNCTION \
typedef void* InMessage; \
typedef void* OutMessage; \
\
FB_UDR_EXECUTE__FUNCTION
#define FB_UDR_BEGIN_FUNCTION(name) \
void FB_CALL FB_UDR_FUNCTION(name)::execute(::Firebird::Error* error, \
::Firebird::ExternalContext* context, UCHAR* inMsg, UCHAR* outMsg) \
#define FB_UDR_EXECUTE_MESSAGE_FUNCTION(inputs, output) \
FB_MESSAGE(InMessage, \
inputs \
) \
FB_MESSAGE(OutMessage, \
output \
) \
\
FB_UDR_EXECUTE__FUNCTION
#define FB_UDR_EXECUTE__FUNCTION \
virtual void FB_CALL execute(::Firebird::Error* error, ::Firebird::ExternalContext* context, \
UCHAR* inMsg, UCHAR* outMsg) \
{ \
try \
{
#define FB_UDR_END_FUNCTION(name) \
{ \
execute(error, context, (InMessage*) inMsg, (OutMessage*) outMsg); \
} \
catch (const ::Firebird::Udr::ThrowError::Exception& e) \
{ \
@ -81,61 +94,48 @@ namespace Firebird
strlen(FB_UDR_UNRECOGNIZED_EXCEPTION)); \
} \
} \
::Firebird::Udr::FunctionFactoryImpl<FB_UDR_FUNCTION(name)> FuncFactory##name(#name);
#define FB_UDR_BEGIN_DECLARE_PROCEDURE(name) \
class FB_UDR_PROCEDURE(name) : public ::Firebird::Udr::Procedure \
{ \
public: \
virtual ::Firebird::ExternalResultSet* FB_CALL open(::Firebird::Error* error, \
::Firebird::ExternalContext* context, UCHAR* inMsg, UCHAR* outMsg); \
#define FB_UDR_END_DECLARE_PROCEDURE(name) \
};
#define FB_UDR_DECLARE_PROCEDURE(name) \
FB_UDR_BEGIN_DECLARE_PROCEDURE(name) \
FB_UDR_END_DECLARE_PROCEDURE(name)
#define FB_UDR_BEGIN_DECLARE_FETCH_PROCEDURE(name) \
class ResultSet##name : public ::Firebird::Udr::ResultSet \
{ \
public: \
ResultSet##name(::Firebird::Error* error, ::Firebird::ExternalContext* context, \
::Firebird::Udr::Procedure* procedure, UCHAR* inMsg, UCHAR* outMsg); \
\
public: \
virtual bool FB_CALL fetch(::Firebird::Error* error); \
\
private:
virtual void FB_CALL execute(::Firebird::Error* error, ::Firebird::ExternalContext* context, \
InMessage* in, OutMessage* out)
#define FB_UDR_END_DECLARE_FETCH_PROCEDURE(name) \
};
#define FB_UDR_DECLARE_FETCH_PROCEDURE(name) \
FB_UDR_BEGIN_DECLARE_FETCH_PROCEDURE(name) \
FB_UDR_END_DECLARE_FETCH_PROCEDURE(name)
#define FB_UDR_DECLARE_PROCEDURE(name) \
FB_UDR_BEGIN_DECLARE_PROCEDURE(name) \
FB_UDR_END_DECLARE_PROCEDURE(name)
#define FB_UDR_BEGIN_PROCEDURE(name) \
::Firebird::ExternalResultSet* FB_CALL Proc##name::open(::Firebird::Error* error, \
class FB_UDR_PROCEDURE(name); \
\
::Firebird::Udr::ProcedureFactoryImpl<FB_UDR_PROCEDURE(name)> ProcFactory##name(#name); \
\
class FB_UDR_PROCEDURE(name) : public ::Firebird::Udr::Procedure<FB_UDR_PROCEDURE(name)> \
{ \
public: \
typedef FB_UDR_PROCEDURE(name) This;
#define FB_UDR_END_PROCEDURE \
}; \
};
#define FB_UDR_EXECUTE_DYNAMIC_PROCEDURE \
typedef void* InMessage; \
typedef void* OutMessage; \
\
FB_UDR_EXECUTE__PROCEDURE
#define FB_UDR_EXECUTE_MESSAGE_PROCEDURE(inputs, outputs) \
FB_MESSAGE(InMessage, \
inputs \
) \
FB_MESSAGE(OutMessage, \
outputs \
) \
\
FB_UDR_EXECUTE__PROCEDURE
#define FB_UDR_EXECUTE__PROCEDURE \
virtual ::Firebird::ExternalResultSet* FB_CALL open(::Firebird::Error* error, \
::Firebird::ExternalContext* context, UCHAR* inMsg, UCHAR* outMsg) \
{ \
return new ResultSet##name(error, context, this, inMsg, outMsg); \
} \
\
ResultSet##name::ResultSet##name(::Firebird::Error* error, ::Firebird::ExternalContext* context, \
::Firebird::Udr::Procedure* procedure, UCHAR* inMsg, UCHAR* outMsg) \
: ResultSet(context, procedure, inMsg, outMsg) \
{ \
try \
{
#define FB_UDR_FETCH_PROCEDURE(name) \
{ \
return new ResultSet(error, context, this, (InMessage*) inMsg, (OutMessage*) outMsg); \
} \
catch (const ::Firebird::Udr::ThrowError::Exception& e) \
{ \
@ -149,14 +149,24 @@ namespace Firebird
FB_UDR_UNRECOGNIZED_EXCEPTION, \
strlen(FB_UDR_UNRECOGNIZED_EXCEPTION)); \
} \
\
return 0; \
} \
\
bool FB_CALL ResultSet##name::fetch(::Firebird::Error* error) \
class ResultSet : public ::Firebird::Udr::ResultSet<ResultSet, This, InMessage, OutMessage> \
{ \
public: \
ResultSet(::Firebird::Error* error, ::Firebird::ExternalContext* context, \
This* procedure, InMessage* inMsg, OutMessage* outMsg) \
: ::Firebird::Udr::ResultSet<ResultSet, This, InMessage, OutMessage>( \
context, procedure, inMsg, outMsg)
#define FB_UDR_FETCH_PROCEDURE \
virtual bool FB_CALL fetch(::Firebird::Error* error) \
{ \
try \
{
#define FB_UDR_END_PROCEDURE(name) \
{ \
return fetch0(error); \
} \
catch (const ::Firebird::Udr::ThrowError::Exception& e) \
{ \
@ -170,18 +180,19 @@ namespace Firebird
FB_UDR_UNRECOGNIZED_EXCEPTION, \
strlen(FB_UDR_UNRECOGNIZED_EXCEPTION)); \
} \
return false; \
\
return 0; \
} \
::Firebird::Udr::ProcedureFactoryImpl<FB_UDR_PROCEDURE(name)> ProcFactory##name(#name);
\
bool FB_CALL fetch0(::Firebird::Error* error)
#define FB_UDR_BEGIN_DECLARE_TRIGGER(name) \
class FB_UDR_TRIGGER(name) : public ::Firebird::Udr::Trigger \
class FB_UDR_TRIGGER(name) : public ::Firebird::Udr::Trigger<FB_UDR_TRIGGER(name)> \
{ \
public: \
virtual void FB_CALL execute(::Firebird::Error* error, ::Firebird::ExternalContext* context, \
::Firebird::ExternalTrigger::Action action, UCHAR* oldMsg, UCHAR* newMsg); \
private:
::Firebird::ExternalTrigger::Action action, UCHAR* oldMsg, UCHAR* newMsg);
#define FB_UDR_END_DECLARE_TRIGGER(name) \
};
@ -425,7 +436,7 @@ protected:
};
class Procedure;
template <typename T> class Procedure;
class Helper
@ -456,97 +467,133 @@ public:
};
template <typename This, typename Procedure, typename InMessage, typename OutMessage>
class ResultSet : public ExternalResultSet, public Helper
{
public:
ResultSet(Firebird::ExternalContext* aContext, Firebird::Udr::Procedure* aProcedure,
UCHAR* aInMsg, UCHAR* aOutMsg)
ResultSet(Firebird::ExternalContext* aContext, Procedure* aProcedure,
InMessage* aIn, OutMessage* aOut)
: context(aContext),
procedure(aProcedure),
inMsg(aInMsg),
outMsg(aOutMsg)
{
}
virtual ~ResultSet()
in(aIn),
out(aOut)
{
}
public:
virtual void FB_CALL dispose(Firebird::Error* /*error*/)
{
delete this;
delete static_cast<This*>(this);
}
protected:
Firebird::ExternalContext* context;
Firebird::Udr::Procedure* procedure;
UCHAR* inMsg;
UCHAR* outMsg;
Procedure* procedure;
InMessage* in;
OutMessage* out;
};
// This class is used to fix an apparent bug with clang, where the object is wrongly initialized
// and overwrites the members set in the operator new.
template <typename T>
class Routine : public T
{
public:
Routine()
{
}
};
template <typename This>
class Function : public ExternalFunction, public Helper
{
public:
virtual ~Function()
{
}
public:
virtual void FB_CALL dispose(Error* /*error*/)
{
delete this;
delete static_cast<This*>(this);
}
void FB_CALL getCharSet(Error* /*error*/, ExternalContext* /*context*/, Utf8* /*name*/, uint /*nameSize*/)
virtual void FB_CALL getCharSet(Error* /*error*/, ExternalContext* /*context*/,
Utf8* /*name*/, uint /*nameSize*/)
{
}
void* operator new(size_t size, const IRoutineMetadata* metadata)
{
Function* p = reinterpret_cast<Function*>(::new char[size]);
p->metadata = metadata;
return p;
}
void operator delete(void* p)
{
::delete [] static_cast<char*>(p);
}
public:
const IRoutineMetadata* metadata;
};
template <typename This>
class Procedure : public ExternalProcedure, public Helper
{
public:
virtual ~Procedure()
{
}
public:
virtual void FB_CALL dispose(Error* /*error*/)
{
delete this;
delete static_cast<This*>(this);
}
void FB_CALL getCharSet(Error* /*error*/, ExternalContext* /*context*/, Utf8* /*name*/, uint /*nameSize*/)
virtual void FB_CALL getCharSet(Error* /*error*/, ExternalContext* /*context*/,
Utf8* /*name*/, uint /*nameSize*/)
{
}
void* operator new(size_t size, const IRoutineMetadata* metadata)
{
Procedure* p = reinterpret_cast<Procedure*>(::new char[size]);
p->metadata = metadata;
return p;
}
void operator delete(void* p)
{
::delete [] static_cast<char*>(p);
}
public:
const IRoutineMetadata* metadata;
};
template <typename This>
class Trigger : public ExternalTrigger, public Helper
{
public:
virtual ~Trigger()
{
}
public:
virtual void FB_CALL dispose(Error* /*error*/)
{
delete this;
delete static_cast<This*>(this);
}
void FB_CALL getCharSet(Error* /*error*/, ExternalContext* /*context*/, Utf8* /*name*/, uint /*nameSize*/)
virtual void FB_CALL getCharSet(Error* /*error*/, ExternalContext* /*context*/,
Utf8* /*name*/, uint /*nameSize*/)
{
}
void* operator new(size_t size, const IRoutineMetadata* metadata)
{
Trigger* p = reinterpret_cast<Trigger*>(::new char[size]);
p->metadata = metadata;
return p;
}
void operator delete(void* p)
{
::delete [] static_cast<char*>(p);
}
public:
const IRoutineMetadata* metadata;
};
@ -569,9 +616,7 @@ public:
virtual ExternalFunction* FB_CALL newItem(const IRoutineMetadata* metadata)
{
Function* function = new T();
function->metadata = metadata;
return function;
return new(metadata) Routine<T>;
}
private:
@ -596,9 +641,7 @@ public:
virtual ExternalProcedure* FB_CALL newItem(const IRoutineMetadata* metadata)
{
Procedure* procedure = new T();
procedure->metadata = metadata;
return procedure;
return new(metadata) Routine<T>;
}
private:
@ -623,9 +666,7 @@ public:
virtual ExternalTrigger* FB_CALL newItem(const IRoutineMetadata* metadata)
{
Trigger* trigger = new T();
trigger->metadata = metadata;
return trigger;
return new(metadata) Routine<T>;
}
private:
@ -637,4 +678,4 @@ private:
} // namespace Udr
} // namespace Firebird
#endif // FIREBIRD_PLUGIN_UDR_CPP
#endif // FIREBIRD_UDR_CPP_ENGINE

1
src/include/ibase.h Normal file
View File

@ -0,0 +1 @@
#include "../jrd/ibase.h"

View File

@ -15,6 +15,7 @@ git add src/include/firebird/impl/boost/preprocessor/detail
git add src/include/firebird/impl/boost/preprocessor/repetition/detail
rm gen/boost
#git commit src/include/firebird/impl/boost
#rm -rf src/include/firebird/impl/boost
#git checkout -- src/include/firebird
echo Now run this:
echo git commit src/include/firebird/impl/boost
echo rm -rf src/include/firebird/impl/boost
echo git checkout -- src/include/firebird