Subject RE: [firebird-support] rFunc UDF - linux and Windows
Author Helen Borrie
At 12:12 AM 9/03/2008, you wrote:
>[quote helen]
>The fbudf ROUND function passes and returns its arguments and result BY
>DESCRIPTOR. That means that the engine will take care of details like scale
>and precision in the input argument and return the expected result. It
>*doesn't* mean that a real is an invalid input argument -- unless you pass
>one that has too much precision, i.e., a double precision or a numeric with
>precision > 9.
>[/quote helen]

As an update on this (remembering a comment from Claudio one time), either i64round() or round() should work with any valid data. Internally, the function call would process the descriptor of the input and execute the appropriate function call. You can declare both functions if you want the specifically different output types, but neither should except *if the data is valid*.


>I tried with some of my trigger ( I have about 60 to translate... ) but
>nothing todo... Here an example
>
>CREATE TRIGGER T_LCR_AIUD_AGGIORNA_LCT FOR LCR
>ACTIVE AFTER INSERT OR UPDATE OR DELETE POSITION 10
>AS
> declare variable quantita_tum float;
> declare variable quantita float;
> declare variable progressivo integer;
>begin
>...
> if (updating) then
> begin
> progressivo = old.progressivo;
> quantita_tum = i64round(new.quantita_tum - old.quantita_tum, 4);
> quantita = i64round(new.quantita - old.quantita, 4);
> end
>...
>
>but an error was caused with this cause esecution
>
>Invalid data type, length, or value.
>function I64ROUND could not be matched.

You should ensure that the data types declared for your variables are compatible with the results returned from the functions. For example:

declare external function i64Round
numeric(18, 4) by descriptor, numeric(18, 4) by descriptor
returns parameter 2
entry_point 'fbround' module_name 'fbudf'

-- says that i64round will return a result (parameter 2) that is numeric(18,4). Your 32-bit variables (float and integer) are not compatible with numeric(18,4).

Note too that this trigger code would throw this exception if either new.quantita or old.quantita was null. NULL is not a valid argument to an arithmetic function. Your trigger should test for null and not apply the rounding function if either the OLD or the NEW value were null. If you don't understand the difference between NULL and values, there's an excellent Null Guide document available at the Firebird website.

>which are difference sing by descripting parameter when I have to call a un
>UDF function from one that use double parameter?

I don't understand what your question is, but nothing beats "learning by your mistakes": declare both functions in your test database and try out various argument types (including invalid ones) to see what results you get, e.g.,

SELECT ROUND( cast(214748.3648 as numeric(18,4)) )
as roundresult from rdb$database

...and so on...

And fix up the logic in any of your triggers that are not handling NULLs. ;-)

./heLen