Fonction scalaire en langage C
L'exemple suivant montre une fonction scalaire simple qui additionne un ensemble de nombres. Cet exemple commence par la construction d'un AE simple. Il utilise le nom de fichier suivant : " func.c
Coder
- Tirer sur l'interface C. Ceci peut être réalisé en utilisant :
#include "nzaeapis.h" - Écrire un texte principal. Déterminer l'API à utiliser, dans ce cas une fonction. Sélectionnez une connexion AE locale ou une connexion AE distante. Cet exemple utilise une connexion AE locale :
#include <stdio.h> #include <stdlib.h> #include "nzaeapis.h" int main(int argc, char * argv[]) { if (nzaeIsLocal()) { NzaeInitialization arg; memset(&arg, 0, sizeof(arg)); arg.ldkVersion = NZAE_LDK_VERSION; if (nzaeInitialize(&arg)) { fprintf(stderr, "initialization failed\n"); return -1; } nzaeClose(arg.handle); } else { fprintf(stderr, "Expecting Local AE\n"); return -1; } return 0; }Cela permet de définir le "
nzae, qui permet de travailler avec les fonctions AE. - Ajouter un stub pour appeler la logique de la fonction :
#include <stdio.h> #include <stdlib.h> #include "nzaeapis.h" static int run(NZAE_HANDLE h); int main(int argc, char * argv[]) { if (nzaeIsLocal()) { NzaeInitialization arg; memset(&arg, 0, sizeof(arg)); arg.ldkVersion = NZAE_LDK_VERSION; if (nzaeInitialize(&arg)) { fprintf(stderr, "initialization failed\n"); return -1; } run(arg.handle); nzaeClose(arg.handle); } else { fprintf(stderr, "Expecting Local AE\n"); return -1; } return 0; } static int run(NZAE_HANDLE h) { return 0; } - Mettre en œuvre la logique complète :
#include <stdio.h> #include <stdlib.h> #include "nzaeapis.h" static int run(NZAE_HANDLE h); int main(int argc, char * argv[]) { if (nzaeIsLocal()) { NzaeInitialization arg; memset(&arg, 0, sizeof(arg)); arg.ldkVersion = NZAE_LDK_VERSION; if (nzaeInitialize(&arg)) { fprintf(stderr, "initialization failed\n"); return -1; } run(arg.handle); nzaeClose(arg.handle); } else { fprintf(stderr, "Expecting Local AE\n"); return -1; } return 0; } static int run(NZAE_HANDLE h) { NzaeMetadata metadata; if (nzaeGetMetadata(h, &metadata)) { fprintf(stderr, "get metadata failed\n"); return -1; } #define CHECK(value) \ { \ NzaeRcCode rc = value; \ if (rc) \ { \ const char * format = "%s in %s at %d"; \ fprintf(stderr, format, \ nzaeGetLastErrorText(h), __FILE__, __LINE__); \ nzaeUserError(h, format, \ nzaeGetLastErrorText(h), __FILE__, __LINE__); \ exit(-1); \ } \ } if (metadata.outputColumnCount != 1 || metadata.outputTypes[0] != NZUDSUDX_DOUBLE) { nzaeUserError(h, "expecting one output column of type double"); return -1; } if (metadata.inputColumnCount < 1) { nzaeUserError(h, "expecting at least one input column"); return -1; } if (metadata.inputTypes[0] != NZUDSUDX_FIXED && metadata.inputTypes[0] != NZUDSUDX_VARIABLE) { nzaeUserError(h, "first input column expected to be a string type"); return -1; } for (;;) { int i; double result = 0; NzaeRcCode rc = nzaeGetNext(h); if (rc == NZAE_RC_END) { break; } NzudsData * input = NULL; CHECK(nzaeGetInputColumn(h, 0, &input)); const char * opString; if (input->isNull) { nzaeUserError(h, "first input column may not be null"); return -1; } if (input->type == NZUDSUDX_FIXED) { opString = input->data.pFixedString; } else if (input->type == NZUDSUDX_VARIABLE) { opString = input->data.pVariableString; } else { nzaeUserError(h, "first input column expected to be a string type"); return -1; } enum OperatorEnum { OP_ADD = 1, OP_MULT = 2 } op; if (strcmp(opString, "+") == 0) { op = OP_ADD; } else if (strcmp(opString, "*") == 0) { op = OP_MULT; result = 1; } else { nzaeUserError(h, "unexpected operator %s", opString); return -1; } for (i = 1; i < metadata.inputColumnCount; i++) { CHECK(nzaeGetInputColumn(h, i, &input)); if (input->isNull) { continue; } switch (op) { case OP_ADD: switch(input->type) { case NZUDSUDX_INT8: result += *input->data.pInt8; break; case NZUDSUDX_INT16: result += *input->data.pInt16; break; case NZUDSUDX_INT32: result += *input->data.pInt32; break; case NZUDSUDX_INT64: result += *input->data.pInt64; break; case NZUDSUDX_FLOAT: result += *input->data.pFloat; break; case NZUDSUDX_DOUBLE: result += *input->data.pDouble; break; case NZUDSUDX_NUMERIC32: case NZUDSUDX_NUMERIC64: case NZUDSUDX_NUMERIC128: // unlike Java, C has no native numeric data types break; default: // ignore nonnumeric type break; } break; case OP_MULT: switch(input->type) { case NZUDSUDX_INT8: result *= *input->data.pInt8; break; case NZUDSUDX_INT16: result *= *input->data.pInt16; break; case NZUDSUDX_INT32: result *= *input->data.pInt32; break; case NZUDSUDX_INT64: result *= *input->data.pInt64; break; case NZUDSUDX_FLOAT: result *= *input->data.pFloat; break; case NZUDSUDX_DOUBLE: result *= *input->data.pDouble; break; case NZUDSUDX_NUMERIC32: case NZUDSUDX_NUMERIC64: case NZUDSUDX_NUMERIC128: // unlike Java, C has no native numeric data types break; default: // ignore non-numeric type break; } break; default: nzaeUserError(h, "internal error, unexpected operator"); return -1; } } CHECK(nzaeSetOutputDouble(h, 0, result)); CHECK(nzaeOutputResult(h)); } nzaeDone(h); return 0; }Lorsque le code est complet, il doit être compilé et enregistré.
Compilation
$NZ_EXPORT_DIR/ae/utilities/bin/compile_ae --language system --version 3 \
--template compile func.c --exe applyLes arguments spécifient le langage système C-utilisant la version 3 avec le modèle compile. En outre, ils précisent que le processus doit produire une application exécutable.
Enregistrement
$NZ_EXPORT_DIR/ae/utilities/bin/register_ae --language system --version 3 \
--template udf --exe apply --sig "applyop_c(VARARGS)" --return "double"En cours d'exécution
SELECT applyop_c('+',1,2);
APPLYOP_C
-----------
3
(1 row)
nzaeUserError s'il est incorrect. L'exemple suivant déclenche une erreur :SELECT applyop_c('-',1,2);
ERROR: unexpected operator -