C++-Datei für UDTF erstellen

Verwenden Sie zunächst einen Texteditor Ihrer Wahl zum Erstellen der C++-Datei. Der Dateiname muss über die Erweiterung .cpp verfügen. Sie können beispielsweise das Verzeichnis /home/nz/udx_files als Bereich für die UDX-Codedateien erstellen.

Ihre C++-Datei muss die Header-Datei ' udxinc.h enthalten, die die erforderlichen Deklarationen für benutzerdefinierte Tabellenfunktionen und die Verarbeitung auf den SPUs enthält.

#include "udxinc.h"
Vergewissern Sie sich außerdem, dass alle standardmäßigen Headerdateien für die C++-Bibliotheken deklariert wurden, die für Ihre Tabellenfunktion möglicherweise erforderlich sind. Wenn für Ihre UDTF (User-Defined Table Function; benutzerdefinierte Tabellenfunktion) benutzerdefinierte gemeinsam genutzte Bibliotheken benötigt werden, dann notieren Sie die Bibliotheksnamen, da Sie sie zu einem späteren Zeitpunkt zur Registrierung der UDTF in der Datenbank benötigen. Beispiel:
#include "udxinc.h"
#include <string.h>

Benutzerdefinierte gemeinsam genutzte Bibliotheken müssen in der Datenbank bereits vorhanden sein, um die UDTF registrieren und diese Bibliotheken als Abhängigkeiten angeben zu können. Sie können die UDTF registrieren, ohne Bibliotheksabhängigkeiten anzugeben. Nach dem Hinzufügen der Bibliotheken können Sie den Befehl ALTER FUNCTION verwenden, um die UDTF-Definition mit den korrekten Abhängigkeiten zu aktualisieren. Weitere Informationen zu benutzerdefinierten gemeinsamen Bibliotheken finden Sie unter Erstellen einer benutzerdefinierten gemeinsamen Bibliothek.

Die UDX-Klassen und -Funktionen für die API-Version 2 werden in einem Namensbereich mit dem Namen nz::udx_ver2 definiert. Ihr C++-Programm muss auf den korrekten Namensbereich verweisen. Beispiel:
#include "udxinc.h"

using namespace nz::udx_ver2;
Zum Implementieren einer UDTF erstellen Sie ein Klassenobjekt, das von der Basisklasse 'Udtf' abgeleitet wird. Beispiel:
#include "udxinc.h"

using namespace nz::udx_ver2;

class parseNames : public Udtf {
public:
}
Die UDTF parseNames verwendet eine Eingabetabelle mit Zeichenfolgefeldern, die durch Leerzeichen oder Kommas voneinander getrennt sind, und gibt eine Tabelle zurück, in der jedes Feld der angeforderten Zeichenfolge in einer eigenen Zeile ausgegeben wird. Wie bei anderen UDXs definieren Sie die Variablen, die für den UDTF-Algorithmus auf Klassenebene erforderlich sind. Beispiel:
#include "udxinc.h"
using namespace nz::udx_ver2;

class parseNames : public Udtf {

private:
    char value[1000];
    int valuelen;
    int i;
public:
}
Die UDTF parseNames verwendet die folgenden Variablen:
  • Die Variable value enthält eine Kopie des Eingabeparameters.
  • Die Variable valuelen enthält die Länge der Eingabezeichenfolge.
  • Die Variable i steht für einen Zähler.
