diff --git a/builds/posix/Makefile.in.plugins_examples b/builds/posix/Makefile.in.plugins_examples
index 6c4f398ac2..a6cfcefab2 100644
--- a/builds/posix/Makefile.in.plugins_examples
+++ b/builds/posix/Makefile.in.plugins_examples
@@ -55,7 +55,10 @@ LINK_PLUGIN_SYMBOLS = $(call LIB_LINK_MAPFILE,../$(PLUGIN_VERS))
all: udrcpp_example dc_example kh_example
-UDR_Objects = $(call makeObjects,../examples/udr,UdrCppExample.cpp)
+UDR_Objects = $(call makeObjects,../examples/udr,Functions.cpp) \
+ $(call makeObjects,../examples/udr,Procedures.cpp) \
+ $(call makeObjects,../examples/udr,Triggers.cpp)
+
UDR_Plugin = $(PLUGINS)/udr/$(LIB_PREFIX)udrcpp_example.$(SHRLIB_EXT)
AllObjects = $(UDR_Objects)
diff --git a/builds/win32/msvc10/udrcpp_example.vcxproj b/builds/win32/msvc10/udrcpp_example.vcxproj
index 526668b476..50831ea7c2 100644
--- a/builds/win32/msvc10/udrcpp_example.vcxproj
+++ b/builds/win32/msvc10/udrcpp_example.vcxproj
@@ -194,10 +194,13 @@
-
+
-
+
+
+
+
diff --git a/builds/win32/msvc10/udrcpp_example.vcxproj.filters b/builds/win32/msvc10/udrcpp_example.vcxproj.filters
index e19830b6b1..a8a401974c 100644
--- a/builds/win32/msvc10/udrcpp_example.vcxproj.filters
+++ b/builds/win32/msvc10/udrcpp_example.vcxproj.filters
@@ -14,18 +14,23 @@
-
+
Source files
-
- Header files
-
+
+ Source files
+
+
+
+
+ Source files
+
Resource files
-
\ No newline at end of file
+
diff --git a/builds/win32/msvc12/udrcpp_example.vcxproj b/builds/win32/msvc12/udrcpp_example.vcxproj
index e25e985cef..62a7fb760f 100644
--- a/builds/win32/msvc12/udrcpp_example.vcxproj
+++ b/builds/win32/msvc12/udrcpp_example.vcxproj
@@ -198,10 +198,13 @@
-
+
-
+
+
+
+
diff --git a/builds/win32/msvc12/udrcpp_example.vcxproj.filters b/builds/win32/msvc12/udrcpp_example.vcxproj.filters
index e19830b6b1..a8a401974c 100644
--- a/builds/win32/msvc12/udrcpp_example.vcxproj.filters
+++ b/builds/win32/msvc12/udrcpp_example.vcxproj.filters
@@ -14,18 +14,23 @@
-
+
Source files
-
- Header files
-
+
+ Source files
+
+
+
+
+ Source files
+
Resource files
-
\ No newline at end of file
+
diff --git a/builds/win32/msvc8/udrcpp_example.vcproj b/builds/win32/msvc8/udrcpp_example.vcproj
index 58119937af..eee7f32717 100644
--- a/builds/win32/msvc8/udrcpp_example.vcproj
+++ b/builds/win32/msvc8/udrcpp_example.vcproj
@@ -330,16 +330,15 @@
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
>
-
-
+
+
diff --git a/builds/win32/msvc9/udrcpp_example.vcproj b/builds/win32/msvc9/udrcpp_example.vcproj
index 95dfea3198..720c9b54db 100644
--- a/builds/win32/msvc9/udrcpp_example.vcproj
+++ b/builds/win32/msvc9/udrcpp_example.vcproj
@@ -327,16 +327,15 @@
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
>
-
-
+
+
diff --git a/examples/udr/Functions.cpp b/examples/udr/Functions.cpp
new file mode 100644
index 0000000000..5c77e40bcd
--- /dev/null
+++ b/examples/udr/Functions.cpp
@@ -0,0 +1,160 @@
+/*
+ * 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) 2008 Adriano dos Santos Fernandes
+ * and all contributors signed below.
+ *
+ * All Rights Reserved.
+ * Contributor(s): ______________________________________.
+ */
+
+#include "UdrCppExample.h"
+
+using namespace Firebird;
+
+
+//------------------------------------------------------------------------------
+
+
+/***
+create function wait_event (
+ event_name varchar(31) character set utf8 not null
+) returns integer not null
+ external name 'udrcpp_example!wait_event'
+ engine udr;
+***/
+FB_UDR_BEGIN_FUNCTION(wait_event)
+ FB_UDR_MESSAGE(InMessage,
+ (FB_VARCHAR(31 * 4), name)
+ );
+
+ FB_UDR_MESSAGE(OutMessage,
+ (FB_INTEGER, result)
+ );
+
+ FB_UDR_EXECUTE_FUNCTION
+ {
+ 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(status, context);
+ ISC_ULONG counter = 0;
+
+ FbException::check(isc_wait_for_event(
+ statusVector, &dbHandle, eveLen, eveBuffer, eveResult), status, statusVector);
+ isc_event_counts(&counter, eveLen, eveBuffer, eveResult);
+ FbException::check(isc_wait_for_event(
+ statusVector, &dbHandle, eveLen, eveBuffer, eveResult), status, statusVector);
+ isc_event_counts(&counter, eveLen, eveBuffer, eveResult);
+
+ isc_free((char*) eveBuffer);
+ isc_free((char*) eveResult);
+
+ out->resultNull = FB_FALSE;
+ out->result = counter;
+ }
+FB_UDR_END_FUNCTION
+
+
+/***
+create function sum_args (
+ n1 integer,
+ n2 integer,
+ n3 integer
+) returns integer
+ external name 'udrcpp_example!sum_args'
+ engine udr;
+***/
+FB_UDR_BEGIN_FUNCTION(sum_args)
+ // Without InMessage/OutMessage definitions, messages will be byte-based.
+
+ FB_UDR_CONSTRUCTOR
+ // , inCount(0)
+ {
+ // Get input metadata.
+ AutoRelease inMetadata(metadata->getInputMetadata(status));
+
+ // Get count of input parameters.
+ inCount = inMetadata->getCount(status);
+
+ inNullOffsets.reset(new unsigned[inCount]);
+ inOffsets.reset(new unsigned[inCount]);
+
+ for (unsigned i = 0; i < inCount; ++i)
+ {
+ // Get null offset of the i-th input parameter.
+ inNullOffsets[i] = inMetadata->getNullOffset(status, i);
+
+ // Get the offset of the i-th input parameter.
+ inOffsets[i] = inMetadata->getOffset(status, i);
+ }
+
+ // Get output metadata.
+ AutoRelease outMetadata(metadata->getOutputMetadata(status));
+
+ // Get null offset of the return value.
+ outNullOffset = outMetadata->getNullOffset(status, 0);
+
+ // Get offset of the return value.
+ outOffset = outMetadata->getOffset(status, 0);
+ }
+
+ // This function requires the INTEGER parameters and return value, otherwise it will crash.
+ // Metadata is inspected dynamically (in execute). This is not the fastest method.
+ FB_UDR_EXECUTE_FUNCTION
+ {
+ *(ISC_SHORT*) (out + outNullOffset) = FB_FALSE;
+
+ // Get a reference to the return value.
+ ISC_LONG& ret = *(ISC_LONG*) (out + outOffset);
+
+ // The return value is automatically initialized to 0.
+ ///ret = 0;
+
+ for (unsigned i = 0; i < inCount; ++i)
+ {
+ // If the i-th input parameter is NULL, set the output to NULL and finish.
+ if (*(ISC_SHORT*) (in + inNullOffsets[i]))
+ {
+ *(ISC_SHORT*) (out + outNullOffset) = FB_TRUE;
+ return;
+ }
+
+ // Read the i-th input parameter value and sum it in the referenced return value.
+ ret += *(ISC_LONG*) (in + inOffsets[i]);
+ }
+ }
+
+ unsigned inCount;
+ AutoArrayDelete inNullOffsets;
+ AutoArrayDelete inOffsets;
+ unsigned outNullOffset;
+ unsigned outOffset;
+FB_UDR_END_FUNCTION
+
+
+//------------------------------------------------------------------------------
+
+
+// This should be used in only one of the UDR library files.
+FB_UDR_IMPLEMENT_ENTRY_POINT
diff --git a/examples/udr/Procedures.cpp b/examples/udr/Procedures.cpp
new file mode 100644
index 0000000000..ea65e456c8
--- /dev/null
+++ b/examples/udr/Procedures.cpp
@@ -0,0 +1,212 @@
+/*
+ * 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) 2008 Adriano dos Santos Fernandes
+ * and all contributors signed below.
+ *
+ * All Rights Reserved.
+ * Contributor(s): ______________________________________.
+ */
+
+#include "UdrCppExample.h"
+
+using namespace Firebird;
+
+
+//------------------------------------------------------------------------------
+
+
+/***
+create procedure gen_rows (
+ start_n integer not null,
+ end_n integer not null
+) returns (
+ n integer not null
+)
+ external name 'udrcpp_example!gen_rows'
+ engine udr;
+***/
+FB_UDR_BEGIN_PROCEDURE(gen_rows)
+ // Without InMessage/OutMessage definitions, messages will be byte-based.
+
+ // Procedure variables.
+ unsigned inOffsetStart, inOffsetEnd, outNullOffset, outOffset;
+
+ // Get offsets once per procedure.
+ FB_UDR_CONSTRUCTOR
+ {
+ AutoRelease inMetadata(metadata->getInputMetadata(status));
+
+ inOffsetStart = inMetadata->getOffset(status, 0);
+ inOffsetEnd = inMetadata->getOffset(status, 1);
+
+ AutoRelease outMetadata(metadata->getOutputMetadata(status));
+
+ outNullOffset = outMetadata->getNullOffset(status, 0);
+ outOffset = outMetadata->getOffset(status, 0);
+ }
+
+ /*** Procedure destructor.
+ FB_UDR_DESTRUCTOR
+ {
+ }
+ ***/
+
+ FB_UDR_EXECUTE_PROCEDURE
+ {
+ counter = *(ISC_LONG*) (in + procedure->inOffsetStart);
+ end = *(ISC_LONG*) (in + procedure->inOffsetEnd);
+
+ *(ISC_SHORT*) (out + procedure->outNullOffset) = FB_FALSE;
+ }
+
+ // After procedure's execute definition, starts the result set definition.
+
+ FB_UDR_FETCH_PROCEDURE
+ {
+ if (counter > end)
+ return false;
+
+ *(ISC_LONG*) (out + procedure->outOffset) = counter++;
+ return true;
+ }
+
+ /*** ResultSet destructor.
+ ~ResultSet()
+ {
+ }
+ ***/
+
+ // ResultSet variables.
+ 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_MESSAGE(InMessage,
+ (FB_INTEGER, start)
+ (FB_INTEGER, end)
+ );
+
+ FB_UDR_MESSAGE(OutMessage,
+ (FB_INTEGER, result)
+ );
+
+ FB_UDR_EXECUTE_PROCEDURE
+ {
+ out->resultNull = FB_FALSE;
+ 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)
+ FB_UDR_MESSAGE(InMessage,
+ (FB_INTEGER, count)
+ );
+
+ FB_UDR_MESSAGE(OutMessage,
+ (FB_INTEGER, n0)
+ (FB_INTEGER, n1)
+ (FB_INTEGER, n2)
+ (FB_INTEGER, n3)
+ (FB_INTEGER, n4)
+ );
+
+ 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_CONSTRUCTOR
+ , n1(0),
+ n2(0)
+ {
+ }
+
+ ISC_LONG n2;
+
+ // FB_UDR_EXECUTE_PROCEDURE starts the ResultSet scope.
+ FB_UDR_EXECUTE_PROCEDURE
+ // This is the ResultSet (class) initializer.
+ , n3(procedure->n1), // n3 will start with the next value for n1 of the last execution
+ n4(0)
+ {
+ out->n0Null = out->n1Null = out->n2Null = out->n3Null = out->n4Null = FB_FALSE;
+
+ 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_PROCEDURE must be always after FB_UDR_EXECUTE_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
diff --git a/examples/udr/UdrCppExample.cpp b/examples/udr/Triggers.cpp
similarity index 50%
rename from examples/udr/UdrCppExample.cpp
rename to examples/udr/Triggers.cpp
index 079de7dbfc..fe0562f19a 100644
--- a/examples/udr/UdrCppExample.cpp
+++ b/examples/udr/Triggers.cpp
@@ -13,490 +13,21 @@
* The Original Code was created by Adriano dos Santos Fernandes
* for the Firebird Open Source RDBMS project.
*
- * Copyright (c) 2008 Adriano dos Santos Fernandes
+ * Copyright (c) 2008 Adriano dos Santos Fernandes
* and all contributors signed below.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
*/
-#define FB_UDR_STATUS_TYPE ::Firebird::ThrowStatusWrapper
-
-#include "ibase.h"
-#include "firebird/UdrCppEngine.h"
-#include
-#include
-
+#include "UdrCppExample.h"
using namespace Firebird;
-using namespace Firebird::Udr;
-
-
-namespace
-{
- template
- class AutoReleaseClear
- {
- public:
- static void clear(T* ptr)
- {
- if (ptr)
- ptr->release();
- }
- };
-
- template
- class AutoDisposeClear
- {
- public:
- static void clear(T* ptr)
- {
- if (ptr)
- ptr->dispose();
- }
- };
-
- template
- class AutoDeleteClear
- {
- public:
- static void clear(T* ptr)
- {
- delete ptr;
- }
- };
-
- template
- class AutoArrayDeleteClear
- {
- public:
- static void clear(T* ptr)
- {
- delete [] ptr;
- }
- };
-
- template
- class AutoImpl
- {
- public:
- AutoImpl(T* aPtr = NULL)
- : ptr(aPtr)
- {
- }
-
- ~AutoImpl()
- {
- Clear::clear(ptr);
- }
-
- AutoImpl& operator =(T* aPtr)
- {
- Clear::clear(ptr);
- ptr = aPtr;
- return *this;
- }
-
- operator T*()
- {
- return ptr;
- }
-
- operator const T*() const
- {
- return ptr;
- }
-
- bool operator !() const
- {
- return !ptr;
- }
-
- bool hasData() const
- {
- return ptr != NULL;
- }
-
- T* operator ->()
- {
- return ptr;
- }
-
- T* release()
- {
- T* tmp = ptr;
- ptr = NULL;
- return tmp;
- }
-
- void reset(T* aPtr = NULL)
- {
- if (aPtr != ptr)
- {
- Clear::clear(ptr);
- ptr = aPtr;
- }
- }
-
- private:
- // not implemented
- AutoImpl(AutoImpl&);
- void operator =(AutoImpl&);
-
- private:
- T* ptr;
- };
-
- template class AutoDispose : public AutoImpl >
- {
- public:
- AutoDispose(T* ptr = NULL)
- : AutoImpl >(ptr)
- {
- }
- };
-
- template class AutoRelease : public AutoImpl >
- {
- public:
- AutoRelease(T* ptr = NULL)
- : AutoImpl >(ptr)
- {
- }
- };
-
- template class AutoDelete : public AutoImpl >
- {
- public:
- AutoDelete(T* ptr = NULL)
- : AutoImpl >(ptr)
- {
- }
- };
-
- template class AutoArrayDelete : public AutoImpl >
- {
- public:
- AutoArrayDelete(T* ptr = NULL)
- : AutoImpl >(ptr)
- {
- }
- };
-}
//------------------------------------------------------------------------------
-/***
-create function wait_event (
- event_name varchar(31) character set utf8 not null
-) returns integer not null
- external name 'udrcpp_example!wait_event'
- engine udr;
-***/
-FB_UDR_BEGIN_FUNCTION(wait_event)
- FB_UDR_MESSAGE(InMessage,
- (FB_VARCHAR(31 * 4), name)
- );
-
- FB_UDR_MESSAGE(OutMessage,
- (FB_INTEGER, result)
- );
-
- FB_UDR_EXECUTE_FUNCTION
- {
- 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(status, context);
- ISC_ULONG counter = 0;
-
- FbException::check(isc_wait_for_event(
- statusVector, &dbHandle, eveLen, eveBuffer, eveResult), status, statusVector);
- isc_event_counts(&counter, eveLen, eveBuffer, eveResult);
- FbException::check(isc_wait_for_event(
- statusVector, &dbHandle, eveLen, eveBuffer, eveResult), status, statusVector);
- isc_event_counts(&counter, eveLen, eveBuffer, eveResult);
-
- isc_free((char*) eveBuffer);
- isc_free((char*) eveResult);
-
- out->resultNull = FB_FALSE;
- out->result = counter;
- }
-FB_UDR_END_FUNCTION
-
-
-/***
-create function sum_args (
- n1 integer,
- n2 integer,
- n3 integer
-) returns integer
- external name 'udrcpp_example!sum_args'
- engine udr;
-***/
-FB_UDR_BEGIN_FUNCTION(sum_args)
- // Without InMessage/OutMessage definitions, messages will be byte-based.
-
- FB_UDR_CONSTRUCTOR
- // , inCount(0)
- {
- // Get input metadata.
- AutoRelease inMetadata(metadata->getInputMetadata(status));
-
- // Get count of input parameters.
- inCount = inMetadata->getCount(status);
-
- inNullOffsets.reset(new unsigned[inCount]);
- inOffsets.reset(new unsigned[inCount]);
-
- for (unsigned i = 0; i < inCount; ++i)
- {
- // Get null offset of the i-th input parameter.
- inNullOffsets[i] = inMetadata->getNullOffset(status, i);
-
- // Get the offset of the i-th input parameter.
- inOffsets[i] = inMetadata->getOffset(status, i);
- }
-
- // Get output metadata.
- AutoRelease outMetadata(metadata->getOutputMetadata(status));
-
- // Get null offset of the return value.
- outNullOffset = outMetadata->getNullOffset(status, 0);
-
- // Get offset of the return value.
- outOffset = outMetadata->getOffset(status, 0);
- }
-
- // This function requires the INTEGER parameters and return value, otherwise it will crash.
- // Metadata is inspected dynamically (in execute). This is not the fastest method.
- FB_UDR_EXECUTE_FUNCTION
- {
- *(ISC_SHORT*) (out + outNullOffset) = FB_FALSE;
-
- // Get a reference to the return value.
- ISC_LONG& ret = *(ISC_LONG*) (out + outOffset);
-
- // The return value is automatically initialized to 0.
- ///ret = 0;
-
- for (unsigned i = 0; i < inCount; ++i)
- {
- // If the i-th input parameter is NULL, set the output to NULL and finish.
- if (*(ISC_SHORT*) (in + inNullOffsets[i]))
- {
- *(ISC_SHORT*) (out + outNullOffset) = FB_TRUE;
- return;
- }
-
- // Read the i-th input parameter value and sum it in the referenced return value.
- ret += *(ISC_LONG*) (in + inOffsets[i]);
- }
- }
-
- unsigned inCount;
- AutoArrayDelete inNullOffsets;
- AutoArrayDelete inOffsets;
- unsigned outNullOffset;
- unsigned outOffset;
-FB_UDR_END_FUNCTION
-
-
-/***
-create procedure gen_rows (
- start_n integer not null,
- end_n integer not null
-) returns (
- n integer not null
-)
- external name 'udrcpp_example!gen_rows'
- engine udr;
-***/
-FB_UDR_BEGIN_PROCEDURE(gen_rows)
- // Without InMessage/OutMessage definitions, messages will be byte-based.
-
- // Procedure variables.
- unsigned inOffsetStart, inOffsetEnd, outNullOffset, outOffset;
-
- // Get offsets once per procedure.
- FB_UDR_CONSTRUCTOR
- {
- AutoRelease inMetadata(metadata->getInputMetadata(status));
-
- inOffsetStart = inMetadata->getOffset(status, 0);
- inOffsetEnd = inMetadata->getOffset(status, 1);
-
- AutoRelease outMetadata(metadata->getOutputMetadata(status));
-
- outNullOffset = outMetadata->getNullOffset(status, 0);
- outOffset = outMetadata->getOffset(status, 0);
- }
-
- /*** Procedure destructor.
- FB_UDR_DESTRUCTOR
- {
- }
- ***/
-
- FB_UDR_EXECUTE_PROCEDURE
- {
- counter = *(ISC_LONG*) (in + procedure->inOffsetStart);
- end = *(ISC_LONG*) (in + procedure->inOffsetEnd);
-
- *(ISC_SHORT*) (out + procedure->outNullOffset) = FB_FALSE;
- }
-
- // After procedure's execute definition, starts the result set definition.
-
- FB_UDR_FETCH_PROCEDURE
- {
- if (counter > end)
- return false;
-
- *(ISC_LONG*) (out + procedure->outOffset) = counter++;
- return true;
- }
-
- /*** ResultSet destructor.
- ~ResultSet()
- {
- }
- ***/
-
- // ResultSet variables.
- 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_MESSAGE(InMessage,
- (FB_INTEGER, start)
- (FB_INTEGER, end)
- );
-
- FB_UDR_MESSAGE(OutMessage,
- (FB_INTEGER, result)
- );
-
- FB_UDR_EXECUTE_PROCEDURE
- {
- out->resultNull = FB_FALSE;
- 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)
- FB_UDR_MESSAGE(InMessage,
- (FB_INTEGER, count)
- );
-
- FB_UDR_MESSAGE(OutMessage,
- (FB_INTEGER, n0)
- (FB_INTEGER, n1)
- (FB_INTEGER, n2)
- (FB_INTEGER, n3)
- (FB_INTEGER, n4)
- );
-
- 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_CONSTRUCTOR
- , n1(0),
- n2(0)
- {
- }
-
- ISC_LONG n2;
-
- // FB_UDR_EXECUTE_PROCEDURE starts the ResultSet scope.
- FB_UDR_EXECUTE_PROCEDURE
- // This is the ResultSet (class) initializer.
- , n3(procedure->n1), // n3 will start with the next value for n1 of the last execution
- n4(0)
- {
- out->n0Null = out->n1Null = out->n2Null = out->n3Null = out->n4Null = FB_FALSE;
-
- 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_PROCEDURE must be always after FB_UDR_EXECUTE_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
-
-
/***
Sample usage:
@@ -783,6 +314,3 @@ FB_UDR_BEGIN_TRIGGER(replicate_persons)
AutoRelease triggerMetadata;
AutoRelease stmt;
FB_UDR_END_TRIGGER
-
-
-FB_UDR_IMPLEMENT_ENTRY_POINT
diff --git a/examples/udr/UdrCppExample.h b/examples/udr/UdrCppExample.h
new file mode 100644
index 0000000000..f2a77ff069
--- /dev/null
+++ b/examples/udr/UdrCppExample.h
@@ -0,0 +1,186 @@
+/*
+ * 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) 2015 Adriano dos Santos Fernandes
+ * and all contributors signed below.
+ *
+ * All Rights Reserved.
+ * Contributor(s): ______________________________________.
+ */
+
+#ifndef UDR_CPP_EXAMPLE_H
+#define UDR_CPP_EXAMPLE_H
+
+#define FB_UDR_STATUS_TYPE ::Firebird::ThrowStatusWrapper
+
+#include "ibase.h"
+#include "firebird/UdrCppEngine.h"
+#include
+#include
+
+
+namespace
+{
+ template
+ class AutoReleaseClear
+ {
+ public:
+ static void clear(T* ptr)
+ {
+ if (ptr)
+ ptr->release();
+ }
+ };
+
+ template
+ class AutoDisposeClear
+ {
+ public:
+ static void clear(T* ptr)
+ {
+ if (ptr)
+ ptr->dispose();
+ }
+ };
+
+ template
+ class AutoDeleteClear
+ {
+ public:
+ static void clear(T* ptr)
+ {
+ delete ptr;
+ }
+ };
+
+ template
+ class AutoArrayDeleteClear
+ {
+ public:
+ static void clear(T* ptr)
+ {
+ delete [] ptr;
+ }
+ };
+
+ template
+ class AutoImpl
+ {
+ public:
+ AutoImpl(T* aPtr = NULL)
+ : ptr(aPtr)
+ {
+ }
+
+ ~AutoImpl()
+ {
+ Clear::clear(ptr);
+ }
+
+ AutoImpl& operator =(T* aPtr)
+ {
+ Clear::clear(ptr);
+ ptr = aPtr;
+ return *this;
+ }
+
+ operator T*()
+ {
+ return ptr;
+ }
+
+ operator const T*() const
+ {
+ return ptr;
+ }
+
+ bool operator !() const
+ {
+ return !ptr;
+ }
+
+ bool hasData() const
+ {
+ return ptr != NULL;
+ }
+
+ T* operator ->()
+ {
+ return ptr;
+ }
+
+ T* release()
+ {
+ T* tmp = ptr;
+ ptr = NULL;
+ return tmp;
+ }
+
+ void reset(T* aPtr = NULL)
+ {
+ if (aPtr != ptr)
+ {
+ Clear::clear(ptr);
+ ptr = aPtr;
+ }
+ }
+
+ private:
+ // not implemented
+ AutoImpl(AutoImpl&);
+ void operator =(AutoImpl&);
+
+ private:
+ T* ptr;
+ };
+
+ template class AutoDispose : public AutoImpl >
+ {
+ public:
+ AutoDispose(T* ptr = NULL)
+ : AutoImpl >(ptr)
+ {
+ }
+ };
+
+ template class AutoRelease : public AutoImpl >
+ {
+ public:
+ AutoRelease(T* ptr = NULL)
+ : AutoImpl >(ptr)
+ {
+ }
+ };
+
+ template class AutoDelete : public AutoImpl >
+ {
+ public:
+ AutoDelete(T* ptr = NULL)
+ : AutoImpl >(ptr)
+ {
+ }
+ };
+
+ template class AutoArrayDelete : public AutoImpl >
+ {
+ public:
+ AutoArrayDelete(T* ptr = NULL)
+ : AutoImpl >(ptr)
+ {
+ }
+ };
+}
+
+#endif // UDR_CPP_EXAMPLE_H