void VALBLK::ChkTyp(PVAL v) { if (Check && (Type != v->GetType() || Unsigned != v->IsUnsigned())) { PGLOBAL& g = Global; strcpy(g->Message, MSG(VALTYPE_NOMATCH)); longjmp(g->jumper[g->jump_level], Type); } // endif Type } // end of ChkTyp
int STRBLK::CompVal(PVAL vp, int n) { ChkIndx(n); ChkTyp(vp); if (vp->IsNull() || !Strp[n]) DBUG_ASSERT(false); return strcmp(vp->GetCharValue(), Strp[n]); } // end of CompVal
int CHRBLK::CompVal(PVAL vp, int n) { ChkIndx(n); ChkTyp(vp); char *xvp = vp->GetCharValue(); // Get Value zero ended string bool ci = Ci || vp->IsCi(); // true if is case insensitive GetValPtrEx(n); // Get a zero ended string in Valp return (ci) ? stricmp(xvp, Valp) : strcmp(xvp, Valp); } // end of CompVal
void STRBLK::SetValue(PVAL valp, int n) { ChkIndx(n); ChkTyp(valp); if (!valp->IsNull()) SetValue((PSZ)valp->GetCharValue(), n); else Strp[n] = NULL; } // end of SetValue
bool ARRAY::AddValue(PGLOBAL g, PVAL vp) { if (Type != vp->GetType()) { sprintf(g->Message, MSG(ADD_BAD_TYPE), GetTypeName(vp->GetType()), GetTypeName(Type)); return TRUE; } // endif Type if (trace) htrc(" adding (%d) from vp=%p\n", Nval, vp); Vblp->SetValue(vp, Nval++); return FALSE; } // end of AddValue
void CHRBLK::SetValue(PVAL valp, int n) { bool b; ChkIndx(n); ChkTyp(valp); if (!(b = valp->IsNull())) SetValue((PSZ)valp->GetCharValue(), n); else Reset(n); SetNull(n, b && Nullable); } // end of SetValue
bool ARRAY::FilTest(PGLOBAL g, PVAL valp, OPVAL opc, int opm) { int i; PVAL vp; BYTE bt = OpBmp(g, opc); int top = Nval - 1; if (top < 0) // Array is empty // Return TRUE for ALL because it means that there are no item that // does not verify the condition, which is true indeed. // Return FALSE for ANY because TRUE means that there is at least // one item that verifies the condition, which is false. return opm == 2; if (valp) { if (Type != valp->GetType()) { Value->SetValue_pval(valp); vp = Value; } else vp = valp; } else if (opc != OP_EXIST) { sprintf(g->Message, MSG(MISSING_ARG), opc); longjmp(g->jumper[g->jump_level], TYPE_ARRAY); } else // OP_EXIST return Nval > 0; if (opc == OP_IN || (opc == OP_EQ && opm == 1)) return Find(vp); else if (opc == OP_NE && opm == 2) return !Find(vp); else if (opc == OP_EQ && opm == 2) return (Ndif == 1) ? !(Vcompare(vp, 0) & bt) : FALSE; else if (opc == OP_NE && opm == 1) return (Ndif == 1) ? !(Vcompare(vp, 0) & bt) : TRUE; if (Type != TYPE_LIST) { if (opc == OP_GT || opc == OP_GE) return !(Vcompare(vp, (opm == 1) ? 0 : top) & bt); else return !(Vcompare(vp, (opm == 2) ? 0 : top) & bt); } // endif Type // Case of TYPE_LIST if (opm == 2) { for (i = 0; i < Nval; i++) if (Vcompare(vp, i) & bt) return FALSE; return TRUE; } else { // opm == 1 for (i = 0; i < Nval; i++) if (!(Vcompare(vp, i) & bt)) return TRUE; return FALSE; } // endif opm } // end of FilTest
bool ARRAY::Find(PVAL valp) { register int n; PVAL vp; if (Type != valp->GetType()) { Value->SetValue_pval(valp); vp = Value; } else vp = valp; Inf = Bot, Sup = Top; while (Sup - Inf > 1) { X = (Inf + Sup) >> 1; n = Vblp->CompVal(vp, X); if (n < 0) Sup = X; else if (n > 0) Inf = X; else return TRUE; } // endwhile return FALSE; } // end of Find
bool INICOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check) { if (!(To_Val = value)) { sprintf(g->Message, MSG(VALUE_ERROR), Name); return true; } else if (Buf_Type == value->GetType()) { // Values are of the (good) column type if (Buf_Type == TYPE_DATE) { // If any of the date values is formatted // output format must be set for the receiving table if (GetDomain() || ((DTVAL *)value)->IsFormatted()) goto newval; // This will make a new value; } else if (Buf_Type == TYPE_DOUBLE || Buf_Type == TYPE_DECIM) // Float values must be written with the correct (column) precision // Note: maybe this should be forced by ShowValue instead of this ? value->SetPrec(GetScale()); Value = value; // Directly access the external value } else { // Values are not of the (good) column type if (check) { sprintf(g->Message, MSG(TYPE_VALUE_ERR), Name, GetTypeName(Buf_Type), GetTypeName(value->GetType())); return true; } // endif check newval: if (InitValue(g)) // Allocate the matching value block return true; } // endif's Value, Buf_Type // Allocate the internal value buffer AllocBuf(g); // Because Colblk's have been made from a copy of the original TDB in // case of Update, we must reset them to point to the original one. if (To_Tdb->GetOrig()) To_Tdb = (PTDB)To_Tdb->GetOrig(); // Set the Column Status = (ok) ? BUF_EMPTY : BUF_NO; return false; } // end of SetBuffer
int STRBLK::Find(PVAL vp) { int i; PSZ s; ChkTyp(vp); if (vp->IsNull()) return -1; else s = vp->GetCharValue(); for (i = 0; i < Nval; i++) if (Strp[i] && !strcmp(s, Strp[i])) break; return (i < Nval) ? i : (-1); } // end of Find
bool ARRAY::GetSubValue(PGLOBAL g, PVAL valp, int *kp) { PVBLK vblp; if (Type != TYPE_LIST) { sprintf(g->Message, MSG(NO_SUB_VAL), Type); return TRUE; } // endif Type vblp = ((LSTBLK*)Vblp)->Mbvk[kp[0]]->Vblk; valp->SetValue_pvblk(vblp, kp[1]); return FALSE; } // end of GetSubValue
void TYPBLK<TYPE>::SetValue(PVAL valp, int n) { bool b; ChkIndx(n); ChkTyp(valp); if (!(b = valp->IsNull())) Typp[n] = GetTypedValue(valp); else Reset(n); SetNull(n, b && Nullable); } // end of SetValue
int CHRBLK::Find(PVAL vp) { ChkTyp(vp); int i; bool ci = Ci || vp->IsCi(); PSZ s = vp->GetCharValue(); if (vp->IsNull()) return -1; for (i = 0; i < Nval; i++) { if (IsNull(i)) continue; GetValPtrEx(i); // Get a zero ended string in Valp if (!((ci) ? strnicmp(s, Valp, Long) : strncmp(s, Valp, Long))) break; } // endfor i return (i < Nval) ? i : (-1); } // end of Find
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
void ARRAY::GetNthValue(PVAL valp, int n) { valp->SetValue_pvblk(Vblp, n); } // end of GetNthValue
uchar TYPBLK<uchar>::GetTypedValue(PVAL valp) {return valp->GetUTinyValue();}
double TYPBLK<double>::GetTypedValue(PVAL valp) {return valp->GetFloatValue();}
ulonglong TYPBLK<ulonglong>::GetTypedValue(PVAL valp) {return valp->GetUBigintValue();}
ushort TYPBLK<ushort>::GetTypedValue(PVAL valp) {return valp->GetUShortValue();}
uint TYPBLK<uint>::GetTypedValue(PVAL valp) {return valp->GetUIntValue();}
BYTE ARRAY::Vcompare(PVAL vp, int n) { Value->SetValue_pvblk(Vblp, n); return vp->TestValue(Value); } // end of Vcompare
strcpy(g->Message, MSG(BLKTYPLEN_MISM)); longjmp(g->jumper[g->jump_level], Type); } // endif Type if (!(b = pv->IsNull(n2))) memcpy(Chrp + n1 * Long, ((CHRBLK*)pv)->Chrp + n2 * Long, Long); else Reset(n1); SetNull(n1, b && Nullable); } // end of SetValue /***********************************************************************/ /* Set one value in a block if val is less than the current value. */ /***********************************************************************/ void CHRBLK::SetMin(PVAL valp, int n) { CheckParms(valp, n) CheckBlanks char *vp = valp->GetCharValue(); char *bp = Chrp + n * Long; if (((Ci) ? strnicmp(vp, bp, Long) : strncmp(vp, bp, Long)) < 0) memcpy(bp, vp, Long); } // end of SetMin /***********************************************************************/ /* Set one value in a block if val is greater than the current value. */ /***********************************************************************/ void CHRBLK::SetMax(PVAL valp, int n) {