Thread: backend dies on my aggregate function in 7.1.2

backend dies on my aggregate function in 7.1.2

From
Dirk Lutzebaeck
Date:
Hi,

I am trying to write an aggregate function (maxalphanum_check) for
7.1.2 but I just get abnormal termination of the backend. It uses a
function maxalphanum_gt which works quite well alone. What am I doing
wrong?

*** this is the aggregate function:

#include <postgres.h>

text * maxalphanum_check(text *internal, text *next) {
  text *new, *new_t;

  if (maxalphanum_gt(next, internal)) {
    new = next;
  } else {
    new = internal;
  }

  /* it seems that we must allocate the value we return */

  new_t = (text *) palloc(VARSIZE(new));
  memset(new_t, 0, VARSIZE(new));
  VARATT_SIZEP(new_t) = VARSIZE(new);
  memcpy((void *) VARDATA(new_t),
         (void *) VARDATA(new),
         VARSIZE(new)-VARHDRSZ);

  return(new_t);
}

*** compiled by


        gcc -O -fPIC -I../../postgresql-7.1.2/src/include -c maxalphanum.c
        gcc -shared -o maxalphanum.so maxalphanum.o


*** the aggregate is then created by

CREATE AGGREGATE maxalphanum (
   SFUNC1 = maxalphanum_check,
   BASETYPE = TEXT,
   STYPE1 = TEXT
);


*** the query which breaks the backend is then eg:

SELECT maxalphanum(x) FROM t GROUP BY x;
pqReadData() -- backend closed the channel unexpectedly.
        This probably means the backend terminated abnormally
        before or while processing the request.
The connection to the server was lost. Attempting reset: Failed.

*** This is the function maxalphanum_gt which works quite well in
selects:

/*
   a state transition function for the maxalphanum aggregate
*/

#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <postgres.h>

#define MAXLEN 256

int maxalphanum_gt(text *str_a, text *str_b) {
  char *a_data = (char *) VARDATA(str_a);
  char *b_data = (char *) VARDATA(str_b);

  char a_str[MAXLEN];
  char b_str[MAXLEN];

  int a_len = VARSIZE(str_a) - VARHDRSZ;
  int b_len = VARSIZE(str_b) - VARHDRSZ;

  char a = a_data[0];
  char b = b_data[0];

  if (a_len == 0 && b_len > 0) {
    return 0;
  }

  if (a_len > 0 && b_len == 0) {
    return 1;
  }

  if (a_len >= MAXLEN || b_len >= MAXLEN) {
    return 0;
  }

  memcpy(a_str, a_data, a_len);
  a_str[a_len] = '\0';

  memcpy(b_str, b_data, b_len);
  b_str[b_len] = '\0';

  if (isdigit(a) && isdigit(b)) {
    return atoi(a_str) > atoi(b_str);
  }

  if (isdigit(a) && isalpha(b)) {
    return 1;
  }

  if (isalpha(a) && isdigit(b)) {
    return 0;
  }

  if (isalpha(a) && isalpha(b)) {
    return strcasecmp(a_str, b_str) > 0;
  }

  return a > b;
}



Dirk

Re: backend dies on my aggregate function in 7.1.2

From
Tom Lane
Date:
Dirk Lutzebaeck <lutzeb@aeccom.com> writes:
> *** the aggregate is then created by

> CREATE AGGREGATE maxalphanum (
>    SFUNC1 = maxalphanum_check,
>    BASETYPE = TEXT,
>    STYPE1 = TEXT
> );

You've not specified any initial condition for the aggregate's state
value.  This means the state starts out NULL ... and your transition
function isn't handling that.

You probably want to mark the transition function 'strict', but you
also need to consider what the initial condition should be: what do
you want returned for no input rows?

            regards, tom lane