Jede UDTF muss die Methode instantiate() sowie die Konstruktormethode und zwei weitere UDTF-spezifische Methoden mit dem Namen newInputRow() und nextOutputRow() implementieren. Die UDTF-spezifische Methode nextEoiOutputRow() ist optional. Im Folgenden wird ein Beispiel für die Methoden und ihre Einsatzmöglichkeiten aufgeführt.
  • Wie bei UDFs rufen Sie die ' instantiate() -Methode auf, um das UDTF-Objekt dynamisch zu erzeugen. In UDX Version 2 nimmt die ' instantiate -Methode ein ArgumentUdxInit *pInit), das den Zugriff auf die Speicherspezifikation, die Log-Einstellung und die UDX-Umgebung ermöglicht (siehe UDX-Umgebung). Der Konstruktor muss außerdem ein UdxInit-Objekt verwenden und es an den Basisklassenkonstruktor übergeben. Beispiel:
       #include "udxinc.h"
    using namespace nz::udx_ver2;
    
    class parseNames : public Udtf {
    private:
        char value[1000];
        int valuelen;
        int i;
    public:
        parseNames(UdxInit *pInit) : Udtf(pInit) {}
    
        static Udtf* instantiate(UdxInit*);
    };
    
    Udtf* parseNames::instantiate (UdxInit* pInit) {   
        return new parseNames(pInit); 
    }
  • Für eine UDTF verwenden Sie die Methode newInputRow(), um Initialisierungsaktionen wie beispielsweise das Kopieren von Eingabeargumenten, das Initialisieren von Klassenvariablen sowie das Verwalten von Situationen wie z. B. Nulleingabevariablen auszuführen. Die Methode wird einmal für jede Eingabezeile aufgerufen. Im Beispiel für die UDTF parseNames wird mit dem folgenden Beispielcode die Eingabeliste in den Variablenwert kopiert, für valuelen die Länge der Eingabezeichenfolge angegeben und die Variable i mit Null initialisiert:
        virtual void newInputRow() {
            StringArg *valuesa = stringArg(0);
            bool valuesaNull  = isArgNull(0);
            if (valuesaNull)
                valuelen = 0;
            else {
                if (valuesa->length >= 1000)
                  throwUdxException("Input value must be less than 1000 
    characters.");
                memcpy(value, valuesa->data, valuesa->length);
                value[valuesa->length] = 0;
                valuelen = valuesa->length;
            }
            i = 0;
        }
  • Mit der Methode nextOutputRow() können Sie die nächste Ausgabezeile der Tabelle erstellen und zurückgeben. Des Weiteren müssen Sie ermitteln, ob weitere Daten vorhanden sind, die zurückgegeben werden müssen, und dann 'Done' (Fertig) zurückgeben. Netezza Performance Server ruft diese Methode mindestens einmal pro Eingabezeile auf. Im Folgenden ist ein Beispielcode dargestellt:
           virtual DataAvailable nextOutputRow() {
            if (i >= valuelen)
                   return Done;
            // save starting position of name
            int start = i;
            // scan string for next comma
            while ((i < valuelen) && value[i] != ',')
                i++;
            // return word
            StringReturn *rk = stringReturnColumn(0);
            if (rk->size < i-start)
              throwUdxException("Value exceeds return size");
            memcpy(rk->data, value+start, i-start);
            rk->size = i-start;
            i++;
            return MoreData;
        }

    Wie im Beispiel dargestellt, erstellen Sie unter Verwendung des geeigneten Spaltenrückgabetyps (z. B. stringReturnColumn() oder intReturnColumn()) eine Spalte und geben deren Position (z. B. 1, 2, 3 usw.) an. Das Syntaxelement für die Rückgabe weiterer Daten ('return MoreData') gibt an, dass eine weitere Zeile zur Verarbeitung ansteht. Wenn die Zählvariable i das Ende der Eingabezeichenfolge erreicht, stehen keine weiteren Daten mehr zur Verarbeitung an, sodass nextOutputRow() die Meldung 'Done' (Fertig) zurückgibt.

  • Wenn Ihre UDTF die Syntax TABLE WITH FINAL unterstützt, dann verwenden Sie die Methode nextEoiOutputRow() mindestens einmal nach dem Ende der Eingabe, um alle Daten zu verarbeiten und auszugeben. Die Basisklasse verfügt über eine Standardimplementierung dieser Methode, die bei Aufruf keine Zeilen zurückgibt. Sie weist Ähnlichkeiten mit nextOutputRow() auf. Eine Ausnahme bildet hierbei lediglich die Tatsache, dass newInputRow() nicht vor ihr aufgerufen wird. Im Folgenden ist eine Beispielmethode dargestellt:
           virtual DataAvailable nextEoiOutputRow()
            return Done;
        }