Creare il file C++ per l'UDA
Per iniziare, utilizzare un qualsiasi editor di testo per creare il file C++. Il file C++ deve includere il file di intestazione 'udxinc.h, che contiene le dichiarazioni necessarie per gli aggregati definiti dall'utente e l'elaborazione sulle SPU.
#include "udxinc.h"
Inoltre, assicurarsi di dichiarare tutti i file header della libreria standard C++ che l'aggregato potrebbe richiedere. Se la vostra UDA richiede librerie condivise definite dall'utente, assicuratevi di annotare il nome delle librerie necessarie quando registrate l'UDA nel database.
Le librerie condivise definite dall'utente devono esistere nel database prima di poter registrare l'UDA e specificare tali librerie come dipendenze. È possibile registrare l'UDA senza specificare le dipendenze delle librerie e, dopo l'aggiunta delle librerie, utilizzare il comando ALTER AGGREGATE per aggiornare la definizione dell'UDA con le dipendenze corrette. Per ulteriori informazioni sulle librerie condivise definite dall'utente, vedere Creare una libreria condivisa definita dall'utente.
nz::udx_ver2
. (Gli UDX della versione 1 dell'API utilizzano lo spazio dei nomi " nz::udx
) Il programma C++ deve fare riferimento allo spazio dei nomi corretto. Ad esempio:#include "udxinc.h"
using namespace nz::udx_ver2;
Questa sezione utilizza 'udx_ver2
come spazio dei nomi predefinito per gli esempi che seguono. Le sezioni segnalano le differenze con la versione 1 di UDX, mentre il riferimento alle funzioni e agli aggregati definiti dall'utente contiene esempi di definizioni della versione 1 e della versione 2. È possibile continuare a creare UDA UDX versione 1 e nuove UDA versione 2; entrambe le versioni funzionano su sistemi con release 6.0.x o successive. Tuttavia, le UDA della versione 1 funzionano sui sistemi Netezza Performance Server release 5.0.x e successive e quindi potrebbero essere più portabili per i vostri sistemi Netezza Performance Server.
#include "udxinc.h"
using namespace nz::udx_ver2;
class CPenMax: public nz::udx_ver2::Uda
{
public:
};
class CPenMax : public nz::udx_ver2::Uda
{
public:
static nz::udx_ver2::Uda* instantiate(UdxInit *pInit)
virtual void initializeState();
virtual void accumulate();
virtual void merge();
virtual ReturnValue finalResult();
};
nz::udx_ver2::Uda* CPenMax::instantiate(UdxInit *pInit)
{
return new CPenMax(pInit);
}
- Il metodo 'instantiate() viene richiamato dal motore di runtime per creare l'oggetto dinamicamente. L'implementazione statica deve essere esterna alla definizione della classe. Nella versione 2 di UDX, il metodo instantiate accetta un argomentoUdxInit *pInit), che consente di accedere alle specifiche di memoria, all'impostazione del registro e all'ambiente UDX nel costruttore (vedere Ambiente UDX). Crea un oggetto del tipo di classe derivata usando l'operatore new e lo restituisce (come tipo di classe base Uda) al motore di runtime. Il motore di runtime cancella l'oggetto quando non è più necessario. Segue un esempio:
class CPenMax : public nz::udx_ver2::Uda { public: CPenMax(UdxInit *pInit) : Uda(pInit) { } static nz::udx_ver2::Uda* instantiate(UdxInit *pInit); virtual void initializeState(); virtual void accumulate(); virtual void merge(); virtual ReturnValue finalResult(); }; nz::udx_ver2::Uda* CPenMax::instantiate(UdxInit *pInit) { return new CPenMax(pInit); }
- Il metodo 'initializeState() viene chiamato per consentire all'implementatore di inizializzare lo stato necessario che viene utilizzato nell'UDA. Lo stato di una UDA è costituito da uno o più valori che devono essere tipi di dati validi Netezza Performance Server. Lo stato viene conservato automaticamente dal motore di runtime tra gli snippet, se necessario. Per calcolare il penultimo massimo, la funzione deve tenere traccia dei due numeri più grandi nelle variabili di stato. Il metodo 'initializeState() imposta entrambe le variabili su NULL. Gli stati vengono dichiarati nel comando CREATE AGGREGATE, descritto più avanti. Segue un esempio:
void CPenMax::initializeState() { setStateNull(0, true); // set current max to null setStateNull(1, true); // set current penmax to null }
- Il metodo 'accumulate() viene chiamato una volta per riga e aggiunge il contributo dei suoi argomenti allo stato dell'accumulatore. Aggiorna gli stati per mantenere i due valori più alti negli stati corretti. Oltre a ottenere gli argomenti tramite '
int curVal = int32Arg(0);
, il metodo recupera le due variabili di stato utilizzando le funzioni 'int32State(int) e 'isStateNull(int). Il metodo di accumulazione aggiorna gli stati come richiesto.void CPenMax::accumulate() { int *pCurMax = int32State(0); bool curMaxNull = isStateNull(0); int *pCurPenMax = int32State(1); bool curPenMaxNull = isStateNull(1); int curVal = int32Arg(0); bool curValNull = isArgNull(0); if ( !curValNull ) { // do nothing if argument is null - can't //affect max or penmax if ( curMaxNull ) { // if current max is null, this arg //becomes current max setStateNull(0, false); // current max no longer null *pCurMax = curVal; } else { if ( curVal > *pCurMax ) { // if arg is new max setStateNull(1, false); // then prior current max // becomes current penmax *pCurPenMax = *pCurMax; *pCurMax = curVal; // and current max gets arg } else if ( curPenMaxNull || curVal > *pCurPenMax ){ // arg might be greater than current penmax setStateNull(1, false); // it is *pCurPenMax = curVal; } } } }
- Il metodo 'merge() viene chiamato con gli argomenti di un secondo insieme di variabili di stato e fonde questo secondo stato nelle proprie variabili di stato. Questo metodo è necessario perché il sistema Netezza Performance Server è un'architettura di elaborazione parallela e gli stati aggregati di tutte le SPU vengono inviati all'host, dove vengono consolidati in un unico stato di aggregazione. Il metodo 'merge() unisce due stati, gestendo correttamente tutti gli stati con valori nulli. Uno degli stati viene passato normalmente come in 'accumulate(). Il secondo stato viene passato come argomento e richiede l'uso di funzioni di recupero degli argomenti, come 'int32Arg(int) e 'isArgNull(int). Segue un esempio:
void CPenMax::merge() { int *pCurMax = int32State(0); bool curMaxNull = isStateNull(0); int *pCurPenMax = int32State(1); bool curPenMaxNull = isStateNull(1); int nextMax = int32Arg(0); bool nextMaxNull = isArgNull(0); int nextPenMax = int32Arg(1); bool nextPenMaxNull = isArgNull(1); if ( !nextMaxNull ) { // if next max is null, then so is //next penmax and we do nothing if ( curMaxNull ) { setStateNull(0, false); // current max was null, // so save next max *pCurMax = nextMax; } else { if ( nextMax > *pCurMax ) { setStateNull(1, false); // next max is greater than current, so save next *pCurPenMax = *pCurMax; // and make current penmax prior current max *pCurMax = nextMax; } else if ( curPenMaxNull || nextMax > *pCurPenMax ) { // next max may be greater than current penmax setStateNull(1, false); // it is *pCurPenMax = nextMax; } } if ( !nextPenMaxNull ) { if ( isStateNull(1) ) { // can't rely on curPenMaxNull here, might have // change state var null flag above setStateNull(1, false); // first non-null penmax, // save it *pCurPenMax = nextPenMax; } else { if ( nextPenMax > *pCurPenMax ) { *pCurPenMax = nextPenMax; // next penmax greater than current, save it } } } } }
- Il metodo " finalResult() restituisce il valore di aggregazione finale dello stato accumulato. Un esempio potrebbe essere un'implementazione UDA di un'aggregazione media, in cui il metodo 'finalResult() divide la somma per il conteggio per produrre una media. In questo esempio, il metodo 'finalResult() raccoglie uno degli stati e lo restituisce utilizzando la macro NZ_UDX_RETURN_INT32 in modo simile a 'evaluate() nel caso delle UDF.
ReturnValue CPenMax::finalResult() { int curPenMax = int32Arg(1); bool curPenMaxNull = isArgNull(1); if ( curPenMaxNull ) NZ_UDX_RETURN_NULL(); setReturnNull(false); NZ_UDX_RETURN_INT32(curPenMax); }
La macro NZ_UDX_RETURN_INT32 aiuta a confermare che il valore di ritorno è del tipo previsto. Per un elenco delle macro di ritorno disponibili, vedere Macro valore di ritorno UDX. Il metodo 'finalResult() può accedere a tutte le chiamate API di aiuto ai tipi di dati e accedere a un elenco di argomenti di stato elencati in Argomenti di stato UDA.