Java言語スカラー関数

この例では以下のファイル名を使用している:

TestJavaInterface.java

コード

この例のコードは、ちょっとした変更で、このプログラムがリモート・モードで動作することを示している。 変更点はメインにあり、getAPIの周りにループが追加され、2回呼び出されるようになっている。 接続がリモートの場合、新しいスレッドで実行され、新しい接続を待つように引き渡される。 最後に、接続がリモートでない場合は、最初の反復の後にループを抜ける。 このコードはローカルAEのように動作し、リモートAEとして2つの反復を処理する。

import org.netezza.ae.*;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

public class TestJavaInterface {

    private static final Executor exec =
        Executors.newCachedThreadPool();

    public static final void main(String [] args) {
        try {
            mainImpl(args);
        } catch (Throwable t) {
            System.err.println(t.toString());
            NzaeUtil.logException(t, "main");
        }
    }

    public static final void mainImpl(String [] args) {
        NzaeApiGenerator helper = new NzaeApiGenerator();
 
       while (true) {
           final NzaeApi api = helper.getApi(NzaeApi.FUNCTION);
           if (api.apiType == NzaeApi.FUNCTION) {
               if (!helper.isRemote()) {
                   run(api.aeFunction);
                   break;
               } else {
                   Runnable task = new Runnable() {
                           public void run() {
                               try {
                                   TestJavaInterface.run(api.aeFunction);
                               } finally {
                                   api.aeFunction.close();
                               }
                           }
                       };
                   exec.execute(task);
               }
           }
        }
        helper.close();
    }

    public static class MyHandler implements NzaeMessageHandler
    {
        public void evaluate(Nzae ae, NzaeRecord input, NzaeRecord output) { 
            final NzaeMetadata meta = ae.getMetadata();
  
            int op = 0;
            double result = 0;

            if (meta.getOutputColumnCount() != 1 ||
                meta.getOutputNzType(0) != NzaeDataTypes.NZUDSUDX_DOUBLE) {
                throw new NzaeException("expecting one output column of type
double");

            }
            if (meta.getInputColumnCount() < 1) {
                throw new NzaeException("expecting at least one input column");
            }
            if (meta.getInputNzType(0) != NzaeDataTypes.NZUDSUDX_FIXED &&
                meta.getInputNzType(0) != NzaeDataTypes.NZUDSUDX_VARIABLE) {
                throw new NzaeException("first input column expected to be a
string type");
            }

            for (int i = 0; i < input.size(); i++) {
                if (input.getField(i) == null) {
                continue;
            }
            int dataType = meta.getInputNzType(i);
            if (i == 0) {
                if (!(dataType == NzaeDataTypes.NZUDSUDX_FIXED
                        || dataType == NzaeDataTypes.NZUDSUDX_VARIABLE)) {
 
                    ae.userError("first column must be a string");
                }
                String opStr = input.getFieldAsString(0);
                if (opStr.equals("*")) {
                    result = 1;
                    op = OP_MULT;
                }
                else if (opStr.equals("+")) {
                    result = 0;
                    op = OP_ADD;
                }
                else {
                    ae.userError("invalid operator = " + opStr);
                }
                continue;
            }
            switch (dataType) {
                case NzaeDataTypes.NZUDSUDX_INT8:
                case NzaeDataTypes.NZUDSUDX_INT16:
                case NzaeDataTypes.NZUDSUDX_INT32:
                case NzaeDataTypes.NZUDSUDX_INT64:
                case NzaeDataTypes.NZUDSUDX_FLOAT:
                case NzaeDataTypes.NZUDSUDX_DOUBLE:
                case NzaeDataTypes.NZUDSUDX_NUMERIC32:
                case NzaeDataTypes.NZUDSUDX_NUMERIC64:
                case NzaeDataTypes.NZUDSUDX_NUMERIC128:
                    switch (op) {
                        case OP_ADD:
                            result +=
input.getFieldAsNumber(i).doubleValue();
                            break;
                        case OP_MULT:
                            result *=
input.getFieldAsNumber(i).doubleValue();
                            break;
                    default:
                        break;
                    }
                    break;
                default:
                    break;
            }
        }   // end of column for loop

        output.setField(0, result);
        }

     }
     private static final int OP_ADD = 1;
     private static final int OP_MULT = 2;

     public static int run(Nzae ae)
     {
         ae.run(new MyHandler());
         return 0;
     }
}

コンパイル

ローカルモードと同様に標準コンパイルを使用する:

$NZ_EXPORT_DIR/ae/utilities/bin/compile_ae --language java --template \
     compile TestJavaInterface.java --version 3

登録

登録方法は若干異なる。 まずこれを実行して登録する:

$NZ_EXPORT_DIR/ae/utilities/bin/register_ae --sig "rem_applyop_java(varargs)" \
     --return "double" --class AeUdf --language java --template udf \
     --define "java_class=TestJavaInterface" --version 3 --remote \
     --rname testjavapi

これは、コードがリモート名testjavapiのリモートaeとして登録されることを指定します。 さらに、ランチャーも登録されている:

$NZ_EXPORT_DIR/ae/utilities/bin/register_ae --sig "rem_applyop_launch(int8)" \
     --return "TABLE(aeresult varchar(255))" --class AeUdtf --language java \
     --template udtf --define "java_class=TestJavaInterface" --version 3 \
     --remote --rname testjavapi --launch

rname--exe--sigの名前部分を除いて、すべてのランチャーは上記のようになる。 この場合、UDTFがすべてのランチャーのインターフェースだからだ。 rnameの値は、コード中の名前と一致しなければならない。

実行中

リモートモードでAEを実行するには、実行ファイルを "サーバー "として実行する この例では、ホスト上で実行されるクエリーだけを処理する。 通常、AEはSPUでも開始される。 ホスト上でインスタンスを起動する:

SELECT * FROM TABLE WITH FINAL(rem_applyop_launch(0));
                                AERESULT
-------------------------------------------------------------------------
 tran: 14896 session: 18286 DATA slc: 0 hardware: 0 machine: bdrosendev process:
15937 thread: 15938
(1 row)

テーブル・ファンクション・スタイル・ランチャーを呼び出すには、異なる構文が使われていることに注目してほしい。 これは、UDTFベースのAEを呼び出す際に使用される構文である。 次にAEを走らせる:

SELECT rem_applyop_java('+', 4,5,1.1);
 REM_APPLYOP_JAVA
------------------
 10.1
(1 row)

最後に、エラーを引き起こす:

SELECT rem_applyop_java(1);
ERROR: first input column expected to be a string type