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
$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
$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