PackChildren aggregate (UDX version 1)

/*
Copyright (c) 2007-2009 Netezza Corporation, an IBM Company
All rights reserved.

The aggregate PackChildren allows us to "pack" multiple children of one
node into a varchar (binary representation)

REGISTRATION:

create or replace aggregate PackChildren (INT4) returns VARCHAR(400)
state (VARCHAR(400))
language cpp parameter style npsgeneric
EXTERNAL CLASS NAME 'CPackChildren'
EXTERNAL HOST OBJECT '/home/nz/osf/packchildren.o_x86'
EXTERNAL SPU OBJECT '/home/nz/osf/packchildren.o_spu10';

Usage:
create table packtest (a int4);
insert into packtest values (1);
insert into packtest values (2);
insert into packtest values (3);

select PackChildren(a) from packtest;
*/

#include "udxinc.h"
#include <string.h>

using namespace nz::udx;

#define MAXCHILDREN 4000

class CPackChildren : public Uda
{
public:
  static Uda* instantiate();
  void initializeState()
  {
    StringArg *s = stringState(0);
    s->length = 0;
    setStateNull(0, false);
  }
  virtual void accumulate()
  {
    StringArg *s = stringState(0);
    int32 value = int32Arg(0);
    if (s->length < MAXCHILDREN * 4)
    {
      *((int32*)(s->data+s->length)) = value;
      s->length = s->length + 4;
    }
  }
  virtual void merge()
  {
   /* Destination */
   StringArg *s = stringState(0);
   /* Source */
   StringArg *s2 = stringArg(0);
   if (s->length + s2->length <= MAXCHILDREN * 4)
    {
       memcpy(s->data+s->length, s2->data, s2->length);
       s->length = s->length + s2->length;
    }
  }
  virtual ReturnValue finalResult()
  {
    setReturnNull(false);
    StringReturn *ret = stringReturnInfo();
    StringArg *s = stringArg(0);
    printf("got %d\n", s->length);
    ret->size = s->length;
    memcpy(ret->data,s->data,s->length);
    NZ_UDX_RETURN_STRING(ret);
  }
};
Uda* CPackChildren::instantiate()
{
  return new CPackChildren;
}