mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 21:23:04 +01:00
Work in progress on message-based external functions and procedures.
This commit is contained in:
parent
5a414ee680
commit
4f5dd005ac
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
112
src/include/firebird/Message.h
Normal file
112
src/include/firebird/Message.h
Normal 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
|
@ -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
1
src/include/ibase.h
Normal file
@ -0,0 +1 @@
|
||||
#include "../jrd/ibase.h"
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user