/* * 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): ______________________________________. * * Paul Reeves, 2023 * */ #define FB_UDR_STATUS_TYPE ::Firebird::ThrowStatusWrapper #include #include #include #include #include #ifdef HAVE_MATH_H #include #endif #ifdef HAVE_STRING_H #include #endif #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #ifdef HAVE_SYS_TIMEB_H # include #endif #ifdef HAVE_LOCALE_H #include #endif #include using namespace Firebird; // First, let's start with a function from the UdfBackwardCompatibility // library and add some additional comments. // We will also use self-docmenting variable names // ////////////////////////////////////////////////// /*** * create function div ( * anumerator integer, * adenominator integer * ) returns double precision * external name 'udf_compat!UC_div!Divide anumerator by adenominator' * engine udr; ***/ FB_UDR_BEGIN_FUNCTION(UC_div) // Divide integer anumerator 1 by integer adenominator using the stdlib FB_UDR_MESSAGE(InMessage, (FB_INTEGER, anumerator) (FB_INTEGER, adenominator) ); FB_UDR_MESSAGE(OutMessage, (FB_DOUBLE, result) ); FB_UDR_EXECUTE_FUNCTION { if (in->anumeratorNull || in->adenominatorNull) { out->resultNull = FB_TRUE; out->result = 0; } else { out->resultNull = FB_FALSE; if (in->adenominator) { out->result = div(in->anumerator, in->adenominator).quot; } else { out->result = std::numeric_limits::infinity(); ISC_STATUS_ARRAY StatusVector = {isc_arg_gds, isc_arith_except, isc_arg_gds, isc_exception_integer_divide_by_zero, isc_arg_end}; FbException::check(isc_exception_integer_divide_by_zero, status, StatusVector); } } } FB_UDR_END_FUNCTION /*** DDL create function flagged ( flags integer, flag integer ) returns integer external name 'my_first_udr_kit!MFK_flagged!How is this function used?' engine udr; ***/ FB_UDR_BEGIN_FUNCTION(MFK_flagged) FB_UDR_MESSAGE(InMessage, (FB_INTEGER, flags) (FB_INTEGER, flag) ); FB_UDR_MESSAGE(OutMessage, (FB_INTEGER, result) ); FB_UDR_EXECUTE_FUNCTION { // Original code // if ( flags == NULL ) { // return 0; // } if ( in->flagsNull ) { out->resultNull = FB_TRUE; out->result = 0; } else { out->resultNull = FB_FALSE; // Original code // ISC_UINT64 i = ( 1ULL << *flag ); // return ( *flags & i ) ? 1 : 0; ISC_UINT64 i = ( 1ULL << in->flag ); out->result = ( in->flags & i ) ? 1 : 0; } } FB_UDR_END_FUNCTION /*** DDL create function Blob_Save ( afilename varchar(8191), ablobcallback BLOB ) returns bigint external name 'my_first_udr_kit!MFK_Blob_Save!Load file and save to Blob' engine udr; ***/ FB_UDR_BEGIN_FUNCTION(MFK_Blob_Save) FB_UDR_MESSAGE(InMessage, (FB_VARCHAR, afilename) (FB_BLOB, ablobcallback) ); FB_UDR_MESSAGE(OutMessage, (FB_BIGINT, result) ); FB_UDR_EXECUTE_FUNCTION { // // Test Input // if (!s || !b || !b->blob_handle) { // return NULL; // } // // open for write & as a binary... // FILE* file_ = fopen(s, "wb"); // if (file_ == NULL) { // ISC_INT64* res = MALLOC(sizeof(ISC_INT64)); // *res = -2; // return res; // } // // allocate buffer size to equal with max segment size // ISC_UCHAR* buffer = malloc(b->blob_max_segment); // if (!buffer) { // ISC_INT64* res = MALLOC(sizeof(ISC_INT64)); // *res = -1; // return res; // } // /* see BLOBCALLBACK in ibase.h */ // ISC_INT64* res = MALLOC(sizeof(ISC_INT64)); // *res = 0; // ISC_USHORT len; // while (b->blob_get_segment(b->blob_handle, buffer, b->blob_max_segment, &len)) { // *res += fwrite(buffer, 1, len, file_); // write buffer into given file.. (size as per 1 Byte for an element) // } // free(buffer); // fclose(file_); // return res; } FB_UDR_END_FUNCTION /*** DDL create function BillDate ( d integer, date ) returns date external name 'my_first_udr_kit!MFK_BillDate!What does BillDate do?' engine udr; ***/ // FB_UDR_BEGIN_FUNCTION(MFK_BillDate) // // FB_UDR_MESSAGE(InMessage, // (FB_INTEGER, d) // (FB_INTEGER, date) // ); // FB_UDR_MESSAGE(OutMessage, // (FB_DATE, result) // ); // // // FB_UDR_END_FUNCTION