PVBLK AllocValBlock(PGLOBAL g, void *mp, int type, int nval, int len, int prec, bool check, bool blank, bool un) { PVBLK blkp; if (trace) htrc("AVB: mp=%p type=%d nval=%d len=%d check=%u blank=%u\n", mp, type, nval, len, check, blank); switch (type) { case TYPE_STRING: case TYPE_DECIM: if (len) blkp = new(g) CHRBLK(mp, nval, len, prec, blank); else blkp = new(g) STRBLK(g, mp, nval); break; case TYPE_SHORT: if (un) blkp = new(g) TYPBLK<ushort>(mp, nval, type, 0, true); else blkp = new(g) TYPBLK<short>(mp, nval, type); break; case TYPE_INT: if (un) blkp = new(g) TYPBLK<uint>(mp, nval, type, 0, true); else blkp = new(g) TYPBLK<int>(mp, nval, type); break; case TYPE_DATE: // ????? blkp = new(g) DATBLK(mp, nval); break; case TYPE_BIGINT: if (un) blkp = new(g) TYPBLK<ulonglong>(mp, nval, type, 0, true); else blkp = new(g) TYPBLK<longlong>(mp, nval, type); break; case TYPE_DOUBLE: blkp = new(g) TYPBLK<double>(mp, nval, type, prec); break; case TYPE_TINY: if (un) blkp = new(g) TYPBLK<uchar>(mp, nval, type, 0, true); else blkp = new(g) TYPBLK<char>(mp, nval, type); break; default: sprintf(g->Message, MSG(BAD_VALBLK_TYPE), type); return NULL; } // endswitch Type blkp->Init(g, check); return blkp; } // end of AllocValBlock
void VALBLK::ChkTyp(PVBLK vb) { if (Check && (Type != vb->GetType() || Unsigned != vb->IsUnsigned())) { PGLOBAL& g = Global; strcpy(g->Message, MSG(VALTYPE_NOMATCH)); longjmp(g->jumper[g->jump_level], Type); } // endif Type } // end of ChkTyp
void CHRBLK::SetValue(PVBLK pv, int n1, int n2) { bool b; if (Type != pv->GetType() || Long != ((CHRBLK*)pv)->Long) { PGLOBAL& g = Global; strcpy(g->Message, MSG(BLKTYPLEN_MISM)); longjmp(g->jumper[g->jump_level], Type); } // endif Type if (!(b = pv->IsNull(n2) && Nullable)) memcpy(Chrp + n1 * Long, ((CHRBLK*)pv)->Chrp + n2 * Long, Long); else Reset(n1); SetNull(n1, b); } // end of SetValue
void STRBLK::SetValues(PVBLK pv, int k, int n) { CheckType(pv) PSZ *sp = ((STRBLK*)pv)->Strp; for (register int i = k; i < n; i++) Strp[i] = (!pv->IsNull(i)) ? sp[i] : NULL; } // end of SetValues
void TYPBLK<TYPE>::SetValue(PVBLK pv, int n1, int n2) { bool b; ChkIndx(n1); ChkTyp(pv); if (!(b = pv->IsNull(n2) && Nullable)) Typp[n1] = GetTypedValue(pv, n2); else Reset(n1); SetNull(n1, b); } // end of SetValue
void CHRBLK::SetValues(PVBLK pv, int k, int n) { #if defined(_DEBUG) if (Type != pv->GetType() || Long != ((CHRBLK*)pv)->Long) { PGLOBAL& g = Global; strcpy(g->Message, MSG(BLKTYPLEN_MISM)); longjmp(g->jumper[g->jump_level], Type); } // endif Type #endif // _DEBUG char *p = ((CHRBLK*)pv)->Chrp; if (!k) memcpy(Chrp, p, Long * n); else memcpy(Chrp + k * Long, p + k * Long, Long * (n - k)); } // end of SetValues
uchar TYPBLK<uchar>::GetTypedValue(PVBLK blk, int n) {return blk->GetUTinyValue(n);}
double TYPBLK<double>::GetTypedValue(PVBLK blk, int n) {return blk->GetFloatValue(n);}
ulonglong TYPBLK<ulonglong>::GetTypedValue(PVBLK blk, int n) {return blk->GetUBigintValue(n);}
ushort TYPBLK<ushort>::GetTypedValue(PVBLK blk, int n) {return blk->GetUShortValue(n);}
uint TYPBLK<uint>::GetTypedValue(PVBLK blk, int n) {return blk->GetUIntValue(n);}
void STRBLK::SetValue(PVBLK pv, int n1, int n2) { ChkTyp(pv); Strp[n1] = (!pv->IsNull(n2)) ? ((STRBLK*)pv)->Strp[n2] : NULL; } // end of SetValue
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
PQRYRES MyColumns(PGLOBAL g, THD *thd, const char *host, const char *db, const char *user, const char *pwd, const char *table, const char *colpat, int port, bool info) { int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_INT, TYPE_STRING, TYPE_SHORT, TYPE_SHORT, TYPE_SHORT, TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_STRING}; XFLD fldtyp[] = {FLD_NAME, FLD_TYPE, FLD_TYPENAME, FLD_PREC, FLD_KEY, FLD_SCALE, FLD_RADIX, FLD_NULL, FLD_REM, FLD_NO, FLD_DEFAULT, FLD_EXTRA, FLD_CHARSET}; unsigned int length[] = {0, 4, 16, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0}; char *fld, *colname, *chset, *fmt, v, buf[128], uns[16], zero[16]; int i, n, nf, ncol = sizeof(buftyp) / sizeof(int); int len, type, prec, rc, k = 0; PQRYRES qrp; PCOLRES crp; MYSQLC myc; if (!port) port = mysqld_port; if (!info) { /********************************************************************/ /* Open the connection with the MySQL server. */ /********************************************************************/ if (myc.Open(g, host, db, user, pwd, port)) return NULL; /********************************************************************/ /* Do an evaluation of the result size. */ /********************************************************************/ STRING cmd(g, 64, "SHOW FULL COLUMNS FROM "); bool b = cmd.Append((PSZ)table); b |= cmd.Append(" FROM "); b |= cmd.Append((PSZ)(db ? db : PlgGetUser(g)->DBName)); if (colpat) { b |= cmd.Append(" LIKE "); b |= cmd.Append((PSZ)colpat); } // endif colpat if (b) { strcpy(g->Message, "Out of memory"); return NULL; } // endif b if (trace) htrc("MyColumns: cmd='%s'\n", cmd.GetStr()); if ((n = myc.GetResultSize(g, cmd.GetStr())) < 0) { myc.Close(); return NULL; } // endif n /********************************************************************/ /* Get the size of the name and default columns. */ /********************************************************************/ length[0] = myc.GetFieldLength(0); // length[10] = myc.GetFieldLength(5); } else { n = 0; length[0] = 128; } // endif info /**********************************************************************/ /* Allocate the structures used to refer to the result set. */ /**********************************************************************/ if (!(qrp = PlgAllocResult(g, ncol, n, IDS_COLUMNS + 3, buftyp, fldtyp, length, false, true))) return NULL; // Some columns must be renamed for (i = 0, crp = qrp->Colresp; crp; crp = crp->Next) switch (++i) { case 2: crp->Nulls = (char*)PlugSubAlloc(g, NULL, n); break; case 4: crp->Name = "Length"; break; case 5: crp->Name = "Key"; break; case 10: crp->Name = "Date_fmt"; break; case 11: crp->Name = "Default"; break; case 12: crp->Name = "Extra"; break; case 13: crp->Name = "Collation"; break; } // endswitch i if (info) return qrp; /**********************************************************************/ /* Now get the results into blocks. */ /**********************************************************************/ for (i = 0; i < n; /*i++*/) { if ((rc = myc.Fetch(g, -1)) == RC_FX) { myc.Close(); return NULL; } else if (rc == RC_EF) break; // Get column name colname = myc.GetCharField(0); crp = qrp->Colresp; // Column_Name crp->Kdata->SetValue(colname, i); // Get type, type name, precision, unsigned and zerofill chset = myc.GetCharField(2); fld = myc.GetCharField(1); prec = 0; len = 0; v = (chset && !strcmp(chset, "binary")) ? 'B' : 0; *uns = 0; *zero = 0; switch ((nf = sscanf(fld, "%[^(](%d,%d", buf, &len, &prec))) { case 3: nf = sscanf(fld, "%[^(](%d,%d) %s %s", buf, &len, &prec, uns, zero); break; case 2: nf = sscanf(fld, "%[^(](%d) %s %s", buf, &len, uns, zero) + 1; break; case 1: nf = sscanf(fld, "%s %s %s", buf, uns, zero) + 2; break; default: sprintf(g->Message, MSG(BAD_FIELD_TYPE), fld); myc.Close(); return NULL; } // endswitch nf if ((type = MYSQLtoPLG(buf, &v)) == TYPE_ERROR) { if (v == 'K') { // Skip this column sprintf(g->Message, "Column %s skipped (unsupported type %s)", colname, buf); PushWarning(g, thd); continue; } // endif v sprintf(g->Message, "Column %s unsupported type %s", colname, buf); myc.Close(); return NULL; } else if (type == TYPE_STRING) { if (v == 'X') { len = GetConvSize(); sprintf(g->Message, "Column %s converted to varchar(%d)", colname, len); PushWarning(g, thd); v = 'V'; } else len = MY_MIN(len, 4096); } // endif type qrp->Nblin++; crp = crp->Next; // Data_Type crp->Kdata->SetValue(type, i); switch (nf) { case 5: crp->Nulls[i] = 'Z'; break; case 4: crp->Nulls[i] = 'U'; break; default: crp->Nulls[i] = v; break; } // endswitch nf crp = crp->Next; // Type_Name crp->Kdata->SetValue(buf, i); if (type == TYPE_DATE) { // When creating tables we do need info about date columns fmt = MyDateFmt(buf); len = strlen(fmt); } else fmt = NULL; crp = crp->Next; // Precision crp->Kdata->SetValue(len, i); crp = crp->Next; // key (was Length) fld = myc.GetCharField(4); crp->Kdata->SetValue(fld, i); crp = crp->Next; // Scale crp->Kdata->SetValue(prec, i); crp = crp->Next; // Radix crp->Kdata->SetValue(0, i); crp = crp->Next; // Nullable fld = myc.GetCharField(3); crp->Kdata->SetValue((toupper(*fld) == 'Y') ? 1 : 0, i); crp = crp->Next; // Remark fld = myc.GetCharField(8); crp->Kdata->SetValue(fld, i); crp = crp->Next; // Date format // crp->Kdata->SetValue((fmt) ? fmt : (char*) "", i); crp->Kdata->SetValue(fmt, i); crp = crp->Next; // New (default) fld = myc.GetCharField(5); crp->Kdata->SetValue(fld, i); crp = crp->Next; // New (extra) fld = myc.GetCharField(6); crp->Kdata->SetValue(fld, i); crp = crp->Next; // New (charset) fld = chset; crp->Kdata->SetValue(fld, i); i++; // Can be skipped } // endfor i #if 0 if (k > 1) { // Multicolumn primary key PVBLK vbp = qrp->Colresp->Next->Next->Next->Next->Kdata; for (i = 0; i < n; i++) if (vbp->GetIntValue(i)) vbp->SetValue(k, i); } // endif k #endif // 0 /**********************************************************************/ /* Close MySQL connection. */ /**********************************************************************/ myc.Close(); /**********************************************************************/ /* Return the result pointer for use by GetData routines. */ /**********************************************************************/ return qrp; } // end of MyColumns