PWMIUT InitWMI(PGLOBAL g, char *nsp, char *classname) { IWbemLocator *loc; char *p; HRESULT res; PWMIUT wp = (PWMIUT)PlugSubAlloc(g, NULL, sizeof(WMIUTIL)); if (trace) htrc("WMIColumns class %s space %s\n", SVP(classname), SVP(nsp)); /*********************************************************************/ /* Set default values for the namespace and class name. */ /*********************************************************************/ if (!nsp) nsp = "root\\cimv2"; if (!classname) { if (!stricmp(nsp, "root\\cimv2")) classname = "ComputerSystemProduct"; else if (!stricmp(nsp, "root\\cli")) classname = "Msft_CliAlias"; else { strcpy(g->Message, "Missing class name"); return NULL; } // endif classname } // endif classname /*********************************************************************/ /* Initialize WMI. */ /*********************************************************************/ //res = CoInitializeEx(NULL, COINIT_MULTITHREADED); res = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); if (FAILED(res)) { sprintf(g->Message, "Failed to initialize COM library. " "Error code = %p", res); return NULL; } // endif res #if 0 // irrelevant for a DLL res = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_CONNECT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL); if (res != RPC_E_TOO_LATE && FAILED(res)) { sprintf(g->Message, "Failed to initialize security. " "Error code = %p", res); CoUninitialize(); return NULL; } // endif Res #endif // 0 res = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (void**) &loc); if (FAILED(res)) { sprintf(g->Message, "Failed to create Locator. " "Error code = %p", res); CoUninitialize(); return NULL; } // endif res res = loc->ConnectServer(_bstr_t(nsp), NULL, NULL, NULL, 0, NULL, NULL, &wp->Svc); if (FAILED(res)) { sprintf(g->Message, "Could not connect. Error code = %p", res); loc->Release(); CoUninitialize(); return NULL; } // endif res loc->Release(); if (trace) htrc("Successfully connected to namespace.\n"); /*********************************************************************/ /* Perform a full class object retrieval. */ /*********************************************************************/ p = (char*)PlugSubAlloc(g, NULL, strlen(classname) + 7); if (strchr(classname, '_')) strcpy(p, classname); else strcat(strcpy(p, "Win32_"), classname); res = wp->Svc->GetObject(bstr_t(p), 0, 0, &wp->Cobj, 0); if (FAILED(res)) { sprintf(g->Message, "failed GetObject %s in %s\n", classname, nsp); wp->Svc->Release(); wp->Svc = NULL; // MUST be set to NULL (why?) return NULL; } // endif res return wp; } // end of InitWMI
int TDBINI::ReadDB(PGLOBAL g) { /*********************************************************************/ /* Now start the pseudo reading process. */ /*********************************************************************/ #if 0 // INI tables are not indexable if (To_Kindex) { /*******************************************************************/ /* Reading is by an index table. */ /*******************************************************************/ int recpos = To_Kindex->Fetch(g); switch (recpos) { case -1: // End of file reached return RC_EF; case -2: // No match for join return RC_NF; case -3: // Same record as last non null one return RC_OK; default: Section = (char*)recpos; // No good on 64 bit machines } // endswitch recpos } else { #endif // 0 if (!Section) Section = Seclist; else Section += (strlen(Section) + 1); if (trace > 1) htrc("INI ReadDB: section=%s N=%d\n", Section, N); N++; //} // endif To_Kindex return (*Section) ? RC_OK : RC_EF; } // end of ReadDB /***********************************************************************/ /* WriteDB: Data Base write routine for INI access methods. */ /***********************************************************************/ int TDBINI::WriteDB(PGLOBAL g) { // This is to check that section name was given when inserting if (Mode == MODE_INSERT) Section = NULL; // Nothing else to do because all was done in WriteColumn return RC_OK; } // end of WriteDB /***********************************************************************/ /* Data Base delete line routine for INI access methods. */ /***********************************************************************/ int TDBINI::DeleteDB(PGLOBAL g, int irc) { switch (irc) { case RC_EF: break; case RC_FX: while (ReadDB(g) == RC_OK) if (!WritePrivateProfileString(Section, NULL, NULL, Ifile)) { sprintf(g->Message, "Error %d accessing %s", GetLastError(), Ifile); return RC_FX; } // endif break; default: if (!Section) { strcpy(g->Message, MSG(NO_SECTION_NAME)); return RC_FX; } else if (!WritePrivateProfileString(Section, NULL, NULL, Ifile)) { sprintf(g->Message, "Error %d accessing %s", GetLastError(), Ifile); return RC_FX; } // endif rc } // endswitch irc return RC_OK; } // end of DeleteDB /***********************************************************************/ /* Data Base close routine for INI access methods. */ /***********************************************************************/ void TDBINI::CloseDB(PGLOBAL g) { #if !defined(WIN32) PROFILE_Close(Ifile); #endif // !WIN32 } // end of CloseDB
PTDBASE TDBPRX::GetSubTable(PGLOBAL g, PTABLE tabp, bool b) { const char *sp = NULL; char *db, *name; bool mysql = true; PTDB tdbp = NULL; TABLE_SHARE *s = NULL; Field* *fp = NULL; PCATLG cat = To_Def->GetCat(); PHC hc = ((MYCAT*)cat)->GetHandler(); LPCSTR cdb, curdb = hc->GetDBName(NULL); THD *thd = (hc->GetTable())->in_use; db = (char*)tabp->GetQualifier(); name = (char*)tabp->GetName(); // Check for eventual loop for (PTABLE tp = To_Table; tp; tp = tp->Next) { cdb = (tp->Qualifier) ? tp->Qualifier : curdb; if (!stricmp(name, tp->Name) && !stricmp(db, cdb)) { sprintf(g->Message, "Table %s.%s pointing on itself", db, name); return NULL; } // endif } // endfor tp if (!tabp->GetSrc()) { if (!(s = GetTableShare(g, thd, db, name, mysql))) return NULL; if (s->is_view && !b) s->field = hc->get_table()->s->field; hc->tshp = s; } else if (b) { // Don't use caller's columns fp = hc->get_table()->field; hc->get_table()->field = NULL; // Make caller use the source definition sp = hc->get_table()->s->option_struct->srcdef; hc->get_table()->s->option_struct->srcdef = tabp->GetSrc(); } // endif srcdef if (mysql) { #if defined(MYSQL_SUPPORT) // Access sub-table via MySQL API if (!(tdbp= cat->GetTable(g, tabp, Mode, "MYPRX"))) { char buf[MAX_STR]; strcpy(buf, g->Message); sprintf(g->Message, "Error accessing %s.%s: %s", db, name, buf); hc->tshp = NULL; goto err; } // endif Define if (db) ((PTDBMY)tdbp)->SetDatabase(tabp->GetQualifier()); if (Mode == MODE_UPDATE || Mode == MODE_DELETE) tdbp->SetName(Name); // For Make_Command #else // !MYSQL_SUPPORT sprintf(g->Message, "%s.%s is not a CONNECT table", db, tblp->Name); goto err; #endif // MYSQL_SUPPORT } else { // Sub-table is a CONNECT table tabp->Next = To_Table; // For loop checking tdbp = cat->GetTable(g, tabp, Mode); } // endif mysql if (s) { if (s->is_view && !b) s->field = NULL; hc->tshp = NULL; } else if (b) { // Restore s structure that can be in cache hc->get_table()->field = fp; hc->get_table()->s->option_struct->srcdef = sp; } // endif s if (trace && tdbp) htrc("Subtable %s in %s\n", name, SVP(((PTDBASE)tdbp)->GetDef()->GetDB())); err: if (s) free_table_share(s); return (PTDBASE)tdbp; } // end of GetSubTable
void TDBASE::MarkDB(PGLOBAL, PTDB tdb2) { if (trace) htrc("DOS MarkDB: tdbp=%p tdb2=%p\n", this, tdb2); } // end of MarkDB
int TDBFMT::ReadBuffer(PGLOBAL g) { int i, len, n, deb, fin, nwp, pos = 0, rc; bool bad = false; if ((rc = Txfp->ReadBuffer(g)) != RC_OK || !Fields) return rc; else ++Linenum; if (trace > 1) htrc("FMT: Row %d is '%s' rc=%d\n", Linenum, To_Line, rc); // Find the offsets and lengths of the columns for this row for (i = 0; i < Fields; i++) { if (!bad) { deb = fin = -1; if (!FldFormat[i]) { n = 0; } else if (FmtTest[i] == 1) { nwp = -1; n = sscanf(To_Line + pos, FldFormat[i], &deb, To_Fld, &fin, &nwp); } else { n = sscanf(To_Line + pos, FldFormat[i], &deb, To_Fld, &fin); if (n != 1 && (deb >= 0 || i == Fields - 1) && FmtTest[i] == 2) { // Missing optional field, not an error n = 1; if (i == Fields - 1) fin = deb = 0; else fin = deb; } // endif n nwp = fin; } // endif i if (n != 1 || deb < 0 || fin < 0 || nwp < 0) { // This is to avoid a very strange sscanf bug occuring // with fields that ends with a null character. // This bug causes subsequent sscanf to return in error, // so next lines are not parsed correctly. sscanf("a", "%*c"); // Seems to reset things Ok if (CheckErr()) { sprintf(g->Message, MSG(BAD_LINEFLD_FMT), Linenum, i + 1, Name); return RC_FX; } else if (Accept) bad = true; else return RC_NF; } // endif n... } // endif !bad if (!bad) { Offset[i] = pos + deb; len = fin - deb; } else { nwp = 0; Offset[i] = pos; len = 0; } // endif bad // if (Mode != MODE_UPDATE) Fldlen[i] = len; // else if (len > Fldlen[i]) { // sprintf(g->Message, MSG(FIELD_TOO_LONG), i+1, To_Tdb->RowNumber(g)); // return RC_FX; // } else { // strncpy(Field[i], To_Line + pos, len); // Field[i][len] = '\0'; // } // endif Mode pos += nwp; } // endfor i if (bad) Nerr++; else sscanf("a", "%*c"); // Seems to reset things Ok return rc; } // end of ReadBuffer
bool DOSFAM::OpenTableFile(PGLOBAL g) { char opmode[4], filename[_MAX_PATH]; //int ftype = Tdbp->GetFtype(); MODE mode = Tdbp->Mode; PDBUSER dbuserp = PlgGetUser(g); // This is required when using Unix files under Windows Bin = (Ending == 1); switch (mode) { case MODE_READ: strcpy(opmode, "r"); break; case MODE_DELETE: if (!Tdbp->Next) { // Store the number of deleted lines DelRows = Cardinality(g); if (Blocked) { // Cardinality must return 0 Block = 0; Last = Nrec; } // endif blocked // This will erase the entire file strcpy(opmode, "w"); Tdbp->ResetSize(); break; } // endif // Selective delete, pass thru Bin = true; case MODE_UPDATE: if ((UseTemp = Tdbp->IsUsingTemp(g))) { strcpy(opmode, "r"); Bin = true; } else strcpy(opmode, "r+"); break; case MODE_INSERT: strcpy(opmode, "a+"); break; default: sprintf(g->Message, MSG(BAD_OPEN_MODE), mode); return true; } // endswitch Mode // For blocked I/O or for moving lines, open the table in binary strcat(opmode, (Blocked || Bin) ? "b" : "t"); // Now open the file stream PlugSetPath(filename, To_File, Tdbp->GetPath()); if (!(Stream = PlugOpenFile(g, filename, opmode))) { if (trace) htrc("%s\n", g->Message); return (mode == MODE_READ && errno == ENOENT) ? PushWarning(g, Tdbp) : true; } // endif Stream if (trace) htrc("File %s open Stream=%p mode=%s\n", filename, Stream, opmode); To_Fb = dbuserp->Openlist; // Keep track of File block /*********************************************************************/ /* Allocate the line buffer. For mode Delete a bigger buffer has to */ /* be allocated because is it also used to move lines into the file.*/ /*********************************************************************/ return AllocateBuffer(g); } // end of OpenTableFile
PQRYRES DBFColumns(PGLOBAL g, char *dp, const char *fn, bool info) { int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_INT, TYPE_INT, TYPE_SHORT}; XFLD fldtyp[] = {FLD_NAME, FLD_TYPE, FLD_TYPENAME, FLD_PREC, FLD_LENGTH, FLD_SCALE}; unsigned int length[] = {11, 6, 8, 10, 10, 6}; char buf[2], filename[_MAX_PATH]; int ncol = sizeof(buftyp) / sizeof(int); int rc, type, len, field, fields; bool bad; DBFHEADER mainhead; DESCRIPTOR thisfield; FILE *infile = NULL; PQRYRES qrp; PCOLRES crp; if (trace) htrc("DBFColumns: File %s\n", SVP(fn)); if (!info) { if (!fn) { strcpy(g->Message, MSG(MISSING_FNAME)); return NULL; } // endif fn /************************************************************************/ /* Open the input file. */ /************************************************************************/ PlugSetPath(filename, fn, dp); if (!(infile= global_fopen(g, MSGID_CANNOT_OPEN, filename, "rb"))) return NULL; /************************************************************************/ /* Get the first 32 bytes of the header. */ /************************************************************************/ if ((rc = dbfhead(g, infile, filename, &mainhead)) == RC_FX) { fclose(infile); return NULL; } // endif dbfhead /************************************************************************/ /* Allocate the structures used to refer to the result set. */ /************************************************************************/ fields = mainhead.Fields; } else fields = 0; qrp = PlgAllocResult(g, ncol, fields, IDS_COLUMNS + 3, buftyp, fldtyp, length, true, false); if (info || !qrp) { if (infile) fclose(infile); return qrp; } // endif info if (trace) { htrc("Structure of %s\n", filename); htrc("headlen=%hd reclen=%hd degree=%d\n", mainhead.Headlen, mainhead.Reclen, fields); htrc("flags(iem)=%d,%d,%d cp=%d\n", mainhead.Incompleteflag, mainhead.Encryptflag, mainhead.Mdxflag, mainhead.Language); htrc("%hd records, last changed %02d/%02d/%d\n", mainhead.Records, mainhead.Filedate[1], mainhead.Filedate[2], mainhead.Filedate[0] + (mainhead.Filedate[0] <= 30) ? 2000 : 1900); htrc("Field Type Offset Len Dec Set Mdx\n"); } // endif trace buf[1] = '\0'; /**************************************************************************/ /* Do it field by field. We are at byte 32 of file. */ /**************************************************************************/ for (field = 0; field < fields; field++) { bad = FALSE; if (fread(&thisfield, HEADLEN, 1, infile) != 1) { sprintf(g->Message, MSG(ERR_READING_REC), field+1, fn); goto err; } else len = thisfield.Length; if (trace) htrc("%-11s %c %6ld %3d %2d %3d %3d\n", thisfield.Name, thisfield.Type, thisfield.Offset, len, thisfield.Decimals, thisfield.Setfield, thisfield.Mdxfield); /************************************************************************/ /* Now get the results into blocks. */ /************************************************************************/ switch (thisfield.Type) { case 'C': // Characters case 'L': // Logical 'T' or 'F' type = TYPE_STRING; break; case 'N': type = (thisfield.Decimals) ? TYPE_DOUBLE : (len > 10) ? TYPE_BIGINT : TYPE_INT; break; case 'F': type = TYPE_DOUBLE; break; case 'D': type = TYPE_DATE; // Is this correct ??? break; default: if (!info) { sprintf(g->Message, MSG(BAD_DBF_TYPE), thisfield.Type); goto err; } // endif info type = TYPE_ERROR; bad = TRUE; } // endswitch Type crp = qrp->Colresp; // Column Name crp->Kdata->SetValue(thisfield.Name, field); crp = crp->Next; // Data Type crp->Kdata->SetValue((int)type, field); crp = crp->Next; // Type Name if (bad) { buf[0] = thisfield.Type; crp->Kdata->SetValue(buf, field); } else crp->Kdata->SetValue(GetTypeName(type), field); crp = crp->Next; // Precision crp->Kdata->SetValue((int)thisfield.Length, field); crp = crp->Next; // Length crp->Kdata->SetValue((int)thisfield.Length, field); crp = crp->Next; // Scale (precision) crp->Kdata->SetValue((int)thisfield.Decimals, field); } // endfor field qrp->Nblin = field; fclose(infile); #if 0 if (info) { /************************************************************************/ /* Prepare return message for dbfinfo command. */ /************************************************************************/ char buf[64]; sprintf(buf, "Ver=%02x ncol=%hu nlin=%u lrecl=%hu headlen=%hu date=%02d/%02d/%02d", mainhead.Version, fields, mainhead.Records, mainhead.Reclen, mainhead.Headlen, mainhead.Filedate[0], mainhead.Filedate[1], mainhead.Filedate[2]); strcat(g->Message, buf); } // endif info #endif // 0 /**************************************************************************/ /* Return the result pointer for use by GetData routines. */ /**************************************************************************/ return qrp; err: fclose(infile); return NULL; } // end of DBFColumns
PARRAY MakeValueArray(PGLOBAL g, PPARM pp) { int n, valtyp = 0; size_t len = 0; PARRAY par; PPARM parmp; if (!pp) return NULL; /*********************************************************************/ /* New version with values coming in a list. */ /*********************************************************************/ if ((valtyp = pp->Type) != TYPE_STRING) len = 1; if (trace) htrc("valtyp=%d len=%d\n", valtyp, len); /*********************************************************************/ /* Firstly check the list and count the number of values in it. */ /*********************************************************************/ for (n = 0, parmp = pp; parmp; n++, parmp = parmp->Next) if (parmp->Type != valtyp) { sprintf(g->Message, MSG(BAD_PARAM_TYPE), "MakeValueArray", parmp->Type); return NULL; } else if (valtyp == TYPE_STRING) len = MY_MAX(len, strlen((char*)parmp->Value)); /*********************************************************************/ /* Make an array object with one block of the proper size. */ /*********************************************************************/ par = new(g) ARRAY(g, valtyp, n, (int)len); if (par->GetResultType() == TYPE_ERROR) return NULL; // Memory allocation error in ARRAY /*********************************************************************/ /* All is right now, fill the array block. */ /*********************************************************************/ for (parmp = pp; parmp; parmp = parmp->Next) switch (valtyp) { case TYPE_STRING: par->AddValue(g, (PSZ)parmp->Value); break; case TYPE_SHORT: par->AddValue(g, *(short*)parmp->Value); break; case TYPE_INT: par->AddValue(g, *(int*)parmp->Value); break; case TYPE_DOUBLE: par->AddValue(g, *(double*)parmp->Value); break; case TYPE_PCHAR: par->AddValue(g, parmp->Value); break; case TYPE_VOID: // Integer stored inside pp->Value par->AddValue(g, parmp->Intval); break; } // endswitch valtyp /*********************************************************************/ /* Send back resulting array. */ /*********************************************************************/ return par; } // end of MakeValueArray
LPCSTR PlugSetPath(LPSTR pBuff, LPCSTR prefix, LPCSTR FileName, LPCSTR defpath) { char newname[_MAX_PATH]; char direc[_MAX_DIR], defdir[_MAX_DIR], tmpdir[_MAX_DIR]; char fname[_MAX_FNAME]; char ftype[_MAX_EXT]; #if defined(__WIN__) char drive[_MAX_DRIVE], defdrv[_MAX_DRIVE]; #else char *drive = NULL, *defdrv = NULL; #endif if (!strncmp(FileName, "//", 2) || !strncmp(FileName, "\\\\", 2)) { strcpy(pBuff, FileName); // Remote file return pBuff; } // endif if (PlugIsAbsolutePath(FileName)) { strcpy(pBuff, FileName); // FileName includes absolute path return pBuff; } // endif #if !defined(__WIN__) if (*FileName == '~') { if (_fullpath(pBuff, FileName, _MAX_PATH)) { if (trace > 1) htrc("pbuff='%s'\n", pBuff); return pBuff; } else return FileName; // Error, return unchanged name } // endif FileName #endif // !__WIN__ if (prefix && strcmp(prefix, ".") && !PlugIsAbsolutePath(defpath)) { char tmp[_MAX_PATH]; int len= snprintf(tmp, sizeof(tmp) - 1, "%s%s%s", prefix, defpath, FileName); memcpy(pBuff, tmp, (size_t) len); pBuff[len]= '\0'; return pBuff; } _splitpath(FileName, drive, direc, fname, ftype); if (defpath) { char c = defpath[strlen(defpath) - 1]; strcpy(tmpdir, defpath); if (c != '/' && c != '\\') strcat(tmpdir, "/"); } else strcpy(tmpdir, "./"); _splitpath(tmpdir, defdrv, defdir, NULL, NULL); if (trace > 1) { htrc("after _splitpath: FileName=%s\n", FileName); #if defined(__WIN__) htrc("drive=%s dir=%s fname=%s ext=%s\n", drive, direc, fname, ftype); htrc("defdrv=%s defdir=%s\n", defdrv, defdir); #else htrc("dir=%s fname=%s ext=%s\n", direc, fname, ftype); #endif } // endif trace if (drive && !*drive) strcpy(drive, defdrv); switch (*direc) { case '\0': strcpy(direc, defdir); break; case '\\': case '/': break; default: // This supposes that defdir ends with a SLASH strcpy(direc, strcat(defdir, direc)); } // endswitch _makepath(newname, drive, direc, fname, ftype); if (trace > 1) htrc("newname='%s'\n", newname); if (_fullpath(pBuff, newname, _MAX_PATH)) { if (trace > 1) htrc("pbuff='%s'\n", pBuff); return pBuff; } else return FileName; // Error, return unchanged name } // end of PlugSetPath
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
bool DBFFAM::OpenTableFile(PGLOBAL g) { char opmode[4], filename[_MAX_PATH]; //int ftype = Tdbp->GetFtype(); MODE mode = Tdbp->GetMode(); PDBUSER dbuserp = PlgGetUser(g); switch (mode) { case MODE_READ: strcpy(opmode, "rb"); break; case MODE_DELETE: if (!Tdbp->GetNext()) { // Store the number of deleted lines DelRows = -1; // Means all lines deleted // DelRows = Cardinality(g); no good because of soft deleted lines // This will erase the entire file strcpy(opmode, "w"); Tdbp->ResetSize(); Records = 0; break; } // endif // Selective delete, pass thru case MODE_UPDATE: UseTemp = Tdbp->IsUsingTemp(g); strcpy(opmode, (UseTemp) ? "rb" : "r+b"); break; case MODE_INSERT: // Must be in text mode to remove an eventual EOF character strcpy(opmode, "a+"); break; default: sprintf(g->Message, MSG(BAD_OPEN_MODE), mode); return true; } // endswitch Mode // Now open the file stream PlugSetPath(filename, To_File, Tdbp->GetPath()); if (!(Stream = PlugOpenFile(g, filename, opmode))) { #ifdef DEBTRACE htrc("%s\n", g->Message); #endif return (mode == MODE_READ && errno == ENOENT) ? PushWarning(g, Tdbp) : true; } // endif Stream #ifdef DEBTRACE htrc("File %s is open in mode %s\n", filename, opmode); #endif To_Fb = dbuserp->Openlist; // Keep track of File block /*********************************************************************/ /* Allocate the line buffer. For mode Delete a bigger buffer has to */ /* be allocated because is it also used to move lines into the file.*/ /*********************************************************************/ return AllocateBuffer(g); } // end of OpenTableFile
int DOSFAM::DeleteRecords(PGLOBAL g, int irc) { bool moved; int curpos = ftell(Stream); /*********************************************************************/ /* There is an alternative here: */ /* 1 - use a temporary file in which are copied all not deleted */ /* lines, at the end the original file will be deleted and */ /* the temporary file renamed to the original file name. */ /* 2 - directly move the not deleted lines inside the original */ /* file, and at the end erase all trailing records. */ /* This will be experimented, but method 1 must be used for Unix as */ /* the function needed to erase trailing records is not available. */ /*********************************************************************/ if (trace) htrc( "DOS DeleteDB: rc=%d UseTemp=%d curpos=%d Fpos=%d Tpos=%d Spos=%d\n", irc, UseTemp, curpos, Fpos, Tpos, Spos); if (irc != RC_OK) { /*******************************************************************/ /* EOF: position Fpos at the end-of-file position. */ /*******************************************************************/ fseek(Stream, 0, SEEK_END); Fpos = ftell(Stream); if (trace) htrc("Fpos placed at file end=%d\n", Fpos); } // endif irc if (Tpos == Spos) { /*******************************************************************/ /* First line to delete, Open temporary file. */ /*******************************************************************/ if (UseTemp) { if (OpenTempFile(g)) return RC_FX; } else { /*****************************************************************/ /* Move of eventual preceeding lines is not required here. */ /* Set the target file as being the source file itself. */ /* Set the future Tpos, and give Spos a value to block copying. */ /*****************************************************************/ T_Stream = Stream; Spos = Tpos = Fpos; } // endif UseTemp } // endif Tpos == Spos /*********************************************************************/ /* Move any intermediate lines. */ /*********************************************************************/ if (MoveIntermediateLines(g, &moved)) return RC_FX; if (irc == RC_OK) { /*******************************************************************/ /* Reposition the file pointer and set Spos. */ /*******************************************************************/ if (!UseTemp || moved) if (fseek(Stream, curpos, SEEK_SET)) { sprintf(g->Message, MSG(FSETPOS_ERROR), 0); return RC_FX; } // endif Spos = GetNextPos(); // New start position if (trace) htrc("after: Tpos=%d Spos=%d\n", Tpos, Spos); } else { /*******************************************************************/ /* Last call after EOF has been reached. */ /* The UseTemp case is treated in CloseTableFile. */ /*******************************************************************/ if (!UseTemp) { /*****************************************************************/ /* Because the chsize functionality is only accessible with a */ /* system call we must close the file and reopen it with the */ /* open function (_fopen for MS ??) this is still to be checked */ /* for compatibility with Text files and other OS's. */ /*****************************************************************/ char filename[_MAX_PATH]; int h; // File handle, return code PlugSetPath(filename, To_File, Tdbp->GetPath()); /*rc=*/ PlugCloseFile(g, To_Fb); if ((h= global_open(g, MSGID_OPEN_STRERROR, filename, O_WRONLY)) <= 0) return RC_FX; /*****************************************************************/ /* Remove extra records. */ /*****************************************************************/ #if defined(UNIX) if (ftruncate(h, (off_t)Tpos)) { sprintf(g->Message, MSG(TRUNCATE_ERROR), strerror(errno)); close(h); return RC_FX; } // endif #else if (chsize(h, Tpos)) { sprintf(g->Message, MSG(CHSIZE_ERROR), strerror(errno)); close(h); return RC_FX; } // endif #endif close(h); if (trace) htrc("done, h=%d irc=%d\n", h, irc); } // endif !UseTemp } // endif irc return RC_OK; // All is correct } // end of DeleteRecords
int DOSFAM::ReadBuffer(PGLOBAL g) { char *p; int rc; if (!Stream) return RC_EF; if (trace) htrc("ReadBuffer: Tdbp=%p To_Line=%p Placed=%d\n", Tdbp, Tdbp->To_Line, Placed); if (!Placed) { /*******************************************************************/ /* Record file position in case of UPDATE or DELETE. */ /*******************************************************************/ if (RecordPos(g)) return RC_FX; CurBlk = (int)Rows++; if (trace) htrc("ReadBuffer: CurBlk=%d\n", CurBlk); } else Placed = false; if (trace) htrc(" About to read: stream=%p To_Buf=%p Buflen=%d\n", Stream, To_Buf, Buflen); if (fgets(To_Buf, Buflen, Stream)) { p = To_Buf + strlen(To_Buf) - 1; if (trace) htrc(" Read: To_Buf=%p p=%c\n", To_Buf, To_Buf, p); #if defined(UNIX) if (true) { // Data files can be imported from Windows (having CRLF) #else if (Bin) { // Data file is read in binary so CRLF remains #endif if (*p == '\n' || *p == '\r') { // is this enough for Unix ??? *p = '\0'; // Eliminate ending CR or LF character if (p > To_Buf) { // is this enough for Unix ??? p--; if (*p == '\n' || *p == '\r') *p = '\0'; // Eliminate ending CR or LF character } // endif To_Buf } // endif p } else if (*p == '\n') *p = '\0'; // Eliminate ending new-line character if (trace) htrc(" To_Buf='%s'\n", To_Buf); strcpy(Tdbp->To_Line, To_Buf); num_read++; rc = RC_OK; } else if (feof(Stream)) { rc = RC_EF; } else { #if defined(UNIX) sprintf(g->Message, MSG(READ_ERROR), To_File, strerror(0)); #else sprintf(g->Message, MSG(READ_ERROR), To_File, _strerror(NULL)); #endif if (trace) htrc("%s\n", g->Message); rc = RC_FX; } // endif's fgets if (trace) htrc("ReadBuffer: rc=%d\n", rc); IsRead = true; return rc; } // end of ReadBuffer /***********************************************************************/ /* WriteBuffer: File write routine for DOS access method. */ /***********************************************************************/ int DOSFAM::WriteBuffer(PGLOBAL g) { char *crlf = "\n"; int curpos = 0; bool moved = true; // T_Stream is the temporary stream or the table file stream itself if (!T_Stream) if (UseTemp && Tdbp->Mode == MODE_UPDATE) { if (OpenTempFile(g)) return RC_FX; } else T_Stream = Stream; if (Tdbp->Mode == MODE_UPDATE) { /*******************************************************************/ /* Here we simply rewrite a record on itself. There are two cases */ /* were another method should be used, a/ when Update apply to */ /* the whole file, b/ when updating the last field of a variable */ /* length file. The method could be to rewrite a new file, then */ /* to erase the old one and rename the new updated file. */ /*******************************************************************/ curpos = ftell(Stream); if (trace) htrc("Last : %d cur: %d\n", Fpos, curpos); if (UseTemp) { /*****************************************************************/ /* We are using a temporary file. Before writing the updated */ /* record, we must eventually copy all the intermediate records */ /* that have not been updated. */ /*****************************************************************/ if (MoveIntermediateLines(g, &moved)) return RC_FX; Spos = curpos; // New start position } else // Update is directly written back into the file, // with this (fast) method, record size cannot change. if (fseek(Stream, Fpos, SEEK_SET)) { sprintf(g->Message, MSG(FSETPOS_ERROR), 0); return RC_FX; } // endif } // endif mode /*********************************************************************/ /* Prepare the write buffer. */ /*********************************************************************/ #if defined(WIN32) if (Bin) crlf = "\r\n"; #endif // WIN32 strcat(strcpy(To_Buf, Tdbp->To_Line), crlf); /*********************************************************************/ /* Now start the writing process. */ /*********************************************************************/ if ((fputs(To_Buf, T_Stream)) == EOF) { sprintf(g->Message, MSG(FPUTS_ERROR), strerror(errno)); return RC_FX; } // endif EOF if (Tdbp->Mode == MODE_UPDATE && moved) if (fseek(Stream, curpos, SEEK_SET)) { sprintf(g->Message, MSG(FSEEK_ERROR), strerror(errno)); return RC_FX; } // endif if (trace) htrc("write done\n"); return RC_OK; } // end of WriteBuffer
void XINCOL::WriteColumn(PGLOBAL g) { char *p; bool rc; PTDBXIN tdbp = (PTDBXIN)To_Tdb; if (trace > 1) htrc("XIN WriteColumn: col %s R%d coluse=%.4X status=%.4X\n", Name, tdbp->GetTdb_No(), ColUse, Status); /*********************************************************************/ /* Get the string representation of Value according to column type. */ /*********************************************************************/ if (Value != To_Val) Value->SetValue_pval(To_Val, false); // Convert the updated value p = Value->GetCharString(Valbuf); if (strlen(p) > (unsigned)Long) { sprintf(g->Message, MSG(VALUE_TOO_LONG), p, Name, Long); longjmp(g->jumper[g->jump_level], 31); } else if (Flag == 1) { if (tdbp->Mode == MODE_UPDATE) { strcpy(g->Message, MSG(NO_SEC_UPDATE)); longjmp(g->jumper[g->jump_level], 31); } else if (*p) { tdbp->Section = p; } else tdbp->Section = NULL; return; } else if (Flag == 2) { if (tdbp->Mode == MODE_UPDATE) { strcpy(g->Message, MSG(NO_KEY_UPDATE)); longjmp(g->jumper[g->jump_level], 31); } else if (*p) { tdbp->Keycur = p; } else tdbp->Keycur = NULL; return; } else if (!tdbp->Section || !tdbp->Keycur) { strcpy(g->Message, MSG(SEC_KEY_FIRST)); longjmp(g->jumper[g->jump_level], 31); } // endif's /*********************************************************************/ /* Updating must be done only when not in checking pass. */ /*********************************************************************/ if (Status) { rc = WritePrivateProfileString(tdbp->Section, tdbp->Keycur, p, tdbp->Ifile); if (!rc) { sprintf(g->Message, "Error %d writing to %s", GetLastError(), tdbp->Ifile); longjmp(g->jumper[g->jump_level], 31); } // endif rc } // endif Status } // end of WriteColumn
void DBFFAM::CloseTableFile(PGLOBAL g, bool abort) { int rc = RC_OK, wrc = RC_OK; MODE mode = Tdbp->GetMode(); Abort = abort; // Closing is True if last Write was in error if (mode == MODE_INSERT && CurNum && !Closing) { // Some more inserted lines remain to be written Rbuf = CurNum--; // Closing = true; wrc = WriteBuffer(g); } else if (mode == MODE_UPDATE || mode == MODE_DELETE) { if (Modif && !Closing) { // Last updated block remains to be written Closing = true; wrc = WriteModifiedBlock(g); } // endif Modif if (UseTemp && T_Stream && wrc == RC_OK) { if (!Abort) { // Copy any remaining lines bool b; Fpos = Tdbp->Cardinality(g); Abort = MoveIntermediateLines(g, &b) != RC_OK; } // endif Abort // Delete the old file and rename the new temp file. RenameTempFile(g); goto fin; } // endif UseTemp } // endif's mode if (Tdbp->GetMode() == MODE_INSERT) { int n = ftell(Stream) - Headlen; rc = PlugCloseFile(g, To_Fb); if (n >= 0 && !(n % Lrecl)) { n /= Lrecl; // New number of lines if (n > Records) { // Update the number of rows in the file header char filename[_MAX_PATH]; PlugSetPath(filename, To_File, Tdbp->GetPath()); if ((Stream= global_fopen(g, MSGID_OPEN_MODE_STRERROR, filename, "r+b"))) { fseek(Stream, 4, SEEK_SET); // Get header.Records position fwrite(&n, sizeof(int), 1, Stream); fclose(Stream); Stream= NULL; Records= n; // Update Records value } } // endif n } // endif n } else // Finally close the file rc = PlugCloseFile(g, To_Fb); fin: if (trace) htrc("DBF CloseTableFile: closing %s mode=%d wrc=%d rc=%d\n", To_File, mode, wrc, rc); Stream = NULL; // So we can know whether table is open } // end of CloseTableFile
bool TDBTBM::OpenDB(PGLOBAL g) { if (trace) htrc("TBM OpenDB: tdbp=%p tdb=R%d use=%d key=%p mode=%d\n", this, Tdb_No, Use, To_Key_Col, Mode); if (Use == USE_OPEN) { /*******************************************************************/ /* Table already open, replace it at its beginning. */ /*******************************************************************/ ResetDB(); return (Tdbp) ? Tdbp->OpenDB(g) : false; // Re-open fist table } // endif use #if 0 /*********************************************************************/ /* When GetMaxsize was called, To_CondFil was not set yet. */ /*********************************************************************/ if (To_CondFil && Tablist) { Tablist = NULL; Nbc = 0; } // endif To_CondFil #endif // 0 /*********************************************************************/ /* Make the table list. */ /*********************************************************************/ if (/*!Tablist &&*/ InitTableList(g)) return TRUE; /*********************************************************************/ /* Open all remote tables of the list. */ /*********************************************************************/ if (OpenTables(g)) return TRUE; /*********************************************************************/ /* Proceed with local tables. */ /*********************************************************************/ if ((CurTable = Tablist)) { Tdbp = (PTDBASE)CurTable->GetTo_Tdb(); // Tdbp->SetMode(Mode); // Check and initialize the subtable columns for (PCOL cp = Columns; cp; cp = cp->GetNext()) if (cp->GetAmType() == TYPE_AM_TABID) cp->COLBLK::Reset(); else if (((PPRXCOL)cp)->Init(g, NULL) && !Accept) return TRUE; if (trace) htrc("Opening subtable %s\n", Tdbp->GetName()); // Now we can safely open the table if (Tdbp->OpenDB(g)) return TRUE; } // endif *Tablist Use = USE_OPEN; return FALSE; } // end of OpenDB
int TDBCSV::ReadBuffer(PGLOBAL g) { char *p1, *p2, *p = NULL; int i, n, len, rc = Txfp->ReadBuffer(g); bool bad = false; if (trace > 1) htrc("CSV: Row is '%s' rc=%d\n", To_Line, rc); if (rc != RC_OK || !Fields) return rc; else p2 = To_Line; // Find the offsets and lengths of the columns for this row for (i = 0; i < Fields; i++) { if (!bad) { if (Qot && *p2 == Qot) { // Quoted field for (n = 0, p1 = ++p2; (p = strchr(p1, Qot)); p1 = p + 2) if (*(p + 1) == Qot) n++; // Doubled internal quotes else break; // Final quote if (p) { len = p++ - p2; // if (Sep != ' ') // for (; *p == ' '; p++) ; // Skip blanks if (*p != Sep && i != Fields - 1) { // Should be the separator if (CheckErr()) { sprintf(g->Message, MSG(MISSING_FIELD), i+1, Name, RowNumber(g)); return RC_FX; } else if (Accept) bad = true; else return RC_NF; } // endif p if (n) { int j, k; // Suppress the double of internal quotes for (j = k = 0; j < len; j++, k++) { if (p2[j] == Qot) j++; // skip first one p2[k] = p2[j]; } // endfor i, j len -= n; } // endif n } else if (CheckErr()) { sprintf(g->Message, MSG(BAD_QUOTE_FIELD), Name, i+1, RowNumber(g)); return RC_FX; } else if (Accept) { len = strlen(p2); bad = true; } else return RC_NF; } else if ((p = strchr(p2, Sep))) len = p - p2; else if (i == Fields - 1) len = strlen(p2); else if (Accept && Maxerr == 0) { len = strlen(p2); bad = true; } else if (CheckErr()) { sprintf(g->Message, MSG(MISSING_FIELD), i+1, Name, RowNumber(g)); return RC_FX; } else if (Accept) { len = strlen(p2); bad = true; } else return RC_NF; } else len = 0; Offset[i] = p2 - To_Line; if (Mode != MODE_UPDATE) Fldlen[i] = len; else if (len > Fldlen[i]) { sprintf(g->Message, MSG(FIELD_TOO_LONG), i+1, RowNumber(g)); return RC_FX; } else { strncpy(Field[i], p2, len); Field[i][len] = '\0'; } // endif Mode if (p) p2 = p + 1; } // endfor i return rc; } // end of ReadBuffer
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; case TYPE_PCHAR: blkp = new(g) PTRBLK(g, mp, nval); break; default: sprintf(g->Message, MSG(BAD_VALBLK_TYPE), type); return NULL; } // endswitch Type return (blkp->Init(g, check)) ? NULL : blkp; } // end of AllocValBlock
bool TDBCSV::PrepareWriting(PGLOBAL g) { char sep[2], qot[2]; int i, nlen, oldlen = strlen(To_Line); if (trace > 1) htrc("CSV WriteDB: R%d Mode=%d key=%p link=%p\n", Tdb_No, Mode, To_Key_Col, To_Link); // Before writing the line we must check its length if ((nlen = CheckWrite(g)) < 0) return true; // Before writing the line we must make it sep[0] = Sep; sep[1] = '\0'; qot[0] = Qot; qot[1] = '\0'; *To_Line = '\0'; for (i = 0; i < Fields; i++) { if (i) strcat(To_Line, sep); if (Field[i]) if (!strlen(Field[i])) { // Generally null fields are not quoted if (Quoted > 2) // Except if explicitely required strcat(strcat(To_Line, qot), qot); } else if (Qot && (strchr(Field[i], Sep) || *Field[i] == Qot || Quoted > 1 || (Quoted == 1 && !Fldtyp[i]))) if (strchr(Field[i], Qot)) { // Field contains quotes that must be doubled int j, k = strlen(To_Line), n = strlen(Field[i]); To_Line[k++] = Qot; for (j = 0; j < n; j++) { if (Field[i][j] == Qot) To_Line[k++] = Qot; To_Line[k++] = Field[i][j]; } // endfor j To_Line[k++] = Qot; To_Line[k] = '\0'; } else strcat(strcat(strcat(To_Line, qot), Field[i]), qot); else strcat(To_Line, Field[i]); } // endfor i #if defined(_DEBUG) assert ((unsigned)nlen == strlen(To_Line)); #endif if (Mode == MODE_UPDATE && nlen < oldlen && !((PDOSFAM)Txfp)->GetUseTemp()) { // In Update mode with no temp file, line length must not change To_Line[nlen] = Sep; for (nlen++; nlen < oldlen; nlen++) To_Line[nlen] = ' '; To_Line[nlen] = '\0'; } // endif if (trace > 1) htrc("Write: line is=%s", To_Line); return false; } // end of PrepareWriting
PQRYRES CSVColumns(PGLOBAL g, const char *fn, char sep, char q, int hdr, int mxr, bool info) { static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_INT, TYPE_INT, TYPE_SHORT}; static XFLD fldtyp[] = {FLD_NAME, FLD_TYPE, FLD_TYPENAME, FLD_PREC, FLD_LENGTH, FLD_SCALE}; static unsigned int length[] = {6, 6, 8, 10, 10, 6}; char *p, *colname[MAXCOL], dechar, filename[_MAX_PATH], buf[4096]; int i, imax, hmax, n, nerr, phase, blank, digit, dec, type; int ncol = sizeof(buftyp) / sizeof(int); int num_read = 0, num_max = 10000000; // Statistics int len[MAXCOL], typ[MAXCOL], prc[MAXCOL]; FILE *infile; PQRYRES qrp; PCOLRES crp; if (info) { imax = hmax = 0; length[0] = 128; goto skipit; } // endif info // num_max = atoi(p+1); // Max num of record to test #if defined(WIN32) if (sep == ',' || strnicmp(setlocale(LC_NUMERIC, NULL), "French", 6)) dechar = '.'; else dechar = ','; #else // !WIN32 dechar = '.'; #endif // !WIN32 if (trace) htrc("File %s sep=%c q=%c hdr=%d mxr=%d\n", SVP(fn), sep, q, hdr, mxr); if (!fn) { strcpy(g->Message, MSG(MISSING_FNAME)); return NULL; } // endif fn imax = hmax = nerr = 0; mxr = MY_MAX(0, mxr); for (i = 0; i < MAXCOL; i++) { colname[i] = NULL; len[i] = 0; typ[i] = TYPE_UNKNOWN; prc[i] = 0; } // endfor i /*********************************************************************/ /* Open the input file. */ /*********************************************************************/ PlugSetPath(filename, fn, PlgGetDataPath(g)); if (!(infile= global_fopen(g, MSGID_CANNOT_OPEN, filename, "r"))) return NULL; if (hdr) { /*******************************************************************/ /* Make the column names from the first line. */ /*******************************************************************/ phase = 0; if (fgets(buf, sizeof(buf), infile)) { n = strlen(buf) + 1; buf[n - 2] = '\0'; #if defined(UNIX) // The file can be imported from Windows if (buf[n - 3] == '\r') buf[n - 3] = 0; #endif // UNIX p = (char*)PlugSubAlloc(g, NULL, n); memcpy(p, buf, n); //skip leading blanks for (; *p == ' '; p++) ; if (q && *p == q) { // Header is quoted p++; phase = 1; } // endif q colname[0] = p; } else { sprintf(g->Message, MSG(FILE_IS_EMPTY), fn); goto err; } // endif's for (i = 1; *p; p++) if (phase == 1 && *p == q) { *p = '\0'; phase = 0; } else if (*p == sep && !phase) { *p = '\0'; //skip leading blanks for (; *(p+1) == ' '; p++) ; if (q && *(p+1) == q) { // Header is quoted p++; phase = 1; } // endif q colname[i++] = p + 1; } // endif sep num_read++; imax = hmax = i; for (i = 0; i < hmax; i++) length[0] = MY_MAX(length[0], strlen(colname[i])); } // endif hdr for (num_read++; num_read <= num_max; num_read++) { /*******************************************************************/ /* Now start the reading process. Read one line. */ /*******************************************************************/ if (fgets(buf, sizeof(buf), infile)) { n = strlen(buf); buf[n - 1] = '\0'; #if defined(UNIX) // The file can be imported from Windows if (buf[n - 2] == '\r') buf[n - 2] = 0; #endif // UNIX } else if (feof(infile)) { sprintf(g->Message, MSG(EOF_AFTER_LINE), num_read -1); break; } else { sprintf(g->Message, MSG(ERR_READING_REC), num_read, fn); goto err; } // endif's /*******************************************************************/ /* Make the test for field lengths. */ /*******************************************************************/ i = n = phase = blank = digit = dec = 0; for (p = buf; *p; p++) if (*p == sep) { if (phase != 1) { if (i == MAXCOL - 1) { sprintf(g->Message, MSG(TOO_MANY_FIELDS), num_read, fn); goto err; } // endif i if (n) { len[i] = MY_MAX(len[i], n); type = (digit || (dec && n == 1)) ? TYPE_STRING : (dec) ? TYPE_DOUBLE : TYPE_INT; typ[i] = MY_MIN(type, typ[i]); prc[i] = MY_MAX((typ[i] == TYPE_DOUBLE) ? (dec - 1) : 0, prc[i]); } // endif n i++; n = phase = blank = digit = dec = 0; } else // phase == 1 n++; } else if (*p == ' ') { if (phase < 2) n++; if (blank) digit = 1; } else if (*p == q) { if (phase == 0) { if (blank) if (++nerr > mxr) { sprintf(g->Message, MSG(MISPLACED_QUOTE), num_read); goto err; } else goto skip; n = 0; phase = digit = 1; } else if (phase == 1) { if (*(p+1) == q) { // This is currently not implemented for CSV tables // if (++nerr > mxr) { // sprintf(g->Message, MSG(QUOTE_IN_QUOTE), num_read); // goto err; // } else // goto skip; p++; n++; } else phase = 2; } else if (++nerr > mxr) { // phase == 2 sprintf(g->Message, MSG(MISPLACED_QUOTE), num_read); goto err; } else goto skip; } else { if (phase == 2) if (++nerr > mxr) { sprintf(g->Message, MSG(MISPLACED_QUOTE), num_read); goto err; } else goto skip; // isdigit cannot be used here because of debug assert if (!strchr("0123456789", *p)) { if (!digit && *p == dechar) dec = 1; // Decimal point found else if (blank || !(*p == '-' || *p == '+')) digit = 1; } else if (dec) dec++; // More decimals n++; blank = 1; } // endif's *p if (phase == 1) if (++nerr > mxr) { sprintf(g->Message, MSG(UNBALANCE_QUOTE), num_read); goto err; } else goto skip; if (n) { len[i] = MY_MAX(len[i], n); type = (digit || n == 0 || (dec && n == 1)) ? TYPE_STRING : (dec) ? TYPE_DOUBLE : TYPE_INT; typ[i] = MY_MIN(type, typ[i]); prc[i] = MY_MAX((typ[i] == TYPE_DOUBLE) ? (dec - 1) : 0, prc[i]); } // endif n imax = MY_MAX(imax, i+1); skip: ; // Skip erroneous line } // endfor num_read if (trace) { htrc("imax=%d Lengths:", imax); for (i = 0; i < imax; i++) htrc(" %d", len[i]); htrc("\n"); } // endif trace fclose(infile); skipit: if (trace) htrc("CSVColumns: imax=%d hmax=%d len=%d\n", imax, hmax, length[0]); /*********************************************************************/ /* Allocate the structures used to refer to the result set. */ /*********************************************************************/ qrp = PlgAllocResult(g, ncol, imax, IDS_COLUMNS + 3, buftyp, fldtyp, length, false, false); if (info || !qrp) return qrp; qrp->Nblin = imax; /*********************************************************************/ /* Now get the results into blocks. */ /*********************************************************************/ for (i = 0; i < imax; i++) { if (i >= hmax) { sprintf(buf, "COL%.3d", i+1); p = buf; } else p = colname[i]; if (typ[i] == TYPE_UNKNOWN) // Void column typ[i] = TYPE_STRING; crp = qrp->Colresp; // Column Name crp->Kdata->SetValue(p, i); crp = crp->Next; // Data Type crp->Kdata->SetValue(typ[i], i); crp = crp->Next; // Type Name crp->Kdata->SetValue(GetTypeName(typ[i]), i); crp = crp->Next; // Precision crp->Kdata->SetValue(len[i], i); crp = crp->Next; // Length crp->Kdata->SetValue(len[i], i); crp = crp->Next; // Scale (precision) crp->Kdata->SetValue(prc[i], i); } // endfor i /*********************************************************************/ /* Return the result pointer for use by GetData routines. */ /*********************************************************************/ return qrp; err: fclose(infile); return NULL; } // end of CSVCColumns
int BLKFAM::ReadBuffer(PGLOBAL g) { int i, n, rc = RC_OK; /*********************************************************************/ /* Sequential reading when Placed is not true. */ /*********************************************************************/ if (Placed) { Placed = false; } else if (++CurNum < Rbuf) { CurLine = NxtLine; // Get the position of the next line in the buffer while (*NxtLine++ != '\n') ; // Set caller line buffer n = NxtLine - CurLine - Ending; memcpy(Tdbp->GetLine(), CurLine, n); Tdbp->GetLine()[n] = '\0'; goto fin; } else if (Rbuf < Nrec && CurBlk != -1) { return RC_EF; } else { /*******************************************************************/ /* New block. */ /*******************************************************************/ CurNum = 0; if (++CurBlk >= Block) return RC_EF; } // endif's if (OldBlk == CurBlk) goto ok; // Block is already there // fseek is required only in non sequential reading if (CurBlk != OldBlk + 1) if (fseek(Stream, BlkPos[CurBlk], SEEK_SET)) { sprintf(g->Message, MSG(FSETPOS_ERROR), BlkPos[CurBlk]); return RC_FX; } // endif fseek // Calculate the length of block to read BlkLen = BlkPos[CurBlk + 1] - BlkPos[CurBlk]; if (trace) htrc("File position is now %d\n", ftell(Stream)); // Read the entire next block n = fread(To_Buf, 1, (size_t)BlkLen, Stream); if (n == BlkLen) { // ReadBlks++; num_read++; Rbuf = (CurBlk == Block - 1) ? Last : Nrec; ok: rc = RC_OK; // Get the position of the current line for (i = 0, CurLine = To_Buf; i < CurNum; i++) while (*CurLine++ != '\n') ; // What about Unix ??? // Now get the position of the next line for (NxtLine = CurLine; *NxtLine++ != '\n';) ; // Set caller line buffer n = NxtLine - CurLine - Ending; memcpy(Tdbp->GetLine(), CurLine, n); Tdbp->GetLine()[n] = '\0'; } else if (feof(Stream)) { rc = RC_EF; } else { #if defined(UNIX) sprintf(g->Message, MSG(READ_ERROR), To_File, strerror(errno)); #else sprintf(g->Message, MSG(READ_ERROR), To_File, _strerror(NULL)); #endif if (trace) htrc("%s\n", g->Message); return RC_FX; } // endelse OldBlk = CurBlk; // Last block actually read IsRead = true; // Is read indeed fin: // Store the current record file position for Delete and Update Fpos = BlkPos[CurBlk] + CurLine - To_Buf; return rc; } // end of ReadBuffer