bool DATBLK::SetFormat(PGLOBAL g, PSZ fmt, int len, int year) { if (!(Dvalp = AllocateValue(g, TYPE_DATE, len, year, false, fmt))) return true; return false; } // end of SetFormat
ARRAY::ARRAY(PGLOBAL g, PARRAY par, int k) : CSORT(FALSE) { int prec; LSTBLK *lp; if (par->Type != TYPE_LIST) { Type = TYPE_ERROR; return; } // endif Type lp = (LSTBLK*)par->Vblp; Nval = par->Nval; Ndif = 0; Bot = 0; Top = 0; Size = par->Size; Xsize = -1; Valblk = lp->Mbvk[k]; Vblp = Valblk->Vblk; Type = Vblp->GetType(); Len = (Type == TYPE_STRING) ? Vblp->GetVlen() : 0; prec = (Type == TYPE_FLOAT) ? 2 : 0; Value = AllocateValue(g, Type, Len, prec, NULL); Constant = TRUE; } // end of ARRAY constructor
bool FNCCOL::InitColumn(PGLOBAL g) { // Must have its own value block if (InitValue(g)) return TRUE; // Make a value from the column name Hval = AllocateValue(g, Name, TYPE_STRING); Hval->SetPrec(1); // Case insensitive Xcolp = ((PTDBPIVOT)To_Tdb)->Xcolp; AddStatus(BUF_READ); // All is done here return FALSE; } // end of InitColumn
ARRAY::ARRAY(PGLOBAL g, int type, int size, int length, int prec) : CSORT(FALSE) { Nval = 0; Ndif = 0; Bot = 0; Top = 0; Size = size; Type = type; Xsize = -1; Len = 1; switch (type) { case TYPE_STRING: Len = length; case TYPE_SHORT: case TYPE_INT: case TYPE_DOUBLE: case TYPE_PCHAR: Type = type; break; case TYPE_VOID: Type = TYPE_INT; break; #if 0 case TYPE_TOKEN: break; case TYPE_LIST: Len = 0; prec = length; break; #endif // 0 default: // This is illegal an causes an ill formed array building sprintf(g->Message, MSG(BAD_ARRAY_TYPE), type); Type = TYPE_ERROR; return; } // endswitch type Valblk = new(g) MBVALS; if (!(Vblp = Valblk->Allocate(g, Type, Len, prec, Size))) Type = TYPE_ERROR; else if (!Valblk->GetMemp() && Type != TYPE_LIST) // The error message was built by PlgDBalloc Type = TYPE_ERROR; else if (type != TYPE_PCHAR) Value = AllocateValue(g, type, Len, prec); Constant = TRUE; } // end of ARRAY constructor
bool COLBLK::InitValue(PGLOBAL g) { if (Value) return false; // Already done // Unsigned can be set only for valid value types int prec = (Unsigned) ? 1 : GetPrecision(); // Allocate a Value object if (!(Value = AllocateValue(g, Buf_Type, Format.Length, prec, GetDomain()))) return true; AddStatus(BUF_READY); Value->SetNullable(Nullable); #ifdef DEBTRACE htrc(" colp=%p type=%d value=%p coluse=%.4X status=%.4X\n", this, Buf_Type, Value, ColUse, Status); #endif return false; } // end of InitValue
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
int ARRAY::Convert(PGLOBAL g, int k, PVAL vp) { int i, prec = 0; bool b = FALSE; PMBV ovblk = Valblk; PVBLK ovblp = Vblp; Type = k; // k is the new type Valblk = new(g) MBVALS; switch (Type) { case TYPE_DOUBLE: prec = 2; case TYPE_SHORT: case TYPE_INT: case TYPE_DATE: Len = 1; break; default: sprintf(g->Message, MSG(BAD_CONV_TYPE), Type); return TYPE_ERROR; } // endswitch k Size = Nval; Nval = 0; Vblp = Valblk->Allocate(g, Type, Len, prec, Size); if (!Valblk->GetMemp()) // The error message was built by PlgDBalloc return TYPE_ERROR; else Value = AllocateValue(g, Type, Len, prec); /*********************************************************************/ /* Converting STRING to DATE can be done according to date format. */ /*********************************************************************/ if (Type == TYPE_DATE && ovblp->GetType() == TYPE_STRING && vp) if (((DTVAL*)Value)->SetFormat(g, vp)) return TYPE_ERROR; else b = TRUE; // Sort the new array on date internal values /*********************************************************************/ /* Do the actual conversion. */ /*********************************************************************/ for (i = 0; i < Size; i++) { Value->SetValue_pvblk(ovblp, i); if (AddValue(g, Value)) return TYPE_ERROR; } // endfor i /*********************************************************************/ /* For sorted arrays, get the initial find values. */ /*********************************************************************/ if (b) Sort(g); ovblk->Free(); return Type; } // end of Convert