Exemplo n.º 1
0
void *ARRAY::GetSortIndex(PGLOBAL g)
  {
  // Prepare non conservative sort with offet values
  Index.Size = Nval * sizeof(int);

  if (!PlgDBalloc(g, NULL, Index))
    goto error;

  Offset.Size = (Nval + 1) * sizeof(int);

  if (!PlgDBalloc(g, NULL, Offset))
    goto error;

  // Call the sort program, it returns the number of distinct values
  Ndif = Qsort(g, Nval);

  if (Ndif < 0)
    goto error;

  if (Ndif < Nval)
    goto error;

  PlgDBfree(Offset);
  return Index.Memp;

 error:
  Nval = Ndif = 0;
  Valblk->Free();
  PlgDBfree(Index);
  PlgDBfree(Offset);
  return NULL;
  } // end of GetSortIndex
Exemplo n.º 2
0
bool VALBLK::AllocBuff(PGLOBAL g, size_t size)
  {
  Mblk.Size = size;

  if (!(Blkp = PlgDBalloc(g, NULL, Mblk))) {
    sprintf(g->Message, MSG(MEM_ALLOC_ERR), "Blkp", (int) Mblk.Size);
    fprintf(stderr, "%s\n", g->Message);
    return true;
    } // endif Blkp

  return false;
  } // end of AllocBuff
