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 ( 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; external name 'MyFirstUDRKit!MFK_div!Divide anumerator by adenominator' engine udr;
grant execute on function div to public; grant execute on function div to public;

View File

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

View File

@ -37,6 +37,7 @@
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
#include <vector> #include <vector>
#include <memory>
#ifdef HAVE_MATH_H #ifdef HAVE_MATH_H
#include <math.h> #include <math.h>
@ -78,23 +79,25 @@ using namespace Firebird;
/*** /***
* create function div ( * create function div (
* anumerator integer, * anumerator bigint,
* adenominator integer * adenominator bigint
* ) returns double precision * ) returns bigint
* external name 'MyFirstUDRKit!MFK_div!Divide anumerator by adenominator' * external name 'MyFirstUDRKit!MFK_div!Divide anumerator by adenominator'
* engine udr; * engine udr;
***/ ***/
FB_UDR_BEGIN_FUNCTION(MFK_div) FB_UDR_BEGIN_FUNCTION(MFK_div)
// Divide integer anumerator 1 by integer adenominator using the stdlib // 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_UDR_MESSAGE(InMessage,
(FB_INTEGER, anumerator) (FB_BIGINT, anumerator)
(FB_INTEGER, adenominator) (FB_BIGINT, adenominator)
); );
FB_UDR_MESSAGE(OutMessage, FB_UDR_MESSAGE(OutMessage,
(FB_DOUBLE, result) (FB_BIGINT, result)
); );
FB_UDR_EXECUTE_FUNCTION FB_UDR_EXECUTE_FUNCTION
@ -108,12 +111,11 @@ FB_UDR_EXECUTE_FUNCTION
{ {
out->resultNull = FB_FALSE; out->resultNull = FB_FALSE;
if (in->adenominator) { if (in->adenominator) {
out->result = div(in->anumerator, in->adenominator).quot; out->result = std::div(in->anumerator, in->adenominator).quot;
} }
else else
{ {
// This is old style - surely we can do better? out->result = int( std::numeric_limits<double>::infinity() );
out->result = std::numeric_limits<double>::infinity();
ISC_STATUS_ARRAY StatusVector = {isc_arg_gds, isc_arith_except, ISC_STATUS_ARRAY StatusVector = {isc_arg_gds, isc_arith_except,
isc_arg_gds, isc_exception_integer_divide_by_zero, isc_arg_end}; isc_arg_gds, isc_exception_integer_divide_by_zero, isc_arg_end};
FbException::check(isc_exception_integer_divide_by_zero, status, StatusVector); FbException::check(isc_exception_integer_divide_by_zero, status, StatusVector);
@ -121,7 +123,7 @@ FB_UDR_EXECUTE_FUNCTION
} }
} }
FB_UDR_END_FUNCTION FB_UDR_END_FUNCTION
//END
@ -130,10 +132,12 @@ create function flagged (
flags integer, flags integer,
flag integer flag integer
) returns 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; engine udr;
***/ ***/
FB_UDR_BEGIN_FUNCTION (MFK_flagged) FB_UDR_BEGIN_FUNCTION (MFK_flagged)
//BEGIN
FB_UDR_MESSAGE(InMessage, FB_UDR_MESSAGE(InMessage,
(FB_INTEGER, flags) (FB_INTEGER, flags)
(FB_INTEGER, flag) (FB_INTEGER, flag)
@ -145,10 +149,6 @@ FB_UDR_BEGIN_FUNCTION(MFK_flagged)
FB_UDR_EXECUTE_FUNCTION FB_UDR_EXECUTE_FUNCTION
{ {
// Original code
// if ( flags == NULL ) {
// return 0;
// }
if ( in->flagsNull != 0 ) { if ( in->flagsNull != 0 ) {
out->resultNull = FB_TRUE; out->resultNull = FB_TRUE;
out->result = 0; out->result = 0;
@ -156,17 +156,12 @@ FB_UDR_BEGIN_FUNCTION(MFK_flagged)
else else
{ {
out->resultNull = FB_FALSE; out->resultNull = FB_FALSE;
// Original code
// ISC_UINT64 i = ( 1ULL << *flag );
// return ( *flags & i ) ? 1 : 0;
ISC_UINT64 i = ( 1ULL << in->flag ); ISC_UINT64 i = ( 1ULL << in->flag );
out->result = ( in->flags & i ) ? 1 : 0; out->result = ( in->flags & i ) ? 1 : 0;
} }
} }
FB_UDR_END_FUNCTION FB_UDR_END_FUNCTION
//END
/*** DDL /*** DDL
* create or alter function LoadBlobFromFile ( * create or alter function LoadBlobFromFile (

View File

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