bool TDBPIVOT::FindDefaultColumns(PGLOBAL g) { PCOLDEF cdp; PTABDEF defp = Tdbp->GetDef(); if (!Fncol) { for (cdp = defp->GetCols(); cdp; cdp = cdp->GetNext()) if (!Picol || stricmp(Picol, cdp->GetName())) Fncol = cdp->GetName(); if (!Fncol) { strcpy(g->Message, MSG(NO_DEF_FNCCOL)); return true; } // endif Fncol } // endif Fncol if (!Picol) { // Find default Picol as the last one not equal to Fncol for (cdp = defp->GetCols(); cdp; cdp = cdp->GetNext()) if (stricmp(Fncol, cdp->GetName())) Picol = cdp->GetName(); if (!Picol) { strcpy(g->Message, MSG(NO_DEF_PIVOTCOL)); return true; } // endif Picol } // endif Picol return false; } // end of FindDefaultColumns
int VCTDEF::MakeFnPattern(char *fpat) { char pat[8]; #if !defined(UNIX) char drive[_MAX_DRIVE]; #else char *drive = NULL; #endif char direc[_MAX_DIR]; char fname[_MAX_FNAME]; char ftype[_MAX_EXT]; // File extention int n, m, ncol = 0; PCOLDEF cdp; for (cdp = To_Cols; cdp; cdp = cdp->GetNext()) ncol++; for (n = 1, m = ncol; m /= 10; n++) ; sprintf(pat, "%%0%dd", n); _splitpath(Fn, drive, direc, fname, ftype); strcat(fname, pat); _makepath(fpat, drive, direc, fname, ftype); PlugSetPath(fpat, fpat, GetPath()); return ncol; } // end of MakeFnPattern
bool CSVDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) { char buf[8]; // Double check correctness of offset values if (Catfunc == FNC_NO) for (PCOLDEF cdp = To_Cols; cdp; cdp = cdp->GetNext()) if (cdp->GetOffset() < 1 && !cdp->IsSpecial()) { strcpy(g->Message, MSG(BAD_OFFSET_VAL)); return true; } // endif Offset // Call DOSDEF DefineAM with am=CSV so FMT is not confused with FIX if (DOSDEF::DefineAM(g, "CSV", poff)) return true; GetCharCatInfo("Separator", ",", buf, sizeof(buf)); Sep = (strlen(buf) == 2 && buf[0] == '\\' && buf[1] == 't') ? '\t' : *buf; Quoted = GetIntCatInfo("Quoted", -1); GetCharCatInfo("Qchar", "", buf, sizeof(buf)); Qot = *buf; if (Qot && Quoted < 0) Quoted = 0; else if (!Qot && Quoted >= 0) Qot = '"'; Fmtd = (!Sep || (am && (*am == 'F' || *am == 'f'))); Header = (GetIntCatInfo("Header", 0) != 0); Maxerr = GetIntCatInfo("Maxerr", 0); Accept = (GetIntCatInfo("Accept", 0) != 0); return false; } // end of DefineAM
bool VCTDEF::Erase(char *filename) { bool rc = false; if (Split) { char fpat[_MAX_PATH]; int i; PCOLDEF cdp; MakeFnPattern(fpat); for (i = 1, cdp = To_Cols; cdp; i++, cdp = cdp->GetNext()) { sprintf(filename, fpat, i); //#if defined(WIN32) // rc |= !DeleteFile(filename); //#else // UNIX rc |= remove(filename); //#endif // UNIX } // endfor cdp } else { rc = DOSDEF::Erase(filename); if (Estimate && Header == 2) { PlugSetPath(filename, Fn, GetPath()); strcat(PlugRemoveType(filename, filename), ".blk"); rc |= remove(filename); } // endif Header } // endif Split return rc; // Return true if error } // end of Erase
bool TDBASE::IsSpecial(PSZ name) { for (PCOLDEF cdp = To_Def->GetCols(); cdp; cdp = cdp->GetNext()) if (!stricmp(cdp->GetName(), name) && (cdp->Flags & U_SPECIAL)) return true; // Special column to ignore while inserting return false; // Not found or not special or not inserting } // end of IsSpecial
int TDBCSV::EstimatedLength(PGLOBAL g) { int n = 0; PCOLDEF cdp; if (trace) htrc("EstimatedLength: Fields=%d Columns=%p\n", Fields, Columns); for (cdp = To_Def->GetCols(); cdp; cdp = cdp->GetNext()) if (!cdp->IsSpecial() && !cdp->IsVirtual()) // A true column n++; return --n; // Number of separators if all fields are null } // end of Estimated Length
PCOL TDBASE::ColDB(PGLOBAL g, PSZ name, int num) { int i; PCOLDEF cdp; PCOL cp, colp = NULL, cprec = NULL; if (trace) htrc("ColDB: am=%d colname=%s tabname=%s num=%d\n", GetAmType(), SVP(name), Name, num); for (cdp = To_Def->GetCols(), i = 1; cdp; cdp = cdp->GetNext(), i++) if ((!name && !num) || (name && !stricmp(cdp->GetName(), name)) || num == i) { /*****************************************************************/ /* Check for existence of desired column. */ /* Also find where to insert the new block. */ /*****************************************************************/ for (cp = Columns; cp; cp = cp->GetNext()) if ((num && cp->GetIndex() == i) || (name && !stricmp(cp->GetName(), name))) break; // Found else if (cp->GetIndex() < i) cprec = cp; if (trace) htrc("cdp(%d).Name=%s cp=%p\n", i, cdp->GetName(), cp); /*****************************************************************/ /* Now take care of Column Description Block. */ /*****************************************************************/ if (cp) colp = cp; else if (!(cdp->Flags & U_SPECIAL)) colp = MakeCol(g, cdp, cprec, i); else if (Mode != MODE_INSERT) colp = InsertSpcBlk(g, cdp); if (trace) htrc("colp=%p\n", colp); if (name || num) break; else if (colp && !colp->IsSpecial()) cprec = colp; } // endif Name return (colp); } // end of ColDB
bool TDBPIVOT::GetSourceTable(PGLOBAL g) { if (Tdbp) return false; // Already done if (!Tabsrc && Tabname) { // Get the table description block of this table if (!(Tdbp = GetSubTable(g, ((PPIVOTDEF)To_Def)->Tablep, true))) return true; if (!GBdone) { char *colist; PCOLDEF cdp; if (FindDefaultColumns(g)) return true; // Locate the suballocated colist (size is not known yet) *(colist = (char*)PlugSubAlloc(g, NULL, 0)) = 0; // Make the column list for (cdp = To_Def->GetCols(); cdp; cdp = cdp->GetNext()) if (!cdp->GetOffset()) strcat(strcat(colist, cdp->GetName()), ", "); // Add the Pivot column at the end of the list strcat(colist, Picol); // Now we know how much was suballocated PlugSubAlloc(g, NULL, strlen(colist) + 1); // Locate the source string (size is not known yet) Tabsrc = (char*)PlugSubAlloc(g, NULL, 0); // Start making the definition strcat(strcat(strcpy(Tabsrc, "SELECT "), colist), ", "); // Make it suitable for Pivot by doing the group by strcat(strcat(Tabsrc, Function), "("); strcat(strcat(strcat(Tabsrc, Fncol), ") "), Fncol); strcat(strcat(Tabsrc, " FROM "), Tabname); strcat(strcat(Tabsrc, " GROUP BY "), colist); if (Tdbp->IsView()) // Until MariaDB bug is fixed strcat(strcat(Tabsrc, " ORDER BY "), colist); // Now we know how much was suballocated PlugSubAlloc(g, NULL, strlen(Tabsrc) + 1); } // endif !GBdone } else if (!Tabsrc) { strcpy(g->Message, MSG(SRC_TABLE_UNDEF)); return true; } // endif if (Tabsrc) { // Get the new table description block of this source table PTABLE tablep = new(g) XTAB("whatever", Tabsrc); tablep->SetQualifier(Database); if (!(Tdbp = GetSubTable(g, tablep, true))) return true; } // endif Tabsrc return false; } // end of GetSourceTable
bool TDBCSV::SkipHeader(PGLOBAL g) { int len = GetFileLength(g); bool rc = false; #if defined(_DEBUG) if (len < 0) return true; #endif // _DEBUG if (Header) { if (Mode == MODE_INSERT) { if (!len) { // New file, the header line must be constructed and written int i, n = 0; int hlen = 0; bool q = Qot && Quoted > 0; PCOLDEF cdp; // Estimate the length of the header list for (cdp = To_Def->GetCols(); cdp; cdp = cdp->GetNext()) { hlen += (1 + strlen(cdp->GetName())); hlen += ((q) ? 2 : 0); n++; // Calculate the number of columns } // endfor cdp if (hlen > Lrecl) { sprintf(g->Message, MSG(LRECL_TOO_SMALL), hlen); return true; } // endif hlen // File is empty, write a header record memset(To_Line, 0, Lrecl); // The column order in the file is given by the offset value for (i = 1; i <= n; i++) for (cdp = To_Def->GetCols(); cdp; cdp = cdp->GetNext()) if (cdp->GetOffset() == i) { if (q) To_Line[strlen(To_Line)] = Qot; strcat(To_Line, cdp->GetName()); if (q) To_Line[strlen(To_Line)] = Qot; if (i < n) To_Line[strlen(To_Line)] = Sep; } // endif Offset rc = (Txfp->WriteBuffer(g) == RC_FX); } // endif !FileLength } else if (Mode == MODE_DELETE) { if (len) rc = (Txfp->SkipRecord(g, true) == RC_FX); } else if (len) // !Insert && !Delete rc = (Txfp->SkipRecord(g, false) == RC_FX || Txfp->RecordPos(g)); } // endif Header return rc; } // end of SkipHeader
bool TDBCSV::OpenDB(PGLOBAL g) { bool rc = false; PCOLDEF cdp; PDOSDEF tdp = (PDOSDEF)To_Def; if (Use != USE_OPEN && (Columns || Mode == MODE_UPDATE)) { // Allocate the storage used to read (or write) records int i, len; PCSVCOL colp; if (!Fields) // May have been set in TABFMT::OpenDB if (Mode != MODE_UPDATE && Mode != MODE_INSERT) { for (colp = (PCSVCOL)Columns; colp; colp = (PCSVCOL)colp->Next) if (!colp->IsSpecial() && !colp->IsVirtual()) Fields = MY_MAX(Fields, (int)colp->Fldnum); if (Columns) Fields++; // Fldnum was 0 based } else for (cdp = tdp->GetCols(); cdp; cdp = cdp->GetNext()) if (!cdp->IsVirtual()) Fields++; Offset = (int*)PlugSubAlloc(g, NULL, sizeof(int) * Fields); Fldlen = (int*)PlugSubAlloc(g, NULL, sizeof(int) * Fields); if (Mode == MODE_INSERT || Mode == MODE_UPDATE) { Field = (PSZ*)PlugSubAlloc(g, NULL, sizeof(PSZ) * Fields); Fldtyp = (bool*)PlugSubAlloc(g, NULL, sizeof(bool) * Fields); } // endif Mode for (i = 0; i < Fields; i++) { Offset[i] = 0; Fldlen[i] = 0; if (Field) { Field[i] = NULL; Fldtyp[i] = false; } // endif Field } // endfor i if (Field) // Prepare writing fields if (Mode != MODE_UPDATE) { for (colp = (PCSVCOL)Columns; colp; colp = (PCSVCOL)colp->Next) if (!colp->IsSpecial() && !colp->IsVirtual()) { i = colp->Fldnum; len = colp->GetLength(); Field[i] = (PSZ)PlugSubAlloc(g, NULL, len + 1); Field[i][len] = '\0'; Fldlen[i] = len; Fldtyp[i] = IsTypeNum(colp->GetResultType()); } // endif colp } else // MODE_UPDATE for (cdp = tdp->GetCols(); cdp; cdp = cdp->GetNext()) if (!cdp->IsVirtual()) { i = cdp->GetOffset() - 1; len = cdp->GetLength(); Field[i] = (PSZ)PlugSubAlloc(g, NULL, len + 1); Field[i][len] = '\0'; Fldlen[i] = len; Fldtyp[i] = IsTypeNum(cdp->GetType()); } // endif cdp } // endif Use if (Header) { // Check that the Lrecl is at least equal to the header line length int headlen = 0; PCOLDEF cdp; PDOSDEF tdp = (PDOSDEF)To_Def; for (cdp = tdp->GetCols(); cdp; cdp = cdp->GetNext()) headlen += strlen(cdp->GetName()) + 3; // 3 if names are quoted if (headlen > Lrecl) { Lrecl = headlen; Txfp->Lrecl = headlen; } // endif headlen } // endif Header Nerr = 0; rc = TDBDOS::OpenDB(g); if (!rc && Mode == MODE_UPDATE && To_Kindex) // Because KINDEX::Init is executed in mode READ, we must restore // the Fldlen array that was modified when reading the table file. for (cdp = tdp->GetCols(); cdp; cdp = cdp->GetNext()) Fldlen[cdp->GetOffset() - 1] = cdp->GetLength(); return rc; } // end of OpenDB
bool TDBFMT::OpenDB(PGLOBAL g) { Linenum = 0; if (Mode == MODE_INSERT || Mode == MODE_UPDATE) { sprintf(g->Message, MSG(FMT_WRITE_NIY), "FMT"); return true; // NIY } // endif Mode if (Use != USE_OPEN && Columns) { // Make the formats used to read records PSZ pfm; int i, n; PCSVCOL colp; PCOLDEF cdp; PDOSDEF tdp = (PDOSDEF)To_Def; for (colp = (PCSVCOL)Columns; colp; colp = (PCSVCOL)colp->Next) if (!colp->IsSpecial() && !colp->IsVirtual()) // a true column Fields = MY_MAX(Fields, (int)colp->Fldnum); if (Columns) Fields++; // Fldnum was 0 based To_Fld = PlugSubAlloc(g, NULL, Lrecl + 1); FldFormat = (PSZ*)PlugSubAlloc(g, NULL, sizeof(PSZ) * Fields); memset(FldFormat, 0, sizeof(PSZ) * Fields); FmtTest = (int*)PlugSubAlloc(g, NULL, sizeof(int) * Fields); memset(FmtTest, 0, sizeof(int) * Fields); // Get the column formats for (cdp = tdp->GetCols(); cdp; cdp = cdp->GetNext()) if (!cdp->IsVirtual() && (i = cdp->GetOffset() - 1) < Fields) { if (!(pfm = cdp->GetFmt())) { sprintf(g->Message, MSG(NO_FLD_FORMAT), i + 1, Name); return true; } // endif pfm // Roughly check the Fmt format if ((n = strlen(pfm) - 2) < 4) { sprintf(g->Message, MSG(BAD_FLD_FORMAT), i + 1, Name); return true; } // endif n FldFormat[i] = (PSZ)PlugSubAlloc(g, NULL, n + 5); strcpy(FldFormat[i], pfm); if (!strcmp(pfm + n, "%m")) { // This is a field that can be missing. Flag it so it can // be handled with special processing. FldFormat[i][n+1] = 'n'; // To have sscanf normal processing FmtTest[i] = 2; } else if (i+1 < Fields && strcmp(pfm + n, "%n")) { // There are trailing characters after the field contents // add a marker for the next field start position. strcat(FldFormat[i], "%n"); FmtTest[i] = 1; } // endif's } // endif i } // endif Use return TDBCSV::OpenDB(g); } // end of OpenDB
bool DBFFAM::AllocateBuffer(PGLOBAL g) { char c; int rc; MODE mode = Tdbp->GetMode(); Buflen = Blksize; To_Buf = (char*)PlugSubAlloc(g, NULL, Buflen); if (mode == MODE_INSERT) { #if defined(WIN32) /************************************************************************/ /* Now we can revert to binary mode in particular because the eventual */ /* writing of a new header must be done in binary mode to avoid */ /* translating 0A bytes (LF) into 0D0A (CRLF) by Windows in text mode. */ /************************************************************************/ if (_setmode(_fileno(Stream), _O_BINARY) == -1) { sprintf(g->Message, MSG(BIN_MODE_FAIL), strerror(errno)); return true; } // endif setmode #endif // WIN32 /************************************************************************/ /* If this is a new file, the header must be generated. */ /************************************************************************/ int len = GetFileLength(g); if (!len) { // Make the header for this DBF table file struct tm *datm; int hlen, n = 0; ushort reclen = 1; time_t t; DBFHEADER *header; DESCRIPTOR *descp; PCOLDEF cdp; PDOSDEF tdp = (PDOSDEF)Tdbp->GetDef(); // Count the number of columns for (cdp = tdp->GetCols(); cdp; cdp = cdp->GetNext()) if (!(cdp->Flags & U_SPECIAL)) { reclen += cdp->GetLong(); n++; } // endif Flags if (Lrecl != reclen) { sprintf(g->Message, MSG(BAD_LRECL), Lrecl, reclen); return true; } // endif Lrecl hlen = HEADLEN * (n + 1) + 2; header = (DBFHEADER*)PlugSubAlloc(g, NULL, hlen); memset(header, 0, hlen); header->Version = DBFTYPE; t = time(NULL) - (time_t)DTVAL::GetShift(); datm = gmtime(&t); header->Filedate[0] = datm->tm_year - 100; header->Filedate[1] = datm->tm_mon + 1; header->Filedate[2] = datm->tm_mday; header->Headlen = (ushort)hlen; header->Reclen = (ushort)reclen; descp = (DESCRIPTOR*)header; // Currently only standard Xbase types are supported for (cdp = tdp->GetCols(); cdp; cdp = cdp->GetNext()) if (!(cdp->Flags & U_SPECIAL)) { descp++; switch ((c = *GetFormatType(cdp->GetType()))) { case 'S': // Short integer case 'L': // Large (big) integer case 'T': // Tiny integer c = 'N'; // Numeric case 'N': // Numeric (integer) case 'F': // Float (double) descp->Decimals = (uchar)cdp->F.Prec; case 'C': // Char case 'D': // Date break; default: // Should never happen sprintf(g->Message, "Unsupported DBF type %c for column %s", c, cdp->GetName()); return true; } // endswitch c strncpy(descp->Name, cdp->GetName(), 11); descp->Type = c; descp->Length = (uchar)cdp->GetLong(); } // endif Flags *(char*)(++descp) = EOH; // Now write the header if (fwrite(header, 1, hlen, Stream) != (unsigned)hlen) { sprintf(g->Message, MSG(FWRITE_ERROR), strerror(errno)); return true; } // endif fwrite Records = 0; Headlen = hlen; } else if (len < 0) return true; // Error in GetFileLength /************************************************************************/ /* For Insert the buffer must be prepared. */ /************************************************************************/ memset(To_Buf, ' ', Buflen); Rbuf = Nrec; // To be used by WriteDB } else if (UseTemp) { // Allocate a separate buffer so block reading can be kept Dbflen = Nrec; DelBuf = PlugSubAlloc(g, NULL, Blksize); } // endif's if (!Headlen) { /************************************************************************/ /* Here is a good place to process the DBF file header */ /************************************************************************/ DBFHEADER header; if ((rc = dbfhead(g, Stream, Tdbp->GetFile(g), &header)) == RC_OK) { if (Lrecl != (int)header.Reclen) { sprintf(g->Message, MSG(BAD_LRECL), Lrecl, header.Reclen); return true; } // endif Lrecl Records = (int)header.Records; Headlen = (int)header.Headlen; } else if (rc == RC_NF) { Records = 0; Headlen = 0; } else // RC_FX return true; // Error in dbfhead } // endif Headlen /**************************************************************************/ /* Position the file at the begining of the data. */ /**************************************************************************/ if (Tdbp->GetMode() == MODE_INSERT) rc = fseek(Stream, 0, SEEK_END); else rc = fseek(Stream, Headlen, SEEK_SET); if (rc) { sprintf(g->Message, MSG(BAD_DBF_FILE), Tdbp->GetFile(g)); return true; } // endif fseek return false; } // end of AllocateBuffer