Exemplo n.º 3
0
PQRYRES PIVAID::MakePivotColumns(PGLOBAL g)
  {
  char    *p, *query, *colname, *skc, buf[64];
  int      rc, ndif, nblin, w = 0;
  bool     b = false;
  PVAL     valp;   
  PQRYRES  qrp;
  PCOLRES *pcrp, crp, fncrp = NULL;

  // Save stack and allocation environment and prepare error return
  if (g->jump_level == MAX_JUMP) {
    strcpy(g->Message, MSG(TOO_MANY_JUMPS));
    return NULL;
    } // endif jump_level

  if ((rc= setjmp(g->jumper[++g->jump_level])) != 0) {
    goto err;
    } // endif rc

  // Are there columns to skip?
  if (Skcol) {
    uint n = strlen(Skcol);

    skc = (char*)PlugSubAlloc(g, NULL, n + 2);
    strcpy(skc, Skcol);
    skc[n + 1] = 0;

    // Replace ; by nulls in skc
    for (p = strchr(skc, ';'); p; p = strchr(p, ';'))
      *p++ = 0;

  } else
    skc = NULL;

  if (!Tabsrc && Tabname) {
    // Locate the  query
    query = (char*)PlugSubAlloc(g, NULL, strlen(Tabname) + 26);
    sprintf(query, "SELECT * FROM `%s` LIMIT 1", Tabname);
  } else if (!Tabsrc) {
    strcpy(g->Message, MSG(SRC_TABLE_UNDEF));
    return NULL;
  } else
    query = Tabsrc;

  // Open a MySQL connection for this table
  if (Myc.Open(g, Host, Database, User, Pwd, Port))
    return NULL;
  else
    b = true;

  // Send the source command to MySQL
  if (Myc.ExecSQL(g, query, &w) == RC_FX)
    goto err;

  // We must have a storage query to get pivot column values
  if (!(Qryp = Myc.GetResult(g, true)))
    goto err;

  if (!Fncol) {
    for (crp = Qryp->Colresp; crp; crp = crp->Next)
      if ((!Picol || stricmp(Picol, crp->Name)) && !SkipColumn(crp, skc))
        Fncol = crp->Name;
  
    if (!Fncol) {
      strcpy(g->Message, MSG(NO_DEF_FNCCOL));
      goto err;
      } // endif Fncol
  
    } // endif Fncol
  
  if (!Picol) {
    // Find default Picol as the last one not equal to Fncol
    for (crp = Qryp->Colresp; crp; crp = crp->Next)
      if (stricmp(Fncol, crp->Name) && !SkipColumn(crp, skc))
        Picol = crp->Name;
  
    if (!Picol) {
      strcpy(g->Message, MSG(NO_DEF_PIVOTCOL));
      goto err;
      } // endif Picol
  
    } // endif picol
  
  // Prepare the column list
  for (pcrp = &Qryp->Colresp; crp = *pcrp; )
    if (SkipColumn(crp, skc)) {
      // Ignore this column
      *pcrp = crp->Next;
    } else if (!stricmp(Picol, crp->Name)) {
      if (crp->Nulls) {
        sprintf(g->Message, "Pivot column %s cannot be nullable", Picol);
        goto err;
        } // endif Nulls

      Rblkp = crp->Kdata;
      *pcrp = crp->Next;
    } else if (!stricmp(Fncol, crp->Name)) {
      fncrp = crp;
      *pcrp = crp->Next;
    } else
      pcrp = &crp->Next;

  if (!Rblkp) {
    strcpy(g->Message, MSG(NO_DEF_PIVOTCOL));
    goto err;
  } else if (!fncrp) {
    strcpy(g->Message, MSG(NO_DEF_FNCCOL));
    goto err;
  } // endif

  if (Tabsrc) {
    Myc.Close();
    b = false;

    // Before calling sort, initialize all
    nblin = Qryp->Nblin;

    Index.Size = nblin * sizeof(int);
    Index.Sub = TRUE;                  // Should be small enough

    if (!PlgDBalloc(g, NULL, Index))
      return NULL;

    Offset.Size = (nblin + 1) * sizeof(int);
    Offset.Sub = TRUE;                 // Should be small enough

    if (!PlgDBalloc(g, NULL, Offset))
      return NULL;

    ndif = Qsort(g, nblin);

    if (ndif < 0)           // error
      return NULL;

  } else {
    // The query was limited, we must get pivot column values
    query = (char*)PlugSubAlloc(g, NULL, 0);
    sprintf(query, "SELECT DISTINCT `%s` FROM `%s`", Picol, Tabname);
    PlugSubAlloc(g, NULL, strlen(query) + 1);
    Myc.FreeResult();

    // Send the source command to MySQL
    if (Myc.ExecSQL(g, query, &w) == RC_FX)
      goto err;

    // We must have a storage query to get pivot column values
    if (!(qrp = Myc.GetResult(g, true)))
      goto err;

    Myc.Close();
    b = false;

    // Get the column list
    crp = qrp->Colresp;
    Rblkp = crp->Kdata;
    ndif = qrp->Nblin;
  } // endif Tabsrc

  // Allocate the Value used to retieve column names
  if (!(valp = AllocateValue(g, Rblkp->GetType(),
                                Rblkp->GetVlen(),
                                Rblkp->GetPrec())))
    return NULL;

  // Now make the functional columns
  for (int i = 0; i < ndif; i++) {
    if (i) {
      crp = (PCOLRES)PlugSubAlloc(g, NULL, sizeof(COLRES));
      memcpy(crp, fncrp, sizeof(COLRES));
    } else
      crp = fncrp;

    // Get the value that will be the generated column name
    if (Tabsrc)
      valp->SetValue_pvblk(Rblkp, Pex[Pof[i]]);
    else
      valp->SetValue_pvblk(Rblkp, i);

    colname = valp->GetCharString(buf);
    crp->Name = (char*)PlugSubAlloc(g, NULL, strlen(colname) + 1);
    strcpy(crp->Name, colname);
    crp->Flag = 1;

    // Add this column
    *pcrp = crp;
    crp->Next = NULL;
    pcrp = &crp->Next;
    } // endfor i

  // We added ndif columns and removed 2 (picol and fncol)
  Qryp->Nbcol += (ndif - 2);
  return Qryp;

err:
  if (b)
    Myc.Close();

  return NULL;
  } // end of MakePivotColumns
