diff options
Diffstat (limited to 'storage/connect/tabmul.cpp')
-rw-r--r-- | storage/connect/tabmul.cpp | 1616 |
1 files changed, 1616 insertions, 0 deletions
diff --git a/storage/connect/tabmul.cpp b/storage/connect/tabmul.cpp new file mode 100644 index 00000000..d0b7b316 --- /dev/null +++ b/storage/connect/tabmul.cpp @@ -0,0 +1,1616 @@ +/************* TabMul C++ Program Source Code File (.CPP) **************/ +/* PROGRAM NAME: TABMUL */ +/* ------------- */ +/* Version 1.9 */ +/* */ +/* COPYRIGHT: */ +/* ---------- */ +/* (C) Copyright to PlugDB Software Development 2003 - 2017 */ +/* Author: Olivier BERTRAND */ +/* */ +/* WHAT THIS PROGRAM DOES: */ +/* ----------------------- */ +/* This program are the TDBMUL class DB routines. */ +/* */ +/* WHAT YOU NEED TO COMPILE THIS PROGRAM: */ +/* -------------------------------------- */ +/* */ +/* REQUIRED FILES: */ +/* --------------- */ +/* TABMUL.CPP - Source code */ +/* PLGDBSEM.H - DB application declaration file */ +/* TABDOS.H - TABDOS classes declaration file */ +/* TABMUL.H - TABFIX classes declaration file */ +/* GLOBAL.H - Global declaration file */ +/* */ +/* REQUIRED LIBRARIES: */ +/* ------------------- */ +/* Large model C library */ +/* */ +/* REQUIRED PROGRAMS: */ +/* ------------------ */ +/* IBM, Borland, GNU or Microsoft C++ Compiler and Linker */ +/* */ +/***********************************************************************/ + +/***********************************************************************/ +/* Include relevant section of system dependant header files. */ +/***********************************************************************/ +#include "my_global.h" +#if defined(_WIN32) +#include <stdlib.h> +#include <stdio.h> +#if defined(__BORLANDC__) +#define __MFC_COMPAT__ // To define min/max as macro +#endif +//#include <windows.h> +#if defined(PATHMATCHSPEC) +#include "Shlwapi.h" +//using namespace std; +#pragma comment(lib,"shlwapi.lib") +#endif // PATHMATCHSPEC +#else +#if defined(UNIX) +#include <fnmatch.h> +#include <errno.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include "osutil.h" +#else +//#include <io.h> +#endif +//#include <fcntl.h> +#endif + +/***********************************************************************/ +/* Include application header files: */ +/***********************************************************************/ +#include "global.h" // global declarations +#include "plgdbsem.h" // DB application declarations +#include "reldef.h" // DB definition declares +#include "filamtxt.h" +#include "tabdos.h" // TDBDOS and DOSCOL class dcls +#include "tabmul.h" // TDBMUL and MULCOL classes dcls + +/* ------------------------- Class TDBMUL ---------------------------- */ + +/***********************************************************************/ +/* TABMUL constructors. */ +/***********************************************************************/ +TDBMUL::TDBMUL(PTDB tdbp) : TDBASE(tdbp->GetDef()) + { + Tdbp = tdbp; + Filenames = NULL; + Rows = 0; + Mul = tdbp->GetDef()->GetMultiple(); + NumFiles = 0; + iFile = 0; + } // end of TDBMUL standard constructor + +TDBMUL::TDBMUL(PTDBMUL tdbp) : TDBASE(tdbp) + { + Tdbp = tdbp->Tdbp; + Filenames = tdbp->Filenames; + Rows = tdbp->Rows; + Mul = tdbp->Mul; + NumFiles = tdbp->NumFiles; + iFile = tdbp->iFile; + } // end of TDBMUL copy constructor + +// Method +PTDB TDBMUL::Clone(PTABS t) + { + PTDBMUL tp; + PGLOBAL g = t->G; // Is this really useful ??? + + tp = new(g) TDBMUL(this); + tp->Tdbp = Tdbp->Clone(t); + tp->Columns = tp->Tdbp->GetColumns(); + return tp; + } // end of Clone + +PTDB TDBMUL::Duplicate(PGLOBAL g) + { + PTDBMUL tmup = new(g) TDBMUL(this); + + tmup->Tdbp = Tdbp->Duplicate(g); + return tmup; + } // end of Duplicate + +/***********************************************************************/ +/* Initializes the table filename list. */ +/* Note: tables created by concatenating the file components without */ +/* specifying the LRECL value (that should be restricted to _MAX_PATH)*/ +/* have a LRECL that is the sum of the lengths of all components. */ +/* This is why we use a big filename array to take care of that. */ +/***********************************************************************/ +bool TDBMUL::InitFileNames(PGLOBAL g) + { +#define PFNZ 4096 +#define FNSZ (_MAX_DRIVE+_MAX_DIR+_MAX_FNAME+_MAX_EXT) + PTDBDIR dirp; + PSZ pfn[PFNZ]; + PSZ filename; + int rc, n = 0; + + if (trace(1)) + htrc("in InitFileName: fn[]=%d\n", FNSZ); + + filename = (char*)PlugSubAlloc(g, NULL, FNSZ); + + // The sub table may need to refer to the Table original block + Tdbp->SetTable(To_Table); // Was not set at construction + + PlugSetPath(filename, Tdbp->GetFile(g), Tdbp->GetPath()); + + if (trace(1)) + htrc("InitFileName: fn='%s'\n", filename); + + if (Mul != 2) { + /*******************************************************************/ + /* To_File is a multiple name with special characters */ + /*******************************************************************/ + if (Mul == 1) + dirp = new(g) TDBDIR(PlugDup(g, filename)); + else // Mul == 3 (Subdir) + dirp = new(g) TDBSDR(PlugDup(g, filename)); + + if (dirp->OpenDB(g)) + return true; + + if (trace(1) && Mul == 3) { + int nf = ((PTDBSDR)dirp)->FindInDir(g); + htrc("Number of files = %d\n", nf); + } // endif trace + + while (true) + if ((rc = dirp->ReadDB(g)) == RC_OK) { +#if defined(_WIN32) + strcat(strcpy(filename, dirp->Drive), dirp->Direc); +#else // !_WIN32 + strcpy(filename, dirp->Direc); +#endif // !_WIN32 + strcat(strcat(filename, dirp->Fname), dirp->Ftype); + pfn[n++] = PlugDup(g, filename); + } else + break; + + dirp->CloseDB(g); + + if (rc == RC_FX) + return true; + + } else { + /*******************************************************************/ + /* To_File is the name of a file containing the file name list */ + /*******************************************************************/ + char *p; + FILE *stream; + + if (!(stream= global_fopen(g, MSGID_OPEN_MODE_STRERROR, filename, "r"))) + return true; + + while (n < PFNZ) { + if (!fgets(filename, FNSZ, stream)) { + fclose(stream); + break; + } // endif fgets + + p = filename + strlen(filename) - 1; + + + // Data files can have CRLF + if (*p == '\n' || *p == '\r') { + p--; // Eliminate ending CR or LF character + + if (p >= filename) + if (*p == '\n' || *p == '\r') + p--; // Eliminate ending CR or LF character + + } // endif p + // Trim rightmost blanks + for (; p >= filename && *p == ' '; p--) ; + + *(++p) = '\0'; + + // Suballocate the file name + pfn[n++] = PlugDup(g, filename); + } // endfor n + + } // endif Mul + + if (n) { + Filenames = (char**)PlugSubAlloc(g, NULL, n * sizeof(char*)); + + for (int i = 0; i < n; i++) + Filenames[i] = pfn[i]; + + } else { + Filenames = (char**)PlugSubAlloc(g, NULL, sizeof(char*)); + Filenames[0] = NULL; + } // endif n + + NumFiles = n; + return false; + } // end of InitFileNames + +/***********************************************************************/ +/* The table column list is the sub-table column list. */ +/***********************************************************************/ +PCOL TDBMUL::ColDB(PGLOBAL g, PSZ name, int num) + { + PCOL cp; + + /*********************************************************************/ + /* Because special columns are directly added to the MUL block, */ + /* make sure that the sub-table has the same column list, before */ + /* and after the call to the ColDB function. */ + /*********************************************************************/ + Tdbp->SetColumns(Columns); + cp = Tdbp->ColDB(g, name, num); + Columns = Tdbp->GetColumns(); + return cp; +} // end of ColDB + +/***********************************************************************/ +/* MUL GetProgMax: get the max value for progress information. */ +/***********************************************************************/ +int TDBMUL::GetProgMax(PGLOBAL g) + { + if (!Filenames && InitFileNames(g)) + return -1; + + return NumFiles; // This is a temporary setting + } // end of GetProgMax + +/***********************************************************************/ +/* MUL GetProgCur: get the current value for progress information. */ +/***********************************************************************/ +int TDBMUL::GetProgCur(void) + { + return iFile; // This is a temporary setting + } // end of GetProgMax + +/***********************************************************************/ +/* MUL Cardinality: returns table cardinality in number of rows. */ +/* This function can be called with a null argument to test the */ +/* availability of Cardinality implementation (1 yes, 0 no). */ +/* Can be used on Multiple FIX table only. */ +/***********************************************************************/ +int TDBMUL::Cardinality(PGLOBAL g) + { + if (!g) + return Tdbp->Cardinality(g); + + if (!Filenames && InitFileNames(g)) + return -1; + + int n, card = 0; + + for (int i = 0; i < NumFiles; i++) { + Tdbp->SetFile(g, Filenames[i]); + Tdbp->ResetSize(); + + if ((n = Tdbp->Cardinality(g)) < 0) { +// strcpy(g->Message, MSG(BAD_CARDINALITY)); + return -1; + } // endif n + + card += n; + } // endfor i + + return card; + } // end of Cardinality + +/***********************************************************************/ +/* Sum up the sizes of all sub-tables. */ +/***********************************************************************/ +int TDBMUL::GetMaxSize(PGLOBAL g) + { + if (MaxSize < 0) { + int i; + int mxsz; + + if (trace(1)) + htrc("TDBMUL::GetMaxSize: Filenames=%p\n", Filenames); + + if (!Filenames && InitFileNames(g)) + return -1; + + if (Use == USE_OPEN) { + strcpy(g->Message, MSG(MAXSIZE_ERROR)); + return -1; + } else + MaxSize = 0; + + for (i = 0; i < NumFiles; i++) { + Tdbp->SetFile(g, Filenames[i]); + Tdbp->ResetSize(); + + if ((mxsz = Tdbp->GetMaxSize(g)) < 0) { + MaxSize = -1; + return mxsz; + } // endif mxsz + + MaxSize += mxsz; + } // endfor i + + } // endif MaxSize + + return MaxSize; + } // end of GetMaxSize + +/***********************************************************************/ +/* Reset read/write position values. */ +/***********************************************************************/ +void TDBMUL::ResetDB(void) + { + for (PCOL colp = Columns; colp; colp = colp->GetNext()) + if (colp->GetAmType() == TYPE_AM_FILID) + colp->COLBLK::Reset(); + + Tdbp->ResetDB(); + } // end of ResetDB + +/***********************************************************************/ +/* Returns RowId if b is false or Rownum if b is true. */ +/***********************************************************************/ +int TDBMUL::RowNumber(PGLOBAL g, bool b) + { + return ((b) ? 0 : Rows) + + ((iFile < NumFiles) ? Tdbp->RowNumber(g, b) : 1); + } // end of RowNumber + +/***********************************************************************/ +/* MUL Access Method opening routine. */ +/* Open first file, other will be opened sequencially when reading. */ +/***********************************************************************/ +bool TDBMUL::OpenDB(PGLOBAL g) + { + if (trace(1)) + htrc("MUL 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. */ + /*******************************************************************/ + if (Filenames[iFile = 0]) { + Tdbp->CloseDB(g); + Tdbp->SetUse(USE_READY); + Tdbp->SetFile(g, Filenames[iFile = 0]); + Tdbp->ResetSize(); + Rows = 0; + ResetDB(); + return Tdbp->OpenDB(g); // Re-open with new file name + } else + return false; + + } // endif use + + /*********************************************************************/ + /* We need to calculate MaxSize before opening the query. */ + /*********************************************************************/ + if (GetMaxSize(g) < 0) + return true; + + /*********************************************************************/ + /* Open the first table file of the list. */ + /*********************************************************************/ +//if (!Filenames && InitFileNames(g)) // was done in GetMaxSize +// return true; + + if (Filenames[iFile = 0]) { + Tdbp->SetFile(g, Filenames[0]); + Tdbp->SetMode(Mode); + Tdbp->ResetDB(); + Tdbp->ResetSize(); + + if (Tdbp->OpenDB(g)) + return true; + + } // endif *Filenames + + Use = USE_OPEN; + return false; + } // end of OpenDB + +/***********************************************************************/ +/* ReadDB: Data Base read routine for MUL access method. */ +/***********************************************************************/ +int TDBMUL::ReadDB(PGLOBAL g) + { + int rc; + + if (NumFiles == 0) + return RC_EF; + else if (To_Kindex) { + /*******************************************************************/ + /* Reading is by an index table. */ + /*******************************************************************/ + strcpy(g->Message, MSG(NO_INDEX_READ)); + rc = RC_FX; + } else { + /*******************************************************************/ + /* Now start the reading process. */ + /*******************************************************************/ + retry: + rc = Tdbp->ReadDB(g); + + if (rc == RC_EF) { + if (Tdbp->GetDef()->GetPseudo() & 1) + // Total number of rows met so far + Rows += Tdbp->RowNumber(g) - 1; + + if (++iFile < NumFiles) { + /***************************************************************/ + /* Continue reading from next table file. */ + /***************************************************************/ + Tdbp->CloseDB(g); + Tdbp->SetUse(USE_READY); + Tdbp->SetFile(g, Filenames[iFile]); + Tdbp->ResetSize(); + ResetDB(); + + if (Tdbp->OpenDB(g)) // Re-open with new file name + return RC_FX; + + goto retry; + } // endif iFile + + } else if (rc == RC_FX) + strcat(strcat(strcat(g->Message, " ("), Tdbp->GetFile(g)), ")"); + + } // endif To_Kindex + + return rc; + } // end of ReadDB + +/***********************************************************************/ +/* Data Base write routine for MUL access method. */ +/***********************************************************************/ +int TDBMUL::WriteDB(PGLOBAL g) + { + return Tdbp->WriteDB(g); +// strcpy(g->Message, MSG(TABMUL_READONLY)); +// return RC_FX; // NIY + } // end of WriteDB + +/***********************************************************************/ +/* Data Base delete line routine for MUL access method. */ +/***********************************************************************/ +int TDBMUL::DeleteDB(PGLOBAL g, int) + { + // When implementing DELETE_MODE InitFileNames must be updated to + // eliminate CRLF under Windows if the file is read in binary. + strcpy(g->Message, MSG(TABMUL_READONLY)); + return RC_FX; // NIY + } // end of DeleteDB + +/***********************************************************************/ +/* Data Base close routine for MUL access method. */ +/***********************************************************************/ +void TDBMUL::CloseDB(PGLOBAL g) + { + if (NumFiles > 0) { + Tdbp->CloseDB(g); + iFile = NumFiles; + } // endif NumFiles + + } // end of CloseDB + +#if 0 +/* ------------------------- Class TDBMSD ---------------------------- */ + + // Method +PTDB TDBMSD::Clone(PTABS t) +{ + PTDBMSD tp; + PGLOBAL g = t->G; // Is this really useful ??? + + tp = new(g) TDBMSD(this); + tp->Tdbp = Tdbp->Clone(t); + tp->Columns = tp->Tdbp->GetColumns(); + return tp; +} // end of Clone + +PTDB TDBMSD::Duplicate(PGLOBAL g) +{ + PTDBMSD tmup = new(g) TDBMSD(this); + + tmup->Tdbp = Tdbp->Duplicate(g); + return tmup; +} // end of Duplicate + +/***********************************************************************/ +/* Initializes the table filename list. */ +/* Note: tables created by concatenating the file components without */ +/* specifying the LRECL value (that should be restricted to _MAX_PATH)*/ +/* have a LRECL that is the sum of the lengths of all components. */ +/* This is why we use a big filename array to take care of that. */ +/***********************************************************************/ +bool TDBMSD::InitFileNames(PGLOBAL g) +{ +#define PFNZ 4096 +#define FNSZ (_MAX_DRIVE+_MAX_DIR+_MAX_FNAME+_MAX_EXT) + PTDBSDR dirp; + PSZ pfn[PFNZ]; + PSZ filename; + int rc, n = 0; + + if (trace(1)) + htrc("in InitFileName: fn[]=%d\n", FNSZ); + + filename = (char*)PlugSubAlloc(g, NULL, FNSZ); + + // The sub table may need to refer to the Table original block + Tdbp->SetTable(To_Table); // Was not set at construction + + PlugSetPath(filename, Tdbp->GetFile(g), Tdbp->GetPath()); + + if (trace(1)) + htrc("InitFileName: fn='%s'\n", filename); + + dirp = new(g) TDBSDR(filename); + + if (dirp->OpenDB(g)) + return true; + + while (true) + if ((rc = dirp->ReadDB(g)) == RC_OK) { +#if defined(_WIN32) + strcat(strcpy(filename, dirp->Drive), dirp->Direc); +#else // !_WIN32 + strcpy(filename, dirp->Direc); +#endif // !_WIN32 + strcat(strcat(filename, dirp->Fname), dirp->Ftype); + pfn[n++] = PlugDup(g, filename); + } else + break; + + if (rc == RC_FX) + return true; + + if (n) { + Filenames = (char**)PlugSubAlloc(g, NULL, n * sizeof(char*)); + + for (int i = 0; i < n; i++) + Filenames[i] = pfn[i]; + + } else { + Filenames = (char**)PlugSubAlloc(g, NULL, sizeof(char*)); + Filenames[0] = NULL; + } // endif n + + NumFiles = n; + return false; +} // end of InitFileNames +#endif // 0 + + /* --------------------------- Class DIRDEF -------------------------- */ + +/***********************************************************************/ +/* DefineAM: define specific AM block values from XDB file. */ +/***********************************************************************/ +bool DIRDEF::DefineAM(PGLOBAL g, LPCSTR, int) + { + Desc = Fn = GetStringCatInfo(g, "Filename", NULL); + Incl = GetBoolCatInfo("Subdir", false); + Huge = GetBoolCatInfo("Huge", false); + Nodir = GetBoolCatInfo("Nodir", true); + return false; + } // end of DefineAM + +/***********************************************************************/ +/* GetTable: makes a new Table Description Block. */ +/***********************************************************************/ +PTDB DIRDEF::GetTable(PGLOBAL g, MODE) + { +#if 0 + if (Huge) + return new(g) TDBDHR(this); // Not implemented yet + else +#endif + if (Incl) + return new(g) TDBSDR(this); // Including sub-directory files + else + return new(g) TDBDIR(this); // Not Including sub-directory files + + } // end of GetTable + +/* ------------------------- Class TDBDIR ---------------------------- */ + +/***********************************************************************/ +/* TABDIR constructors. */ +/***********************************************************************/ +void TDBDIR::Init(void) +{ + iFile = 0; +#if defined(_WIN32) + Dvalp = NULL; + memset(&FileData, 0, sizeof(_finddata_t)); + hSearch = INVALID_HANDLE_VALUE; + *Drive = '\0'; +#else // !_WIN32 + memset(&Fileinfo, 0, sizeof(struct stat)); + Entry = NULL; + Dir = NULL; + Done = false; + *Pattern = '\0'; +#endif // !_WIN32 + *Fpath = '\0'; + *Direc = '\0'; + *Fname = '\0'; + *Ftype = '\0'; +} // end of Init + +TDBDIR::TDBDIR(PDIRDEF tdp) : TDBASE(tdp) +{ + To_File = tdp->Fn; + Nodir = tdp->Nodir; + Init(); +} // end of TDBDIR standard constructor + +TDBDIR::TDBDIR(PSZ fpat) : TDBASE((PTABDEF)NULL) +{ + To_File = fpat; + Nodir = true; + Init(); +} // end of TDBDIR constructor + +/***********************************************************************/ +/* Initialize/get the components of the search file pattern. */ +/***********************************************************************/ +char* TDBDIR::Path(PGLOBAL g) + { + (void) PlgGetCatalog(g); // XXX Should be removed? + PTABDEF defp = (PTABDEF)To_Def; + +#if defined(_WIN32) + if (!*Drive) { + PlugSetPath(Fpath, To_File, defp ? defp->GetPath() : NULL); + _splitpath(Fpath, Drive, Direc, Fname, Ftype); + } else + _makepath(Fpath, Drive, Direc, Fname, Ftype); // Usefull for TDBSDR + + return Fpath; +#else // !_WIN32 + if (!Done) { + PlugSetPath(Fpath, To_File, defp ? defp->GetPath() : NULL); + _splitpath(Fpath, NULL, Direc, Fname, Ftype); + strcat(strcpy(Pattern, Fname), Ftype); + Done = true; + } // endif Done + + return Pattern; +#endif // !_WIN32 + } // end of Path + +/***********************************************************************/ +/* Allocate DIR column description block. */ +/***********************************************************************/ +PCOL TDBDIR::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n) + { + return new(g) DIRCOL(cdp, this, cprec, n); + } // end of MakeCol + +/***********************************************************************/ +/* DIR GetMaxSize: returns the number of retrieved files. */ +/***********************************************************************/ +int TDBDIR::GetMaxSize(PGLOBAL g) + { + if (MaxSize < 0) { + int n = -1; +#if defined(_WIN32) + int rc; + // Start searching files in the target directory. + hSearch = FindFirstFile(Path(g), &FileData); + + if (hSearch == INVALID_HANDLE_VALUE) { + rc = GetLastError(); + + if (rc != ERROR_FILE_NOT_FOUND) { + char buf[512]; + + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, GetLastError(), 0, (LPTSTR)&buf, sizeof(buf), NULL); + snprintf(g->Message, sizeof(g->Message), MSG(BAD_FILE_HANDLE), buf); + return -1; + } // endif rc + + return 0; + } // endif hSearch + + while (true) { + if (!(FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) + n++; + + if (!FindNextFile(hSearch, &FileData)) { + rc = GetLastError(); + + if (rc != ERROR_NO_MORE_FILES) { + snprintf(g->Message, sizeof(g->Message), MSG(NEXT_FILE_ERROR), rc); + FindClose(hSearch); + return -1; + } // endif rc + + break; + } // endif Next + + } // endwhile + + // Close the search handle. + FindClose(hSearch); +#else // !_WIN32 + Path(g); + + // Start searching files in the target directory. + if (!(Dir = opendir(Direc))) { + snprintf(g->Message, sizeof(g->Message), MSG(BAD_DIRECTORY), Direc, strerror(errno)); + return -1; + } // endif dir + + while ((Entry = readdir(Dir))) { + strcat(strcpy(Fpath, Direc), Entry->d_name); + + if (lstat(Fpath, &Fileinfo) < 0) { + snprintf(g->Message, sizeof(g->Message), "%s: %s", Fpath, strerror(errno)); + return -1; + } else if (S_ISREG(Fileinfo.st_mode)) + // Test whether the file name matches the table name filter + if (!fnmatch(Pattern, Entry->d_name, 0)) + n++; // We have a match + + } // endwhile Entry + + // Close the DIR handle. + closedir(Dir); +#endif // !_WIN32 + MaxSize = n; + } // endif MaxSize + + return MaxSize; + } // end of GetMaxSize + +/***********************************************************************/ +/* DIR Access Method opening routine. */ +/* Open first file, other will be opened sequencially when reading. */ +/***********************************************************************/ +bool TDBDIR::OpenDB(PGLOBAL g) + { + if (trace(1)) + htrc("DIR OpenDB: tdbp=%p tdb=R%d use=%d mode=%d\n", + this, Tdb_No, Use, Mode); + + if (Use == USE_OPEN) { + /*******************************************************************/ + /* Table already open, reopen it. */ + /*******************************************************************/ + CloseDB(g); + SetUse(USE_READY); + } // endif use + + Use = USE_OPEN; +#if !defined(_WIN32) + Path(g); // Be sure it is done + Dir = NULL; // For ReadDB +#endif // !_WIN32 + return false; + } // end of OpenDB + +/***********************************************************************/ +/* Data Base read routine for DIR access method. */ +/***********************************************************************/ +int TDBDIR::ReadDB(PGLOBAL g) + { + int rc = RC_OK; + +#if defined(_WIN32) + do { + if (hSearch == INVALID_HANDLE_VALUE) { + /*****************************************************************/ + /* Start searching files in the target directory. The use of */ + /* the Path function is required when called from TDBSDR. */ + /*****************************************************************/ + hSearch = FindFirstFile(Path(g), &FileData); + + if (hSearch == INVALID_HANDLE_VALUE) { + rc = RC_EF; + break; + } else + iFile++; + + } else { + if (!FindNextFile(hSearch, &FileData)) { + // Restore file name and type pattern + _splitpath(To_File, NULL, NULL, Fname, Ftype); + rc = RC_EF; + break; + } else + iFile++; + + } // endif hSearch + + } while (Nodir && FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY); + + if (rc == RC_OK) + _splitpath(FileData.cFileName, NULL, NULL, Fname, Ftype); + +#else // !Win32 + rc = RC_NF; + + if (!Dir) + // Start searching files in the target directory. + if (!(Dir = opendir(Direc))) { + snprintf(g->Message, sizeof(g->Message), MSG(BAD_DIRECTORY), Direc, strerror(errno)); + rc = RC_FX; + } // endif dir + + while (rc == RC_NF) + if ((Entry = readdir(Dir))) { + // We need the Fileinfo structure to get info about the file + strcat(strcpy(Fpath, Direc), Entry->d_name); + + if (lstat(Fpath, &Fileinfo) < 0) { + snprintf(g->Message, sizeof(g->Message), "%s: %s", Fpath, strerror(errno)); + rc = RC_FX; + } else if (S_ISREG(Fileinfo.st_mode)) + // Test whether the file name matches the table name filter + if (!fnmatch(Pattern, Entry->d_name, 0)) { + iFile++; // We have a match + _splitpath(Entry->d_name, NULL, NULL, Fname, Ftype); + rc = RC_OK; + } // endif fnmatch + + } else { + // Restore file name and type pattern + _splitpath(To_File, NULL, NULL, Fname, Ftype); + rc = RC_EF; + } // endif Entry + +#endif // !_WIN32 + + return rc; + } // end of ReadDB + +/***********************************************************************/ +/* Data Base write routine for DIR access method. */ +/***********************************************************************/ +int TDBDIR::WriteDB(PGLOBAL g) + { + strcpy(g->Message, MSG(TABDIR_READONLY)); + return RC_FX; // NIY + } // end of WriteDB + +/***********************************************************************/ +/* Data Base delete line routine for DIR access method. */ +/***********************************************************************/ +int TDBDIR::DeleteDB(PGLOBAL g, int) + { + strcpy(g->Message, MSG(TABDIR_READONLY)); + return RC_FX; // NIY + } // end of DeleteDB + +/***********************************************************************/ +/* Data Base close routine for MUL access method. */ +/***********************************************************************/ +void TDBDIR::CloseDB(PGLOBAL) + { +#if defined(_WIN32) + // Close the search handle. + FindClose(hSearch); + hSearch = INVALID_HANDLE_VALUE; +#else // !_WIN32 + // Close the DIR handle + if (Dir) { + closedir(Dir); + Dir = NULL; + } // endif dir +#endif // !_WIN32 + iFile = 0; + } // end of CloseDB + +// ------------------------ DIRCOL functions ---------------------------- + +/***********************************************************************/ +/* DIRCOL public constructor. */ +/***********************************************************************/ +DIRCOL::DIRCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ) + : COLBLK(cdp, tdbp, i) + { + if (cprec) { + Next = cprec->GetNext(); + cprec->SetNext(this); + } else { + Next = tdbp->GetColumns(); + tdbp->SetColumns(this); + } // endif cprec + + // Set additional DIR access method information for column. + Tdbp = (PTDBDIR)tdbp; + N = cdp->GetOffset(); + } // end of DIRCOL constructor + +/***********************************************************************/ +/* DIRCOL constructor used for copying columns. */ +/* tdbp is the pointer to the new table descriptor. */ +/***********************************************************************/ +DIRCOL::DIRCOL(DIRCOL *col1, PTDB tdbp) : COLBLK(col1, tdbp) + { + Tdbp = (PTDBDIR)tdbp; + N = col1->N; + } // end of DIRCOL copy constructor + +#if defined(_WIN32) +/***********************************************************************/ +/* Retrieve time information from FileData. */ +/***********************************************************************/ +void DIRCOL::SetTimeValue(PGLOBAL g, FILETIME& ftime) +{ + char tsp[24]; + SYSTEMTIME stp; + + if (FileTimeToSystemTime(&ftime, &stp)) { + sprintf(tsp, "%04d-%02d-%02d %02d:%02d:%02d", + stp.wYear, stp.wMonth, stp.wDay, stp.wHour, stp.wMinute, stp.wSecond); + + if (Value->GetType() != TYPE_STRING) { + if (!Tdbp->Dvalp) + Tdbp->Dvalp = AllocateValue(g, TYPE_DATE, 20, 0, false, + "YYYY-MM-DD hh:mm:ss"); + + Tdbp->Dvalp->SetValue_psz(tsp); + Value->SetValue_pval(Tdbp->Dvalp); + } else + Value->SetValue_psz(tsp); + + } else + Value->Reset(); + +} // end of SetTimeValue +#endif // _WIN32 + +/***********************************************************************/ +/* ReadColumn: what this routine does is to access the information */ +/* corresponding to this column and convert it to buffer type. */ +/***********************************************************************/ +void DIRCOL::ReadColumn(PGLOBAL g) + { + if (trace(1)) + htrc("DIR ReadColumn: col %s R%d use=%.4X status=%.4X type=%d N=%d\n", + Name, Tdbp->GetTdb_No(), ColUse, Status, Buf_Type, N); + + /*********************************************************************/ + /* Retrieve the information corresponding to the column number. */ + /*********************************************************************/ + switch (N) { +#if defined(_WIN32) + case 0: Value->SetValue_psz(Tdbp->Drive); break; +#endif // _WIN32 + case 1: Value->SetValue_psz(Tdbp->Direc); break; + case 2: Value->SetValue_psz(Tdbp->Fname); break; + case 3: Value->SetValue_psz(Tdbp->Ftype); break; +#if defined(_WIN32) + case 4: Value->SetValue((int)Tdbp->FileData.dwFileAttributes); break; + case 5: Value->SetValue((int)Tdbp->FileData.nFileSizeLow); break; + case 6: SetTimeValue(g, Tdbp->FileData.ftLastWriteTime); break; + case 7: SetTimeValue(g, Tdbp->FileData.ftCreationTime); break; + case 8: SetTimeValue(g, Tdbp->FileData.ftLastAccessTime); break; +#else // !_WIN32 + case 4: Value->SetValue((int)Tdbp->Fileinfo.st_mode); break; + case 5: Value->SetValue((int)Tdbp->Fileinfo.st_size); break; + case 6: Value->SetValue((int)Tdbp->Fileinfo.st_mtime); break; + case 7: Value->SetValue((int)Tdbp->Fileinfo.st_ctime); break; + case 8: Value->SetValue((int)Tdbp->Fileinfo.st_atime); break; + case 9: Value->SetValue((int)Tdbp->Fileinfo.st_uid); break; + case 10: Value->SetValue((int)Tdbp->Fileinfo.st_gid); break; +#endif // !_WIN32 + default: + snprintf(g->Message, sizeof(g->Message), MSG(INV_DIRCOL_OFST), N); + throw GetAmType(); + } // endswitch N + + } // end of ReadColumn + +/* ------------------------- Class TDBSDR ---------------------------- */ + +/***********************************************************************/ +/* SDR GetMaxSize: returns the number of retrieved files. */ +/***********************************************************************/ +int TDBSDR::GetMaxSize(PGLOBAL g) + { + if (MaxSize < 0) { + Path(g); + MaxSize = FindInDir(g); + } // endif MaxSize + + return MaxSize; + } // end of GetMaxSize + +/***********************************************************************/ +/* SDR FindInDir: returns the number of retrieved files. */ +/***********************************************************************/ +int TDBSDR::FindInDir(PGLOBAL g) + { + int n = 0; + size_t m = strlen(Direc); + + // Start searching files in the target directory. +#if defined(_WIN32) + int rc; + HANDLE h; + +#if defined(PATHMATCHSPEC) + if (!*Drive) + Path(g); + + _makepath(Fpath, Drive, Direc, "*", "*"); + + h = FindFirstFile(Fpath, &FileData); + + if (h == INVALID_HANDLE_VALUE) { + rc = GetLastError(); + + if (rc != ERROR_FILE_NOT_FOUND) { + char buf[512]; + + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, GetLastError(), 0, (LPTSTR)&buf, sizeof(buf), NULL); + snprintf(g->Message, sizeof(g->Message), MSG(BAD_FILE_HANDLE), buf); + return -1; + } // endif rc + + return 0; + } // endif h + + while (true) { + if ((FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && + *FileData.cFileName != '.') { + // Look in the name sub-directory + strcat(strcat(Direc, FileData.cFileName), "/"); + n += FindInDir(g); + Direc[m] = '\0'; // Restore path + } else if (PathMatchSpec(FileData.cFileName, Fpath)) + n++; + + if (!FindNextFile(h, &FileData)) { + rc = GetLastError(); + + if (rc != ERROR_NO_MORE_FILES) { + snprintf(g->Message, sizeof(g->Message), MSG(NEXT_FILE_ERROR), rc); + FindClose(h); + return -1; + } // endif rc + + break; + } // endif Next + + } // endwhile +#else // !PATHMATCHSPEC + h = FindFirstFile(Path(g), &FileData); + + if (h == INVALID_HANDLE_VALUE) { + rc = GetLastError(); + + if (rc != ERROR_FILE_NOT_FOUND) { + char buf[512]; + + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, GetLastError(), 0, (LPTSTR)&buf, sizeof(buf), NULL); + snprintf(g->Message, sizeof(g->Message), MSG(BAD_FILE_HANDLE), buf); + return -1; + } // endif rc + + return 0; + } // endif hSearch + + while (true) { + n++; + + if (!FindNextFile(h, &FileData)) { + rc = GetLastError(); + + if (rc != ERROR_NO_MORE_FILES) { + snprintf(g->Message, sizeof(g->Message), MSG(NEXT_FILE_ERROR), rc); + FindClose(h); + return -1; + } // endif rc + + break; + } // endif Next + + } // endwhile + + // Now search files in sub-directories. + _makepath(Fpath, Drive, Direc, "*", "."); + h = FindFirstFile(Fpath, &FileData); + + if (h != INVALID_HANDLE_VALUE) { + while (true) { + if ((FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && + *FileData.cFileName != '.') { + // Look in the name sub-directory + strcat(strcat(Direc, FileData.cFileName), "/"); + n += FindInDir(g); + Direc[m] = '\0'; // Restore path + } // endif SUBDIR + + if (!FindNextFile(h, &FileData)) + break; + + } // endwhile + + } // endif h +#endif // !PATHMATCHSPEC + + // Close the search handle. + FindClose(h); +#else // !_WIN32 + int k; + DIR *dir = opendir(Direc); + + if (!dir) { + snprintf(g->Message, sizeof(g->Message), MSG(BAD_DIRECTORY), Direc, strerror(errno)); + return -1; + } // endif dir + + while ((Entry = readdir(dir))) { + strcat(strcpy(Fpath, Direc), Entry->d_name); + + if (lstat(Fpath, &Fileinfo) < 0) { + snprintf(g->Message, sizeof(g->Message), "%s: %s", Fpath, strerror(errno)); + return -1; + } else if (S_ISDIR(Fileinfo.st_mode) && *Entry->d_name != '.') { + // Look in the name sub-directory + strcat(strcat(Direc, Entry->d_name), "/"); + + if ((k= FindInDir(g)) < 0) + return k; + else + n += k; + + Direc[m] = '\0'; // Restore path + } else if (S_ISREG(Fileinfo.st_mode)) + // Test whether the file name matches the table name filter + if (!fnmatch(Pattern, Entry->d_name, 0)) + n++; // We have a match + + } // endwhile readdir + + // Close the DIR handle. + closedir(dir); +#endif // !_WIN32 + + return n; + } // end of FindInDir + +/***********************************************************************/ +/* DIR Access Method opening routine. */ +/* Open first file, other will be opened sequencially when reading. */ +/***********************************************************************/ +bool TDBSDR::OpenDB(PGLOBAL g) + { + if (!Sub) { + Path(g); + Sub = (PSUBDIR)PlugSubAlloc(g, NULL, sizeof(SUBDIR)); + Sub->Next = NULL; + Sub->Prev = NULL; +#if defined(_WIN32) + Sub->H = INVALID_HANDLE_VALUE; + Sub->Len = strlen(Direc); +#else // !_WIN32 + Sub->D = NULL; + Sub->Len = 0; +#endif // !_WIN32 + } // endif To_Sub + + return TDBDIR::OpenDB(g); + } // end of OpenDB + +/***********************************************************************/ +/* Data Base read routine for SDR access method. */ +/***********************************************************************/ +int TDBSDR::ReadDB(PGLOBAL g) + { + int rc; + +#if defined(_WIN32) + again: + rc = TDBDIR::ReadDB(g); + + if (rc == RC_EF) { + // Are there more files in sub-directories + retry: + do { + if (Sub->H == INVALID_HANDLE_VALUE) { +// _makepath(Fpath, Drive, Direc, "*", "."); why was this made? + _makepath(Fpath, Drive, Direc, "*", NULL); + Sub->H = FindFirstFile(Fpath, &FileData); + } else if (!FindNextFile(Sub->H, &FileData)) { + FindClose(Sub->H); + Sub->H = INVALID_HANDLE_VALUE; + *FileData.cFileName= '\0'; + break; + } // endif findnext + + } while(!(FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) || + (*FileData.cFileName == '.' && + (!FileData.cFileName[1] || FileData.cFileName[1] == '.'))); + + if (Sub->H == INVALID_HANDLE_VALUE) { + // No more sub-directories. Are we in a sub-directory? + if (!Sub->Prev) + return rc; // No, all is finished + + // here we must continue in the parent directory + Sub = Sub->Prev; + goto retry; + } else { + // Search next sub-directory + Direc[Sub->Len] = '\0'; + + if (!Sub->Next) { + PSUBDIR sup; + + sup = (PSUBDIR)PlugSubAlloc(g, NULL, sizeof(SUBDIR)); + sup->Next = NULL; + sup->Prev = Sub; + sup->H = INVALID_HANDLE_VALUE; + Sub->Next = sup; + } // endif Next + + Sub = Sub->Next; + strcat(strcat(Direc, FileData.cFileName), "/"); + Sub->Len = strlen(Direc); + + // Reset Hsearch used by TDBDIR::ReadDB + FindClose(hSearch); + hSearch = INVALID_HANDLE_VALUE; + goto again; + } // endif H + + } // endif rc +#else // !_WIN32 + rc = RC_NF; + + again: + if (!Sub->D) + // Start searching files in the target directory. + if (!(Sub->D = opendir(Direc))) { + snprintf(g->Message, sizeof(g->Message), MSG(BAD_DIRECTORY), Direc, strerror(errno)); + rc = RC_FX; + } // endif dir + + while (rc == RC_NF) + if ((Entry = readdir(Sub->D))) { + // We need the Fileinfo structure to get info about the file + strcat(strcpy(Fpath, Direc), Entry->d_name); + + if (lstat(Fpath, &Fileinfo) < 0) { + snprintf(g->Message, sizeof(g->Message), "%s: %s", Fpath, strerror(errno)); + rc = RC_FX; + } else if (S_ISDIR(Fileinfo.st_mode) && strcmp(Entry->d_name, ".") + && strcmp(Entry->d_name, "..")) { + // Look in the name sub-directory + if (!Sub->Next) { + PSUBDIR sup; + + sup = (PSUBDIR)PlugSubAlloc(g, NULL, sizeof(SUBDIR)); + sup->Next = NULL; + sup->Prev = Sub; + Sub->Next = sup; + } // endif Next + + Sub = Sub->Next; + Sub->D = NULL; + Sub->Len = strlen(Direc); + strcat(strcat(Direc, Entry->d_name), "/"); + goto again; + } else if (S_ISREG(Fileinfo.st_mode)) + // Test whether the file name matches the table name filter + if (!fnmatch(Pattern, Entry->d_name, 0)) { + iFile++; // We have a match + _splitpath(Entry->d_name, NULL, NULL, Fname, Ftype); + rc = RC_OK; + } // endif fnmatch + + } else { + // No more files. Close the DIR handle. + closedir(Sub->D); + + // Are we in a sub-directory? + if (Sub->Prev) { + // Yes, we must continue in the parent directory + Direc[Sub->Len] = '\0'; + Sub = Sub->Prev; + } else + rc = RC_EF; // No, all is finished + + } // endif Entry + +#endif // !_WIN32 + + return rc; + } // end of ReadDB + +#if 0 +/* ------------------------- Class TDBDHR ---------------------------- */ + +/***********************************************************************/ +/* TABDHR constructors. */ +/***********************************************************************/ +TDBDHR::TDBDHR(PDHRDEF tdp) : TDBASE(tdp) + { + memset(&FileData, 0, sizeof(WIN32_FIND_DATA)); + Hsearch = INVALID_HANDLE_VALUE; + iFile = 0; + *Drive = '\0'; + *Direc = '\0'; + *Fname = '\0'; + *Ftype = '\0'; + } // end of TDBDHR standard constructor + +TDBDHR::TDBDHR(PTDBDHR tdbp) : TDBASE(tdbp) + { + FileData = tdbp->FileData; + Hsearch = tdbp->Hsearch; + iFile = tdbp->iFile; + strcpy(Drive, tdbp->Drive); + strcpy(Direc, tdbp->Direc); + strcpy(Fname, tdbp->Fname); + strcpy(Ftype, tdbp->Ftype); + } // end of TDBDHR copy constructor + +// Method +PTDB TDBDHR::Clone(PTABS t) + { + PTDB tp; + PGLOBAL g = t->G; // Is this really useful ??? + + tp = new(g) TDBDHR(this); + tp->Columns = Columns; + return tp; + } // end of Clone + +/***********************************************************************/ +/* Allocate DHR column description block. */ +/***********************************************************************/ +PCOL TDBDHR::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n) + { + return new(g) DHRCOL(cdp, this, cprec, n); + } // end of MakeCol + +/***********************************************************************/ +/* DHR GetMaxSize: returns the number of retrieved files. */ +/***********************************************************************/ +int TDBDHR::GetMaxSize(PGLOBAL g) + { + if (MaxSize < 0) { + char filename[_MAX_PATH]; + int i, rc; + int n = -1; + HANDLE h; + PDBUSER dup = PlgGetUser(g); + + PlugSetPath(filename, To_File, dup->Path); + + // Start searching files in the target directory. + h = FindFirstFile(filename, &FileData); + + if (h == INVALID_HANDLE_VALUE) { + switch (rc = GetLastError()) { + case ERROR_NO_MORE_FILES: + case ERROR_FILE_NOT_FOUND: + n = 0; + break; + default: + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, rc, 0, + (LPTSTR)&filename, sizeof(filename), NULL); + snprintf(g->Message, sizeof(g->Message), MSG(BAD_FILE_HANDLE), filename); + } // endswitch rc + + } else { + for (n = 1;; n++) + if (!FindNextFile(h, &FileData)) { + rc = GetLastError(); + + if (rc != ERROR_NO_MORE_FILES) { + snprintf(g->Message, sizeof(g->Message), MSG(NEXT_FILE_ERROR), rc); + n = -1; + } // endif rc + + break; + } // endif FindNextFile + + // Close the search handle. + if (!FindClose(h) && n != -1) + strcpy(g->Message, MSG(SRCH_CLOSE_ERR)); + + } // endif Hsearch + + MaxSize = n; + } // endif MaxSize + + return MaxSize; + } // end of GetMaxSize + +/***********************************************************************/ +/* DHR Access Method opening routine. */ +/* Open first file, other will be opened sequencially when reading. */ +/***********************************************************************/ +bool TDBDHR::OpenDB(PGLOBAL g) + { + if (trace(1)) + htrc("DHR OpenDB: tdbp=%p tdb=R%d use=%d mode=%d\n", + this, Tdb_No, Use, Mode); + + if (Use == USE_OPEN) { + /*******************************************************************/ + /* Table already open, reopen it. */ + /*******************************************************************/ + CloseDB(g); + SetUse(USE_READY); + } // endif use + + /*********************************************************************/ + /* Direct access needed for join or sorting. */ + /*********************************************************************/ + if (NeedIndexing(g)) { + // Direct access of DHR tables is not implemented yet + snprintf(g->Message, sizeof(g->Message), MSG(NO_DIR_INDX_RD), "DHR"); + return true; + } // endif NeedIndexing + + Use = USE_OPEN; + return false; + } // end of OpenDB + +/***********************************************************************/ +/* Data Base read routine for DHR access method. */ +/***********************************************************************/ +int TDBDHR::ReadDB(PGLOBAL g) + { + int rc = RC_OK; + DWORD erc; + + if (Hsearch == INVALID_HANDLE_VALUE) { + char *filename[_MAX_PATH]; + PDBUSER dup = PlgGetUser(g); + + PlugSetPath(filename, To_File, dup->Path); + _splitpath(filename, Drive, Direc, NULL, NULL); + + /*******************************************************************/ + /* Start searching files in the target directory. */ + /*******************************************************************/ + Hsearch = FindFirstFile(filename, &FileData); + + if (Hsearch != INVALID_HANDLE_VALUE) + iFile = 1; + else switch (erc = GetLastError()) { + case ERROR_NO_MORE_FILES: + case ERROR_FILE_NOT_FOUND: +// case ERROR_PATH_NOT_FOUND: ??????? + rc = RC_EF; + break; + default: + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, erc, 0, + (LPTSTR)&filename, sizeof(filename), NULL); + snprintf(g->Message, sizeof(g->Message), MSG(BAD_FILE_HANDLE), filename); + rc = RC_FX; + } // endswitch erc + + } else { + if (!FindNextFile(Hsearch, &FileData)) { + DWORD erc = GetLastError(); + + if (erc != ERROR_NO_MORE_FILES) { + snprintf(g->Message, sizeof(g->Message), MSG(NEXT_FILE_ERROR), erc); + FindClose(Hsearch); + rc = RC_FX; + } else + rc = RC_EF; + + } else + iFile++; + + } // endif Hsearch + + if (rc == RC_OK) + _splitpath(FileData.cFileName, NULL, NULL, Fname, Ftype); + + return rc; + } // end of ReadDB + +/***********************************************************************/ +/* Data Base close routine for MUL access method. */ +/***********************************************************************/ +void TDBDHR::CloseDB(PGLOBAL g) + { + // Close the search handle. + if (!FindClose(Hsearch)) { + strcpy(g->Message, MSG(SRCH_CLOSE_ERR)); + throw GetAmType(); + } // endif FindClose + + iFile = 0; + Hsearch = INVALID_HANDLE_VALUE; + } // end of CloseDB + +// ------------------------ DHRCOL functions ---------------------------- + +/***********************************************************************/ +/* DHRCOL public constructor. */ +/***********************************************************************/ +DHRCOL::DHRCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am) + : COLBLK(cdp, tdbp, i) + { + if (cprec) { + Next = cprec->GetNext(); + cprec->SetNext(this); + } else { + Next = tdbp->GetColumns(); + tdbp->SetColumns(this); + } // endif cprec + + // Set additional DHR access method information for column. + N = cdp->GetOffset(); + } // end of DOSCOL constructor + +/***********************************************************************/ +/* DHRCOL constructor used for copying columns. */ +/* tdbp is the pointer to the new table descriptor. */ +/***********************************************************************/ +DHRCOL::DHRCOL(DHRCOL *col1, PTDB tdbp) : COLBLK(col1, tdbp) + { + N = col1->N; + } // end of DHRCOL copy constructor + +/***********************************************************************/ +/* ReadColumn: what this routine does is to access the information */ +/* corresponding to this column and convert it to buffer type. */ +/***********************************************************************/ +void DHRCOL::ReadColumn(PGLOBAL g) + { + int rc; + PTDBDHR tdbp = (PTDBDHR)To_Tdb; + + if (trace(1)) + htrc("DHR ReadColumn: col %s R%d use=%.4X status=%.4X type=%d N=%d\n", + Name, tdbp->GetTdb_No(), ColUse, Status, Buf_Type, N); + + /*********************************************************************/ + /* Retrieve the information corresponding to the column number. */ + /*********************************************************************/ + switch (N) { + case 0: // Drive + Value->SetValue(Drive, _MAX_DRIVE); + break; + case 1: // Path + Value->SetValue(Direc, _MAX_DHR); + break; + case 2: // Name + Value->SetValue(Fname, _MAX_FNAME); + break; + case 3: // Extention + Value->SetValue(Ftype, _MAX_EXT); + break; + case 4: // Extention + Value->SetValue(tdbp->FileData.cAlternateFileName, 14); + break; + case 5: + Value->SetValue(tdbp->FileData.dwFileAttributes); + break; + case 6: + Value->SetValue(.................. + } // end of ReadColumn +#endif // 0 + |