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
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
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
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
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