Fortran language scalar function
The following example shows a simple scalar function that sums a set of numbers. This example starts from the beginning to construct a simple AE. It uses the following file name: applyop.f
Code
- Create the program and call
nzaeRun()
. This call sets up the AE and then makes a callback tonzaeHandleRequest()
, which is necessary for Fortran implementation. This can typically be accomplished by using:program applyopProgram call nzaeRun() stop end subroutine nzaeHandleRequest(handle) c Our custom Fortran code will go here. return end
- Complete the custom Fortran code. In this UDF, you pass in a string operator, which is either a
"+" (add) or a "*" (multiply), as well as two integers. The code returns either the product or the
sum of the integers. In SQL, a simple version of this might be called by
either:
orSELECT applyop('+', 3, 5);
SELECT applyop('*', 3, 5);
Although the mentioned example has only one input, the NPS system deals with streams of input. Therefore, the NPS system is more likely to use:SELECT applyop(mytable.operator, mytable.value1, mytable.value2) FROM mytable;
In the first example, the NPS system takes the constants, "+", 3, and 5 and turns them into a stream of length one containing three elements. Internally, all of the mentioned cases are handled in the same manner and the assumption can be made that there are multiple inputs to the
applyop
AE. - A loop handling input is needed, which in Fortran 77 can be accomplished with an
if
statement and agoto
. For example:program applyopProgram call nzaeRun() stop end subroutine nzaeHandleRequest(handle) integer hasNext, leftInput, rightInput, result character operator hasNext = -1 10 call nzaeGetNext(handle, hasNext) if (hasNext .eq. 0) then goto 20 endif c Our loop work will go here. goto 10 20 return end
Note the initialization of the
hasNext
variable. This is necessary for "out" variables that call into the underlying interface. Without this, thehasNext
pointer remains unallocated and cannot receive data from the underlying call. ThenzaeGetNext()
function sets the variablehasNext
to 1 (TRUE) if there is another element in the stream, and to 0 (FALSE) if the stream is done. - Add the logic:
program applyOpProgram call nzaeRun() stop end subroutine nzaeHandleRequest(handle) integer hasNext, leftInput, rightInput, isNull, result character operator hasNext = -1 leftInput = 0 rightInput = 0 operator = 'f' isNull = 0 10 call nzaeGetNext(handle, hasNext) if (hasNext .eq. 0) then goto 20 endif c GET OUR INPUT. call nzaeGetInputString(handle, 0, operator, isNull) call nzaeGetInputInt32(handle, 1, leftInput, isNull) call nzaeGetInputInt32(handle, 2, rightInput, isNull) c OPERATE. if (operator .eq. '+') then result = leftInput + rightInput else if (operator .eq. '*') then result = leftInput * rightInput else call nzaeUserError(handle, 'Unhandled operator.') endif c OUTPUT. call nzaeSetOutputInt32(handle, 0, result) call nzaeOutputResult(handle) goto 10 20 return end
Each input in the loop contains the three elements that are passed into the function. The function
nzaeGetInputX()
takes the handle that represents one user request, a column index that in this case specifies 0 for operator, 1 for left input and 2 for right input, and the output variable. The functionnzaeUserError()
reports an error to the SQL user. The functionnzaeSetOutputX()
outputs the result. Because this is run as a UDF, there can be only one column in the result. A later example demonstrates how to use UDTFs to output multiple columns. When the code is complete, it must be compiled and registered.
Compilation
$NZ_EXPORT_DIR/ae/utilities/bin/compile_ae --language fortran --version 3 \
--template compile --exe applyopFortran applyop.f
The output executables, one for the host and one for the SPU, are placed under the host and spu directories in /nz/export/ae/applications/$NZ_USER/$NZ_DATABASE
Registration
$NZ_EXPORT_DIR/ae/utilities/bin/register_ae --language fortran --version 3 \
--template udf --exe applyopFortran \
--sig "applyop_fortran(varchar(1), int4, int4)" --return int4
Running
SELECT applyop_fortran('+', 4, 10);
APPLYOP
---------
14
(1 row)
nzaeHandleRequest()
, you
call nzaeUserError()
to send an error. The following example triggers an
error:SELECT applyop_fortran('-',1,2);
ERROR: Unhandled operator.