Skalare Funktion in der Sprache C++ (Remote-Modus)

In diesem Beispiel wird der folgende Dateiname verwendet:

applyopcpp.cpp

Code erstellen

Der Code in diesem Beispiel zeigt, dass dieses Programm mit geringfügigen Änderungen im Remote-Modus funktioniert:

Die Änderung ist im Wesentlichen. Der erforderliche Name der entfernten AE-Verbindung, testcapi, wird festgelegt, und dann wird eine Schleife um getAPI hinzugefügt, damit es zweimal aufgerufen wird. Dieser Code funktioniert wie eine lokale AE und behandelt zwei Iterationen wie eine entfernte AE.

#include <nzaefactory.hpp>

using namespace nz::ae;

static int run(nz::ae::NzaeFunction *aeFunc);

int main(int argc, char * argv[])
{
    NzaeApiGenerator helper;
    // The following line is only needed if a launcher is not used
    helper.setName("testcapi");
    for (int i=0; i < 2; i++) {
        nz::ae::NzaeApi &api = helper.getApi(nz::ae::NzaeApi::FUNCTION);      
        run(api.aeFunction);
        if (!helper.isRemote())
            break;
    }

    return 0;
}

class MyHandler : public NzaeFunctionMessageHandler
{
public:
    MyHandler() {
        m_Once = false;
    }
    enum OperatorEnum
    {
        OP_ADD = 1,
        OP_MULT = 2
    } op;

