Re: function returning a row

Поиск
Список
Период
Сортировка
От Kjetil Haaland
Тема Re: function returning a row
Дата
Msg-id 200501311642.42625.kjetil.haaland@student.uib.no
обсуждение исходный текст
Ответ на Re: function returning a row  (Michael Fuhr <mike@fuhr.org>)
Ответы Re: function returning a row  (Tom Lane <tgl@sss.pgh.pa.us>)
Список pgsql-novice
On Wednesday 15 December 2004 18:05, Michael Fuhr wrote:
> On Wed, Dec 15, 2004 at 07:16:20AM -0800, Joe Conway wrote:
> See also "Returning Sets from C-Language Functions" in the "C-Language
> Functions" section of the "Extending SQL" chapter in the documentation.

Hi again.

I know it is kind of an old thread, but i have some problems with getting this
function to work. When i run it in the database, the database crashes. The
last thing it prints out before it stops is "return next". I have added my
code here, sorry that there is that much, but i didn't find anything that i
could leave out. I don't know if i need to have the tables in the structure,
since it is allocated with multi_call_memory, but i have tried with and
without it in the structure, and it didn't make any difference. Hope someone
can help.

thanks
- Kjetil

typedef struct {
  bool finished;
  int x_value;
  int y_value;
  int min_value;
  int max_x;
  int max_y;
  int **dynamic;
  int **backtracking;
  bool **before;
}set_data;

