Make the div function use bigint for inputs and output

This commit is contained in:
Paul Reeves 2023-01-26 16:38:04 +01:00
parent 6064402f85
commit 2c9b46512b
4 changed files with 30 additions and 33 deletions

View File

@ -3,9 +3,9 @@
*/
create or alter function div (
anumerator integer, adenominator integer
anumerator bigint, adenominator bigint
)
returns double precision
returns bigint
external name 'MyFirstUDRKit!MFK_div!Divide anumerator by adenominator' engine udr;
grant execute on function div to public;

View File

@ -11,9 +11,9 @@ begin
function div (
anumerator integer, adenominator integer
anumerator bigint, adenominator bigint
)
returns double precision;
returns bigint;
function flagged (
flags integer, flag integer
@ -34,9 +34,9 @@ as
begin
function div (
anumerator integer, adenominator integer
anumerator bigint, adenominator bigint
)
returns double precision
returns bigint
external name 'MyFirstUDRKit!MFK_div!Divide anumerator by adenominator' engine udr;
function flagged (

View File

@ -37,6 +37,7 @@
#include <iostream>
#include <fstream>
#include <vector>
#include <memory>
#ifdef HAVE_MATH_H
#include <math.h>
@ -78,23 +79,25 @@ using namespace Firebird;
/***
* create function div (
* anumerator integer,
* adenominator integer
* ) returns double precision
* anumerator bigint,
* adenominator bigint
* ) returns bigint
* external name 'MyFirstUDRKit!MFK_div!Divide anumerator by adenominator'
* engine udr;
***/
FB_UDR_BEGIN_FUNCTION(MFK_div)
// Divide integer anumerator 1 by integer adenominator using the stdlib
// Note this differs from the example that shifts with firebird as it returns
// a bigint, not a double precision
//BEGIN
FB_UDR_MESSAGE(InMessage,
(FB_INTEGER, anumerator)
(FB_INTEGER, adenominator)
(FB_BIGINT, anumerator)
(FB_BIGINT, adenominator)
);
FB_UDR_MESSAGE(OutMessage,
(FB_DOUBLE, result)
(FB_BIGINT, result)
);
FB_UDR_EXECUTE_FUNCTION
@ -108,12 +111,11 @@ FB_UDR_EXECUTE_FUNCTION
{
out->resultNull = FB_FALSE;
if (in->adenominator) {
out->result = div(in->anumerator, in->adenominator).quot;
out->result = std::div(in->anumerator, in->adenominator).quot;
}
else
{
// This is old style - surely we can do better?
out->result = std::numeric_limits<double>::infinity();
out->result = int( std::numeric_limits<double>::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);
@ -121,7 +123,7 @@ FB_UDR_EXECUTE_FUNCTION
}
}
FB_UDR_END_FUNCTION
//END
@ -130,11 +132,13 @@ create function flagged (
flags integer,
flag integer
) returns integer
external name 'MyFirstUDRKit!MFK_flagged!How is this function used?'
external name 'MyFirstUDRKit!MFK_flagged!Check if flag is set in flags. flag is zero-based.'
engine udr;
***/
FB_UDR_BEGIN_FUNCTION(MFK_flagged)
FB_UDR_MESSAGE(InMessage,
FB_UDR_BEGIN_FUNCTION (MFK_flagged)
//BEGIN
FB_UDR_MESSAGE(InMessage,
(FB_INTEGER, flags)
(FB_INTEGER, flag)
);
@ -145,10 +149,6 @@ FB_UDR_BEGIN_FUNCTION(MFK_flagged)
FB_UDR_EXECUTE_FUNCTION
{
// Original code
// if ( flags == NULL ) {
// return 0;
// }
if ( in->flagsNull != 0 ) {
out->resultNull = FB_TRUE;
out->result = 0;
@ -156,17 +156,12 @@ FB_UDR_BEGIN_FUNCTION(MFK_flagged)
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
//END
/*** DDL
* create or alter function LoadBlobFromFile (

View File

@ -6,14 +6,16 @@
create sequence test_div_seq;
commit;
create domain D_ID as BIGINT;
create domain D_DOUBLE as double precision;
create domain D_BIGINT as BIGINT;
create table test_div(
test_div_id d_id generated always as identity
, numerator D_BIGINT
, denominator D_BIGINT
, result D_DOUBLE
, result COMPUTED BY ( DIV(numerator, denominator) )
);
commit;