Fortran言語のスカラー関数

次の例は、数値の集合を合計する単純なスカラー関数を示している。 この例では、単純なAEを作るところから始める。 ファイル名は「applyop.f

コード

  1. プログラムを作成し、「nzaeRun()呼び出す。 この呼び出しはAEをセットアップし、Fortranの実装に必要なコールバックを'nzaeHandleRequest()に行う。 これは通常、以下の方法で実現できる:
    program applyopProgram
    call nzaeRun()
    stop
    end
    subroutine nzaeHandleRequest(handle)
    c Our custom Fortran code will go here.
    return
    end
  2. カスタムFortranコードを完成させる。 このUDFでは、"+"(加算)または "*"(乗算)の文字列演算子と、2つの整数を渡す。 このコードは整数の積か和を返す。 SQLでは、この単純なバージョンは次のどちらかで呼び出される:
    SELECT applyop('+', 3, 5);
    または
    SELECT applyop('*', 3, 5);
    前述の例では入力は1つだけだが、NPSシステムは入力のストリームを扱う。 従って、NPSシステムの方が利用しやすい:
    SELECT applyop(mytable.operator, mytable.value1, mytable.value2) FROM mytable;

    最初の例では、NPSシステムは定数 "+"、3、5を受け取り、それらを3つの要素を含む長さ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ポインタは未割り当てのままとなり、基礎となるコールからデータを受け取ることができない。 nzaeGetNext()関数は、ストリームに別の要素があれば変数 'hasNextに1(TRUE)を設定し、ストリームが終了すれば0(FALSE)を設定する。

  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

    ループ内の各入力には、関数に渡される3つの要素が含まれている。 関数'nzaeGetInputX()は、1つのユーザーリクエストを表すハンドル、列インデックス(この場合、0が演算子、1が左入力、2が右入力を表す)、および出力変数を受け取る。 関数'nzaeUserError()はSQLユーザーにエラーを報告する。 関数「nzaeSetOutputX()」は結果を出力する。 これはUDFとして実行されるため、結果には1つの列しか存在しない。 後の例では、UDTFを使って複数の列を出力する方法を示す。 コードが完成したら、コンパイルして登録しなければならない。

コンパイル

コードをコンパイルする:
$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

登録

実行可能ファイルを登録する:
$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.