    void doOnce(NzaeFunction& api) {
        const NzaeMetadata& meta = api.getMetadata();
        if (meta.getOutputColumnCount() != 1 ||
            meta.getOutputType(0) != NzaeDataTypes::NZUDSUDX_DOUBLE) {
            throw NzaeException("expecting one output column of type double");
        }
        if (meta.getInputColumnCount() < 1) {
            throw NzaeException("expecting at least one input column");
        }
        if (meta.getInputType(0) != NzaeDataTypes::NZUDSUDX_FIXED &&
            meta.getInputType(0) != NzaeDataTypes::NZUDSUDX_VARIABLE) {
            throw NzaeException("first input column expected to be a string
type");
        }
        m_Once = true;
    }

        void evaluate(NzaeFunction& api, NzaeRecord &input, NzaeRecord &result) {
    
        if (!m_Once)
            doOnce(api);
        double res = 0;

        NzaeField &field = input.get(0);
        if (field.isNull())
            throw NzaeException("first input column may not be null");
        NzaeStringField &sf = (NzaeStringField&) input.get(0);
        std::string strop = (std::string)sf;
        if (strop == "+")
            op = OP_ADD;
        else if (strop == "*") {
            op = OP_MULT;
            res = 1;
        }
        else
            throw NzaeException(NzaeException::format("unexpected operator %s", \
                strop.c_str()));

        for (int i=1 ; i < input.numFields(); i++) {
            NzaeField &inf = input.get(i);
            if (inf.isNull())
                continue;
            double temp = 0;
            bool ignore = false;
            switch (inf.type()) {
                case NzaeDataTypes::NZUDSUDX_INT8:
                {
                    NzaeInt8Field &sf = (NzaeInt8Field&)input.get(i);
                    temp = (int8_t)sf;
                    break;
                }
                case NzaeDataTypes::NZUDSUDX_INT16:
                {
                    NzaeInt16Field &sf = (NzaeInt16Field&)input.get(i);
                    temp = (int16_t)sf;
                    break;
                }
                case NzaeDataTypes::NZUDSUDX_INT32:
                {
                    NzaeInt32Field &sf = (NzaeInt32Field&)input.get(i);
                    temp = (int32_t)sf;
                    break;
                }
                case NzaeDataTypes::NZUDSUDX_INT64:
                {
                    NzaeInt64Field &sf = (NzaeInt64Field&)input.get(i);
                    temp = (int64_t)sf;
                    break;
                }
                case NzaeDataTypes::NZUDSUDX_FLOAT:
                {
                    NzaeFloatField &sf = (NzaeFloatField&)input.get(i);
                    temp = (float)sf;
                    break;
                }
                case NzaeDataTypes::NZUDSUDX_DOUBLE:
                {
                    NzaeDoubleField &sf = (NzaeDoubleField&)input.get(i);
                    temp = (double)sf;
                    break;
                }
                case NzaeDataTypes::NZUDSUDX_NUMERIC32:
                case NzaeDataTypes::NZUDSUDX_NUMERIC64:
                case NzaeDataTypes::NZUDSUDX_NUMERIC128:
                {
                    NzaeNumericField &sf = (NzaeNumericField&)input.get(i);
                    temp = (double)sf;
                    break;
                }
            default:
                ignore = true;
                // ignore
                break;
            }
            if (!ignore) {
                if (op == OP_ADD)
                    res += temp;
                else
                    res *= temp;
            }
        }
        NzaeDoubleField &f = (NzaeDoubleField&)result.get(0);
        f = res;
    }
    bool m_Once;
};

static int run(NzaeFunction *aeFunc)
{
    aeFunc->run(new MyHandler());
    return 0;
}

Kompilierung

Verwenden Sie die Standardkompilierung, wie im lokalen Modus:

$NZ_EXPORT_DIR/ae/utilities/bin/compile_ae --language cpp --template compile \
     --exe applyopcpp --compargs "-g -Wall" --linkargs "-g" applyopcpp.cpp \
     --version 3

Registrierung

Die Registrierung ist etwas anders. Führen Sie zunächst diesen Befehl aus, um sich zu registrieren:
$NZ_EXPORT_DIR/ae/utilities/bin/register_ae --sig "rem_applyop_cpp(VARARGS)" \
     --return "double" --language cpp --template udf --exe applyopcpp \
     --version 3 --remote --rname testcapi
Führen Sie dann Folgendes aus. Sie gibt an, dass der Code als entfernte AE mit dem entfernten Namen testcapi registriert wird, der mit dem Code übereinstimmt. Darüber hinaus registriert es einen Launcher:
$NZ_EXPORT_DIR/ae/utilities/bin/register_ae --sig "rem_applyop_launch(int8)" \
     --return "TABLE(aeresult varchar(255))" --language cpp --template udtf \
     --exe applyopcpp --version 3 --remote --launch --rname testcapi

Mit Ausnahme von --rname, --exe und dem Namensteil von --sig sehen alle Startprogramme wie oben beschrieben aus. In diesem Fall ist es ein UDTF, da dies die Schnittstelle für alle Launcher ist. Der Wert von --rname muss mit dem Namen im Code übereinstimmen.

Aktiv

Um die AE im Remote-Modus auszuführen, wird die ausführbare Datei als "Server" ausgeführt In diesem Fall werden nur die auf dem Host ausgeführten Abfragen bearbeitet. In der Regel werden die Agrarumweltmaßnahmen auch auf den SPUs gestartet. Starten Sie eine Instanz auf dem Host:

SELECT * FROM TABLE WITH FINAL(rem_applyop_launch(0));
AERESULT
-------------------------------------------------------------------------------
tran: 7192 DATA slc: 0 hardware: 0 machine: spubox1 process: 8306 thread: 8306
(1 row)

Beachten Sie, dass eine andere Syntax verwendet wird, um das Startprogramm für die Tabellenfunktion aufzurufen. Dies ist die Syntax für den Aufruf jeder UDTF-basierten AE. Führen Sie nun die AE aus:

SELECT rem_applyop_cpp('+', 4,5,1.1);
REM_APPLYOP_CPP
-----------------
10.1
(1 row)

Schließlich verursachen Sie einen Fehler:

SELECT rem_applyop_cpp(1);
ERROR: first input COLUMN expected TO be a string type