Fortran语言标量函数

下面的示例展示了一个简单的标量函数,用于对一组数字求和。 本例从一开始就构建了一个简单的 AE。 它使用以下文件名:"applyop.f

代码

  1. 创建程序并调用 "nzaeRun()。 该调用会设置 AE,然后回调到 "nzaeHandleRequest(),这是实现Fortran所必需的。 这通常可以通过使用
    program applyopProgram
    call nzaeRun()
    stop
    end
    subroutine nzaeHandleRequest(handle)
    c Our custom Fortran code will go here.
    return
    end
  2. 完成定制的Fortran代码。 在此 UDF 中,您需要输入一个字符串运算符,即 "+"(加)或 "*"(乘),以及两个整数。 代码会返回乘积或整数之和。 在 SQL 中,其简单版本可以通过以下任一方式调用:
    SELECT applyop('+', 3, 5);
    SELECT applyop('*', 3, 5);
    虽然上述例子只有一个输入,但核动力源系统处理的是输入流。 因此,新农保系统更容易使用:
    SELECT applyop(mytable.operator, mytable.value1, mytable.value2) FROM mytable;

    在第一个例子中,NPS 系统将常数 "+"、3 和 5 转化为长度为 1 的包含三个元素的数据流。 在内部,所有提到的情况都是以同样的方式处理的,可以假设 "applyopAE 有多个输入。

  3. 需要一个处理输入的循环,这在Fortran77 中可以通过 "if语句和 "goto语句来实现。 例如:
    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

    注意 "hasNext变量的初始化。 这对于调用底层接口的 "out "变量来说是必要的。 否则,"hasNext指针将保持未分配状态,无法从底层调用中接收数据。 The nzaeGetNext() function sets the variable hasNext to 1 (TRUE) if there is another element in the stream, and to 0 (FALSE) if the stream is done.

  4. 添加逻辑:
    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

    循环中的每个输入都包含传入函数的三个元素。 函数 "nzaeGetInputX()接收代表一个用户请求的句柄、一列索引(在本例中,0 表示操作符,1 表示左输入,2 表示右输入)和输出变量。 函数 "nzaeUserError()向 SQL 用户报告错误。 函数 "nzaeSetOutputX()输出结果。 由于这是作为 UDF 运行的,因此结果中只能有一列。 后面的示例演示了如何使用 UDTF 输出多列。 代码完成后,必须进行编译和注册。

编译

编译代码
$NZ_EXPORT_DIR/ae/utilities/bin/compile_ae --language fortran --version 3 \
--template compile --exe applyopFortran applyop.f

输出的可执行文件,一个用于主机,一个用于 SPU,分别置于 "/nz/export/ae/applications/$NZ_USER/$NZ_DATABASE中的 "host和 "spu目录下。

注册

注册可执行文件:
$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

正在运行

现在可以在 SQL 中运行 AE:
SELECT applyop_fortran('+', 4, 10);
APPLYOP
---------
14
(1 row)
请注意,在代码中,当您验证 "nzaeHandleRequest()中的类型时,会调用 "nzaeUserError()来发送错误信息。 以下示例会引发错误:
SELECT applyop_fortran('-',1,2);
ERROR: Unhandled operator.