diff --git a/builds/win32/msvc9/Firebird3_Examples.sln b/builds/win32/msvc9/Firebird3_Examples.sln index f8270e97ba..d293864d3d 100644 --- a/builds/win32/msvc9/Firebird3_Examples.sln +++ b/builds/win32/msvc9/Firebird3_Examples.sln @@ -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 diff --git a/examples/udr/UdrCppExample.cpp b/examples/udr/UdrCppExample.cpp index 32241a280f..418cb5ae23 100644 --- a/examples/udr/UdrCppExample.cpp +++ b/examples/udr/UdrCppExample.cpp @@ -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::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 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 retDesc(outMessage); + + int ret = 0; + + for (unsigned i = 0; i < count; ++i) + { + ParamDesc 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 startDesc(inMessage); + ParamDesc endDesc(inMessage); + + counter = inMessage[startDesc]; + end = inMessage[endDesc]; + } + + FB_UDR_FETCH_PROCEDURE + { + if (counter > end) + return false; + + MessageImpl outMessage(1, out); + ParamDesc 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 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 retDesc(outMessage); - - outMessage[retDesc] = counter; -} -FB_UDR_END_FUNCTION(wait_event) - - -FB_UDR_BEGIN_FUNCTION(sum_args) -{ - AutoDispose 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 retDesc(outMessage); - - int ret = 0; - - for (unsigned i = 0; i < count; ++i) - { - ParamDesc 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 startDesc(inMessage); - ParamDesc endDesc(inMessage); - - counter = inMessage[startDesc]; - end = inMessage[endDesc]; -} -FB_UDR_FETCH_PROCEDURE(gen_rows) -{ - if (counter > end) - return false; - - MessageImpl outMessage(1, outMsg); - ParamDesc retDesc(outMessage); - - outMessage[retDesc] = counter++; - - return true; -} -FB_UDR_END_PROCEDURE(gen_rows) - - FB_UDR_TRIGGER(replicate)::FB_UDR_TRIGGER(replicate)() : initialized(false) { diff --git a/src/include/firebird/Message.h b/src/include/firebird/Message.h new file mode 100644 index 0000000000..1853a220c6 --- /dev/null +++ b/src/include/firebird/Message.h @@ -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 + * 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 +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 diff --git a/src/include/firebird/UdrCppEngine.h b/src/include/firebird/UdrCppEngine.h index 7704b30c98..0a7b685744 100644 --- a/src/include/firebird/UdrCppEngine.h +++ b/src/include/firebird/UdrCppEngine.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 FuncFactory##name(#name); \ + \ + class FB_UDR_FUNCTION(name) : public ::Firebird::Udr::Function \ { \ - 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 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 ProcFactory##name(#name); \ + \ + class FB_UDR_PROCEDURE(name) : public ::Firebird::Udr::Procedure \ + { \ + 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 \ + { \ + public: \ + ResultSet(::Firebird::Error* error, ::Firebird::ExternalContext* context, \ + This* procedure, InMessage* inMsg, OutMessage* outMsg) \ + : ::Firebird::Udr::ResultSet( \ + 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 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 \ { \ 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 class Procedure; class Helper @@ -456,97 +467,133 @@ public: }; +template 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); } 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 +class Routine : public T +{ +public: + Routine() + { + } +}; + + +template class Function : public ExternalFunction, public Helper { -public: - virtual ~Function() - { - } - public: virtual void FB_CALL dispose(Error* /*error*/) { - delete this; + delete static_cast(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(::new char[size]); + p->metadata = metadata; + return p; + } + + void operator delete(void* p) + { + ::delete [] static_cast(p); + } + public: const IRoutineMetadata* metadata; }; +template class Procedure : public ExternalProcedure, public Helper { -public: - virtual ~Procedure() - { - } - public: virtual void FB_CALL dispose(Error* /*error*/) { - delete this; + delete static_cast(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(::new char[size]); + p->metadata = metadata; + return p; + } + + void operator delete(void* p) + { + ::delete [] static_cast(p); + } + public: const IRoutineMetadata* metadata; }; +template class Trigger : public ExternalTrigger, public Helper { -public: - virtual ~Trigger() - { - } - public: virtual void FB_CALL dispose(Error* /*error*/) { - delete this; + delete static_cast(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(::new char[size]); + p->metadata = metadata; + return p; + } + + void operator delete(void* p) + { + ::delete [] static_cast(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; } 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; } 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; } private: @@ -637,4 +678,4 @@ private: } // namespace Udr } // namespace Firebird -#endif // FIREBIRD_PLUGIN_UDR_CPP +#endif // FIREBIRD_UDR_CPP_ENGINE diff --git a/src/include/ibase.h b/src/include/ibase.h new file mode 100644 index 0000000000..7a09855d12 --- /dev/null +++ b/src/include/ibase.h @@ -0,0 +1 @@ +#include "../jrd/ibase.h" diff --git a/src/misc/copy-boost.sh b/src/misc/copy-boost.sh index 092a023700..3bc661b1e9 100755 --- a/src/misc/copy-boost.sh +++ b/src/misc/copy-boost.sh @@ -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