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

  1. Tirer sur l'interface C. Ceci peut être réalisé en utilisant :
    #include "nzaeapis.h"
  2. É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.

  3. 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;
    }
  4. 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

Compilez le code comme suit :
$NZ_EXPORT_DIR/ae/utilities/bin/compile_ae --language system --version 3 \
--template compile func.c --exe apply

Les 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

Une fois compilé, enregistrez le code comme suit :
$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

Vous pouvez maintenant exécuter l'AE dans SQL :
SELECT applyop_c('+',1,2);
APPLYOP_C
-----------
3
(1 row)
Notez que dans le code, vous validez l'opérateur et utilisez " nzaeUserError s'il est incorrect. L'exemple suivant déclenche une erreur :
SELECT applyop_c('-',1,2);
ERROR: unexpected operator -