Datum smith_waterman_set(PG_FUNCTION_ARGS) {
  FuncCallContext *funcctx;
  MemoryContext oldcontext;
  int call_cntr;

  set_data *set;
  int x_value, y_value, max_x, max_y;
  int min_value;
  int **dynamic;
  int **backtracking;
  bool **before;
  char *in;
  char *sml;
  char g[2]="-";

  if(SRF_IS_FIRSTCALL()) {
    funcctx = SRF_FIRSTCALL_INIT();
    oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);

    set = (set_data *) palloc(sizeof(*set));

    text *intext = PG_GETARG_TEXT_P(0);
    text *smltext = PG_GETARG_TEXT_P(1);
    in = (char*)palloc(VARSIZE(intext)-VARHDRSZ+1);
    sml = (char*)palloc(VARSIZE(smltext)-VARHDRSZ+1);
    snprintf (in, VARSIZE(intext) - VARHDRSZ + 1, VARDATA(intext));
    snprintf (sml, VARSIZE(smltext) - VARHDRSZ + 1, VARDATA(smltext));

    dynamic = (int **) palloc((1+strlen(in))* sizeof(int));
    backtracking = (int **) palloc((1+strlen(in)) *sizeof(int));
    before = (bool **) palloc((1+strlen(in))*sizeof(bool));

    if(dynamic == NULL) {
      printf("\n failed to allocate memory for dynamic");
      ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR),
              errmsg("failed to allocate memory for dynamic")));
    }

    int i, j, diag, up, left, max, s, maxi, maxj;
    int maxvalue = -1;
    for(i=0; i<strlen(in)+1; i++) {
      dynamic[i] = palloc((1+strlen(sml))* sizeof(int));
      backtracking[i] = palloc((1+strlen(sml))*sizeof(int));
      before[i] = palloc((1+strlen(sml))*sizeof(bool));
      if(dynamic[i] == NULL) {
    printf("\nfailed to allocate for dynamic[%d]", i);
    ereport(ERROR,
        (errcode(ERRCODE_SYNTAX_ERROR),
         errmsg("failed to allocate memory for dynamic[%d]", i)));
      }
      if(backtracking[i] == NULL) {
    printf("\nfailed to allocate for backtracking[%d]", i);
    ereport(ERROR,
        (errcode(ERRCODE_SYNTAX_ERROR),
         errmsg("failed to allocate memory for backtracking[%d]", i)));
      }
    }

    //sets up the dynamic programing table,
    //all values are zero since it is local similarity
    for(i=0; i<strlen(in)+1; i++) {
      for(j=0; j<strlen(sml)+1; j++) {
    dynamic[i][j] = 0;
    backtracking[i][j] = 0;
      }
    }

    for(i=0; i<strlen(in); i++) {
      for(j=0; j<strlen(sml); j++) {
    s = score(in+i, sml+j);

    diag = dynamic[i][j] + s;
    up = dynamic[i][j+1] + s - gap;
    left = dynamic[i+1][j] + s - gap;

    max = MAX3(diag, up, left);

    if(max <= 0) {
      dynamic[i+1][j+1] = 0;
      backtracking[i+1][j+1] = 0;
    }
    else if(max == diag) {
      dynamic[i+1][j+1] = diag;
      backtracking[i+1][j+1] = 1;
    }
    else if(max == up) {
      dynamic[i+1][j+1] = up;
      backtracking[i+1][j+1] = 2;
    }
    else if(max == left) {
      dynamic[i+1][j+1] = left;
      backtracking[i+1][j+1] = 3;
    }

    if(dynamic[i+1][j+1] > maxvalue) {
      maxvalue = dynamic[i+1][j+1];
      maxi = i+1;
      maxj = j+1;
    }
      }
    }
    set->finished = false;
    set->x_value = strlen(in);
    set->y_value = strlen(sml);
    set->min_value = PG_GETARG_INT32(2);
    set->max_x = strlen(in);
    set->max_y = strlen(sml);
    set->dynamic = dynamic;
    set->backtracking = backtracking;
    set->before = before;

    funcctx->user_fctx = set;
    MemoryContextSwitchTo(oldcontext);
  }

  //stuff done on every call of the function
  funcctx = SRF_PERCALL_SETUP();

  call_cntr = funcctx->call_cntr;
  set = funcctx->user_fctx;
  x_value = set->x_value;
  y_value = set->y_value;
  min_value = set->min_value;
  max_x = set->max_x;
  max_y = set->max_y;
  dynamic = set->dynamic;
  backtracking = set->backtracking;
  before = set->before;

  if(!(set->finished)) {
    alignres *result;

    char *res1 = (char *) palloc((strlen(in)+strlen(sml))*sizeof(char));
    char *res2 = (char *) palloc((strlen(in)+strlen(sml))*sizeof(char));

    //finds the alignment
    int k=0, i=0, j=0, temp_i=0, temp_j=0;
    int lengde=0;
    bool more = false;
    bool first = true;
    bool found = false;
    for(i=x_value; i>0; i--) {
    elog(NOTICE, "found = %d", found);
    if(!found) {
      for(j=max_y; j>0; j--) {
        if(first) {
          j=y_value;
          first = false;
        }
        elog(NOTICE, "dynamic[%d][%d]=%d", i, j, dynamic[i][j]);
        if(dynamic[i][j] >= min_value && before[i][j] == false) {
          before[i][j] = true;
          elog(NOTICE, "more");
          more = true;
          if(j>0) {
        set->x_value = i;
        set->y_value = j-1;
          }
          else if(i>0){
        set->x_value = i-1;
        set->y_value = max_y;
          }
          else
        set->finished = true;
          found = true;
          temp_i = i;
          temp_j = j;
          break;
       }
     }
      }
     else
    break;
    }
    i = temp_i;
    j = temp_j;

    while(more)
      lengde++;
      if(backtracking[i][j]==1) {
    res1[k]=in[i-1];
    res2[k]=sml[j-1];
    i=i-1;
    j=j-1;
    before[i][j] = true;
      }
      else if(backtracking[i][j]==2) {
    res1[k]=in[i-1];
    res2[k]=g[0];
    i=i-1;
    before[i][j] = true;
      }
      else if(backtracking[i][j]==3) {
    res1[k]=g[0];
    res2[k]=sml[j-1];
    j=j-1;
    before[i][j] = true;
      }
      else {
    more = false;
    lengde--;
      }
      k++;
    }
    if(backtracking[i][j] > 0) {
      if(i != 0)
    res1[k]=in[i-1];
      else
    res1[k]=g[0];
      if(j != 0)
    res2[k]=sml[j-1];
      else
    res2[k]=g[0];
      lengde++;
    }

    smst_in = (char*) palloc(1+lengde*sizeof(char));
    smst_sml = (char*) palloc(1+lengde*sizeof(char));

    i = lengde-1;
    j = 0;

    while (*(smst_in+j) = *(res1+i)) {
      j++;
      i--;
    }
    smst_in[lengde] = '\0';

    i = lengde-1;
    j = 0;

    while (*(smst_sml+j) = *(res2+i)) {
      j++;
      i--;
    }
    smst_sml[lengde] = '\0';
    elog(NOTICE, "smst_in=%s, smst_sml=%s", smst_in, smst_sml);

    result = (alignres *)
palloc(sizeof(*result)+strlen(smst_in)+strlen(smst_sml));
    bool first2 = true;
    set->finished = true;
    for(i=x_value; i>0; i--) {
      for(j=max_y; j>0; j--) {
    if(first2) {
      j=y_value;
      first2 = false;
    }
    if(dynamic[i][j] >= min_value && before[i][j] == false) {
      elog(NOTICE, "verdi = %d, setter finished til false", dynamic[i][j]);
      set->x_value = i;
      set->y_value = j;
      set->finished = false;
      break;
    }
      }
    }
    funcctx->user_fctx = set;
    elog(NOTICE, "return next");
    SRF_RETURN_NEXT(funcctx, PointerGetDatum(result));
  }
  else {
    elog(NOTICE, "return done");
    SRF_RETURN_DONE(funcctx);
  }
}

В списке pgsql-novice по дате отправления:

Предыдущее
От:
Дата:
Сообщение: pgAdminIII and User Grants
Следующее
От: Tom Lane
Дата:
Сообщение: Re: function returning a row