Funzione scalare in linguaggio Java
L'esempio seguente mostra una semplice funzione scalare che somma un insieme di numeri. Questo esempio parte dall'inizio per costruire un semplice AE. Utilizza il seguente nome di file: 'TestJavaInterface.java
Codice
- Inserire l'interfaccia Java. In genere si può ottenere questo risultato utilizzando:
import org.netezza.ae.*; - Scrivere un testo principale. Determinare un'API da utilizzare, in questo caso una funzione. Ottenere una connessione AE, locale o remota. Questo esempio utilizza una connessione AE locale. Esistono due interfacce che possono essere utilizzate per ottenere la connessione. Uno è quello che utilizza il "
NzaeFactorye l'altro quello che utilizza il "NzaeApiGenerator. Questo esempio utilizza la classe Generator, che è più semplice e può essere utilizzata anche per la modalità remota. Il programma dovrebbe apparire simile a:import org.netezza.ae.*; public class TestJavaInterface { 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(); final NzaeApi api = helper.getApi(NzaeApi.FUNCTION); helper.close(); } }Recupera un riferimento a '
NzaeApiche contiene un oggetto 'NzaeFunctionutilizzabile. - Quando la funzione è disponibile, aggiungere uno stub per richiamare la logica della funzione:
import org.netezza.ae.*; public class TestJavaInterface { 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(); final NzaeApi api = helper.getApi(NzaeApi.FUNCTION); run(api.aeFunction); helper.close(); } public static int run(Nzae aeFunc) { return 0; } } - Implementare la funzione.Esistono due modi per implementare una funzione. Una è quella di utilizzare direttamente l'interfaccia dell'oggetto '
Nzae. L'altra è implementare una classe derivata da 'NzaeMessageHandlerche fornisca un'interfaccia più semplice. In questo esempio, viene utilizzato il gestore di messaggi. Il secondo metodo è trattato in un esempio separato. Il gestore di messaggi può essere utilizzato solo per le funzioni che restituiscono una riga di output per ogni input. Inoltre, il gestore copre automaticamente alcuni dettagli della gestione degli errori.import org.netezza.ae.*; public class TestJavaInterface { 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(); final NzaeApi api = helper.getApi(NzaeApi.FUNCTION); run(api.aeFunction); 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; 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_INT32: 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; } }In questo esempio, la funzione run istanzia l'oggetto handler e poi invoca il metodo run della classe function sull'handler. Il gestore deve implementare un metodo evaluate, che prende un riferimento alla funzione e i riferimenti al record di input e al record di output. Per le funzioni normali, il record di output contiene una sola colonna. La valutazione può quindi recuperare i campi dal record di input e utilizzarli per impostare il campo di output. Questo codice fornisce una funzione di base, senza controllo degli errori, che deve prendere come primo argomento il segno più (+) o l'asterisco (*) e come argomenti successivi i valori INT32. Quindi somma o moltiplica i valori INT32 in base al valore dell'argomento specificato e restituisce il risultato come un doppio.
- La fase finale di preparazione del codice aggiunge il controllo degli errori e il supporto per altri tipi di dati.
import org.netezza.ae.*; public class TestJavaInterface { 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(); final NzaeApi api = helper.getApi(NzaeApi.FUNCTION); run(api.aeFunction); 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; } }Questo codice garantisce il numero e il tipo corretto di argomenti di input e il numero e il tipo corretto di argomenti di output. Supporta tutti i tipi di numeri interi: float, double e numeric. Quando il codice è completo, deve essere compilato e registrato.
Compilazione
$NZ_EXPORT_DIR/ae/utilities/bin/compile_ae --language java --template \
compile TestJavaInterface.java --version 3Gli argomenti specificano che si sta utilizzando il linguaggio Java, versione 3, con la compilazione del modello e la creazione del file 'TestJavaInterface.class dal file sorgente 'TestJavaInterface.java.
Registrazione
$NZ_EXPORT_DIR/ae/utilities/bin/register_ae --sig "applyop_java(varargs)" \
--return "double" --class AeUdf --language java --template udf \
--define "java_class=TestJavaInterface" --version 3Registra l'UDF " applyop_java, che accetta vari argomenti e restituisce un double. La classe è 'AeUdf e il modello è udf, che è vero per tutte le UDF AE. Questo è registrato nel database db e la classe java da eseguire è 'TestJavaInterface.
In esecuzione
SELECT applyop_java('+',1,2);
APPLYOP_JAVA
--------------
3
(1 row)
doOnce e si invia un errore utilizzando 'NzaeException. L'esempio seguente genera un errore:SELECT applyop_java('-',1,2);
ERROR: invalid operator = -