Exemplo n.º 4
0
bool ARRAY::Sort(PGLOBAL g)
  {
  int   i, j, k;

  // This is to avoid multiply allocating for correlated subqueries
  if (Nval > Xsize) {
    if (Xsize >= 0) {
      // Was already allocated
      PlgDBfree(Index);
      PlgDBfree(Offset);
      } // endif Xsize

    // Prepare non conservative sort with offet values
    Index.Size = Nval * sizeof(int);

    if (!PlgDBalloc(g, NULL, Index))
      goto error;

    Offset.Size = (Nval + 1) * sizeof(int);

    if (!PlgDBalloc(g, NULL, Offset))
      goto error;

    Xsize = Nval;
    } // endif Nval

  // Call the sort program, it returns the number of distinct values
  Ndif = Qsort(g, Nval);

  if (Ndif < 0)
    goto error;

  // Use the sort index to reorder the data in storage so it will
  // be physically sorted and Index can be removed.
  for (i = 0; i < Nval; i++) {
    if (Pex[i] == i || Pex[i] == Nval)
      // Already placed or already moved
      continue;

    Save(i);

    for (j = i;; j = k) {
      k = Pex[j];
      Pex[j] = Nval;           // Mark position as set

      if (k == i) {
        Restore(j);
        break;                 // end of loop
      } else
        Move(j, k);

      } // endfor j

    } // endfor i

  // Reduce the size of the To_Val array if Ndif < Nval
  if (Ndif < Nval) {
    for (i = 1; i < Ndif; i++)
      if (i != Pof[i])
        break;

    for (; i < Ndif; i++)
      Move(i, Pof[i]);

    Nval = Ndif;
    } // endif ndif

//if (!Correlated) {
    if (Size > Nval) {
      Size = Nval;
      Valblk->ReAllocate(g, Size);
      } // endif Size

    // Index and Offset are not used anymore
    PlgDBfree(Index);
    PlgDBfree(Offset);
    Xsize = -1;
//  } // endif Correlated

  Bot = -1;                // For non optimized search
  Top = Ndif;              //   Find searches the whole array.
  return FALSE;

 error:
  Nval = Ndif = 0;
  Valblk->Free();
  PlgDBfree(Index);
  PlgDBfree(Offset);
  return TRUE;
  } // end of Sort
Exemplo n.º 5
0
bool MULAR::Sort(PGLOBAL g)
  {
  int i, j, k, n, nval, ndif;

  // All arrays must have the same number of values
  nval = Pars[0]->Nval;

  for (n = 1; n < Narray; n++)
    if (Pars[n]->Nval != nval) {
      strcpy(g->Message, MSG(BAD_ARRAY_VAL));
      return TRUE;
      } // endif nval

  // Prepare non conservative sort with offet values
  Index.Size = nval * sizeof(int);

  if (!PlgDBalloc(g, NULL, Index))
    goto error;

  Offset.Size = (nval + 1) * sizeof(int);

  if (!PlgDBalloc(g, NULL, Offset))
    goto error;

  // Call the sort program, it returns the number of distinct values
  ndif = Qsort(g, nval);

  if (ndif < 0)
    goto error;

  // Use the sort index to reorder the data in storage so it will
  // be physically sorted and Index can be removed.
  for (i = 0; i < nval; i++) {
    if (Pex[i] == i || Pex[i] == nval)
      // Already placed or already moved
      continue;

    for (n = 0; n < Narray; n++)
      Pars[n]->Save(i);

    for (j = i;; j = k) {
      k = Pex[j];
      Pex[j] = nval;           // Mark position as set

      if (k == i) {
        for (n = 0; n < Narray; n++)
          Pars[n]->Restore(j);

        break;                 // end of loop
      } else
        for (n = 0; n < Narray; n++)
          Pars[n]->Move(j, k);

      } // endfor j

    } // endfor i

  // Reduce the size of the To_Val array if ndif < nval
  if (ndif < nval) {
    for (i = 1; i < ndif; i++)
      if (i != Pof[i])
        break;

    for (; i < ndif; i++)
      for (n = 0; n < Narray; n++)
        Pars[n]->Move(i, Pof[i]);

    for (n = 0; n < Narray; n++) {
      Pars[n]->Nval = ndif;
      Pars[n]->Size = ndif;
      Pars[n]->Valblk->ReAllocate(g, ndif);
      } // endfor n

    } // endif ndif

  // Index and Offset are not used anymore
  PlgDBfree(Index);
  PlgDBfree(Offset);

  for (n = 0; n < Narray; n++) {
    Pars[n]->Bot = -1;        // For non optimized search
    Pars[n]->Top = ndif;      //   Find searches the whole array.
    } // endfor n

  return FALSE;

 error:
  PlgDBfree(Index);
  PlgDBfree(Offset);
  return TRUE;
  } // end of Sort