diff options
Diffstat (limited to 'storage/connect/tabsys.cpp')
-rw-r--r-- | storage/connect/tabsys.cpp | 1754 |
1 files changed, 877 insertions, 877 deletions
diff --git a/storage/connect/tabsys.cpp b/storage/connect/tabsys.cpp index 75bc32a9d2e..1ac101f02be 100644 --- a/storage/connect/tabsys.cpp +++ b/storage/connect/tabsys.cpp @@ -1,877 +1,877 @@ -/************* TabSys C++ Program Source Code File (.CPP) **************/
-/* PROGRAM NAME: TABSYS */
-/* ------------- */
-/* Version 2.2 */
-/* */
-/* Author Olivier BERTRAND 2004-2013 */
-/* */
-/* This program are the INI/CFG tables classes. */
-/***********************************************************************/
-
-/***********************************************************************/
-/* Include relevant sections of the System header files. */
-/***********************************************************************/
-#include "my_global.h"
-#if defined(WIN32)
-#if defined(__BORLANDC__)
-#define __MFC_COMPAT__ // To define min/max as macro
-#endif // __BORLANDC__
-//#include <windows.h>
-#else // !WIN32
-#if defined(UNIX)
-#include <errno.h>
-#include <unistd.h>
-#else // !UNIX
-#include <io.h>
-#endif // !UNIX
-#include <fcntl.h>
-#endif // !WIN32
-
-/***********************************************************************/
-/* Include application header files: */
-/* global.h is header containing all global declarations. */
-/* plgdbsem.h is header containing the DB application declarations. */
-/* tabdos.h is header containing the TABDOS class declarations. */
-/***********************************************************************/
-#include "global.h"
-#include "plgdbsem.h"
-#include "reldef.h"
-//#include "xobject.h"
-#include "filamtxt.h"
-#include "tabdos.h"
-#include "tabsys.h"
-#include "tabmul.h"
-#if defined(UNIX)
-#include "osutil.h"
-#endif // UNIX
-
-#define CSZ 36 // Column section name length
-#define CDZ 256 // Column definition length
-
-#if !defined(WIN32)
-#define GetPrivateProfileSectionNames(S,L,I) \
- GetPrivateProfileString(NULL,NULL,"",S,L,I)
-#endif // !WIN32
-
-extern "C" int trace;
-
-/* -------------- Implementation of the INI classes ------------------ */
-
-/***********************************************************************/
-/* Constructor. */
-/***********************************************************************/
-INIDEF::INIDEF(void)
- {
- Pseudo = 3;
- Fn = NULL;
- Xname = NULL;
- Subtype = '?';
- Layout = '?';
- Ln = 0;
- } // end of INIDEF constructor
-
-/***********************************************************************/
-/* DefineAM: define specific AM block values from XDB file. */
-/***********************************************************************/
-bool INIDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
- {
- char buf[8], ds[2];
- void *memp = Cat->GetDescp();
-
- if (!stricmp(am, "SYS"))
- strcpy(ds, "T"); // SYS tables default to T(able)
- else
- strcpy(ds, "I"); // INI tables default to I(ni)
-
- Fn = Cat->GetStringCatInfo(g, Name, "Filename", "?");
- Cat->GetCharCatInfo(Name, "Subtype", ds, buf, sizeof(buf));
- Subtype = toupper(*buf);
- Cat->GetCharCatInfo(Name, "Layout", "C", buf, sizeof(buf));
- Layout = toupper(*buf);
-
- switch (Subtype) {
-#if 0
- case 'C':
- case 'T':
- // Restricted table
- Xname = Cat->GetStringCatInfo(g, Name, "Name", "?");
-
- if (!strcmp(Xname, "?"))
- Xname = NULL;
-
- if (*Fn == '?')
- Fn = Cat->GetStringCatInfo(g, Name, "Database", "?");
-
- if (*Fn != '?') {
- char *p = (char*)PlugSubAlloc(g, memp, _MAX_PATH);
-
- if (!PlgSetXdbPath(g, Fn, NULL, p, _MAX_PATH, NULL, 0))
- Fn = p;
-
- } else
- Fn = Cat->GetDescFile();
-
- Ln = GetIniSize("Database", "Tabsize", "2K", Fn);
- break;
-#endif // 0
- case 'I':
- if (*Fn != '?') {
- char *p = (char*)PlugSubAlloc(g, memp, _MAX_PATH);
-
- PlugSetPath(p, Fn, GetPath());
- Fn = p;
- } else {
- strcpy(g->Message, MSG(MISSING_FNAME));
- return true;
- } // endif Fn
-
- Ln = Cat->GetSizeCatInfo((char*)Name, "Secsize", "8K");
- break;
- default:
- sprintf(g->Message, MSG(INV_SUBTYPE), buf);
- return true;
- } // endswitch Subtype
-
- Desc = Fn;
- return false;
- } // end of DefineAM
-
-/***********************************************************************/
-/* GetTable: makes a new TDB of the proper type. */
-/***********************************************************************/
-PTDB INIDEF::GetTable(PGLOBAL g, MODE m)
- {
- PTDBASE tdbp;
-
- switch (Subtype) {
- case 'I':
- if (Layout == 'C')
- tdbp = new(g) TDBINI(this);
- else
- tdbp = new(g) TDBXIN(this);
-
- break;
- default:
- return NULL;
- } // endswitch Subtype
-
- if (Multiple)
- tdbp = new(g) TDBMUL(tdbp); // No block optimization yet
-
- return tdbp;
- } // end of GetTable
-
-/***********************************************************************/
-/* DeleteTableFile: Delete INI table files using platform API. */
-/* SysTable and SysColumn tables are readonly and not erasable. */
-/***********************************************************************/
-bool INIDEF::DeleteTableFile(PGLOBAL g)
- {
- char filename[_MAX_PATH];
- bool rc;
-
- // Delete the INI table file if not protected
- if (Subtype == 'I' && !IsReadOnly()) {
- PlugSetPath(filename, Fn, GetPath());
-#if defined(WIN32)
- rc = !DeleteFile(filename);
-#else // UNIX
- rc = remove(filename);
-#endif // UNIX
- } else
- rc =true;
-
- return rc; // Return true if error
- } // end of DeleteTableFile
-
-/* ------------------------------------------------------------------- */
-
-/***********************************************************************/
-/* Implementation of the TDBINI class. */
-/***********************************************************************/
-TDBINI::TDBINI(PINIDEF tdp) : TDBASE(tdp)
- {
- Ifile = tdp->Fn;
- Seclist = NULL;
- Section = NULL;
- Seclen = tdp->Ln;
- N = 0;
- } // end of TDBINI constructor
-
-TDBINI::TDBINI(PTDBINI tdbp) : TDBASE(tdbp)
- {
- Ifile = tdbp->Ifile;
- Seclist = tdbp->Seclist;
- Section = tdbp->Section;
- Seclen = tdbp->Seclen;
- N = tdbp->N;
- } // end of TDBINI copy constructor
-
-// Is this really useful ???
-PTDB TDBINI::CopyOne(PTABS t)
- {
- PTDB tp;
- PINICOL cp1, cp2;
- PGLOBAL g = t->G;
-
- tp = new(g) TDBINI(this);
-
- for (cp1 = (PINICOL)Columns; cp1; cp1 = (PINICOL)cp1->GetNext()) {
- cp2 = new(g) INICOL(cp1, tp); // Make a copy
- NewPointer(t, cp1, cp2);
- } // endfor cp1
-
- return tp;
- } // end of CopyOne
-
-/***********************************************************************/
-/* Get the section list from the INI file. */
-/***********************************************************************/
-char *TDBINI::GetSeclist(PGLOBAL g)
- {
- if (trace)
- htrc("GetSeclist: Seclist=%p\n", Seclist);
-
- if (!Seclist) {
- // Result will be retrieved from the INI file
- Seclist = (char*)PlugSubAlloc(g, NULL, Seclen);
- GetPrivateProfileSectionNames(Seclist, Seclen, Ifile);
- } // endif Seclist
-
- return Seclist;
- } // end of GetSeclist
-
-/***********************************************************************/
-/* Allocate INI column description block. */
-/***********************************************************************/
-PCOL TDBINI::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
- {
- return new(g) INICOL(cdp, this, cprec, n);
- } // end of MakeCol
-
-/***********************************************************************/
-/* INI GetMaxSize: returns the number of sections in the INI file. */
-/***********************************************************************/
-int TDBINI::GetMaxSize(PGLOBAL g)
- {
- if (MaxSize < 0 && GetSeclist(g)) {
- // Count the number of sections from the section list
- char *p;
-
- for (MaxSize = 0, p = Seclist; *p; p += (strlen(p) + 1))
- MaxSize++;
-
- } // endif MaxSize
-
- return MaxSize;
- } // end of GetMaxSize
-
-/***********************************************************************/
-/* INI Access Method opening routine. */
-/***********************************************************************/
-bool TDBINI::OpenDB(PGLOBAL g)
- {
- PINICOL colp;
-
- if (Use == USE_OPEN) {
- if (To_Kindex)
- /*****************************************************************/
- /* Table is to be accessed through a sorted index table. */
- /*****************************************************************/
- To_Kindex->Reset();
-
- Section = NULL;
- N = 0;
- return false;
- } // endif use
-
- /*********************************************************************/
- /* OpenDB: initialize the INI file processing. */
- /*********************************************************************/
- GetSeclist(g);
- Use = USE_OPEN; // Do it now in case we are recursively called
-
- /*********************************************************************/
- /* Allocate the buffers that will contain key values. */
- /*********************************************************************/
- for (colp = (PINICOL)Columns; colp; colp = (PINICOL)colp->GetNext())
- if (!colp->IsSpecial()) // Not a pseudo column
- colp->AllocBuf(g);
-
- if (trace)
- htrc("INI OpenDB: seclist=%s seclen=%d ifile=%s\n",
- Seclist, Seclen, Ifile);
-
- return false;
- } // end of OpenDB
-
-/***********************************************************************/
-/* Data Base read routine for INI access method. */
-/***********************************************************************/
-int TDBINI::ReadDB(PGLOBAL g)
- {
- /*********************************************************************/
- /* Now start the pseudo reading process. */
- /*********************************************************************/
- 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;
- } // endswitch recpos
-
- } else {
- 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)
- WritePrivateProfileString(Section, NULL, NULL, Ifile);
-
- break;
- default:
- if (!Section) {
- strcpy(g->Message, MSG(NO_SECTION_NAME));
- return RC_FX;
- } else
- WritePrivateProfileString(Section, NULL, NULL, Ifile);
-
- } // endswitch irc
-
- return RC_OK;
- } // end of DeleteDB
-
-/***********************************************************************/
-/* Data Base close routine for INI access methods. */
-/***********************************************************************/
-void TDBINI::CloseDB(PGLOBAL g)
- {
- // Nothing to do
- } // end of CloseDB
-
-// ------------------------ INICOL functions ----------------------------
-
-/***********************************************************************/
-/* INICOL public constructor. */
-/***********************************************************************/
-INICOL::INICOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am)
- : COLBLK(cdp, tdbp, i)
- {
- if (cprec) {
- Next = cprec->GetNext();
- cprec->SetNext(this);
- } else {
- Next = tdbp->GetColumns();
- tdbp->SetColumns(this);
- } // endif cprec
-
- // Set additional INI access method information for column.
- Valbuf = NULL;
- Flag = cdp->GetOffset();
- Long = cdp->GetLong();
- To_Val = NULL;
- } // end of INICOL constructor
-
-/***********************************************************************/
-/* INICOL constructor used for copying columns. */
-/* tdbp is the pointer to the new table descriptor. */
-/***********************************************************************/
-INICOL::INICOL(INICOL *col1, PTDB tdbp) : COLBLK(col1, tdbp)
- {
- Valbuf = col1->Valbuf;
- Flag = col1->Flag;
- Long = col1->Long;
- To_Val = col1->To_Val;
- } // end of INICOL copy constructor
-
-/***********************************************************************/
-/* Allocate a buffer of the proper size. */
-/***********************************************************************/
-void INICOL::AllocBuf(PGLOBAL g)
- {
- if (!Valbuf)
- Valbuf = (char*)PlugSubAlloc(g, NULL, Long + 1);
-
- } // end of AllocBuf
-
-/***********************************************************************/
-/* SetBuffer: prepare a column block for write operation. */
-/***********************************************************************/
-bool INICOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check)
- {
- if (!(To_Val = value)) {
- sprintf(g->Message, MSG(VALUE_ERROR), Name);
- return true;
- } else if (Buf_Type == value->GetType()) {
- // Values are of the (good) column type
- if (Buf_Type == TYPE_DATE) {
- // If any of the date values is formatted
- // output format must be set for the receiving table
- if (GetDomain() || ((DTVAL *)value)->IsFormatted())
- goto newval; // This will make a new value;
-
- } else if (Buf_Type == TYPE_FLOAT)
- // Float values must be written with the correct (column) precision
- // Note: maybe this should be forced by ShowValue instead of this ?
- ((DFVAL *)value)->SetPrec(GetPrecision());
-
- Value = value; // Directly access the external value
- } else {
- // Values are not of the (good) column type
- if (check) {
- sprintf(g->Message, MSG(TYPE_VALUE_ERR), Name,
- GetTypeName(Buf_Type), GetTypeName(value->GetType()));
- return true;
- } // endif check
-
- newval:
- if (InitValue(g)) // Allocate the matching value block
- return true;
-
- } // endif's Value, Buf_Type
-
- // Allocate the internal value buffer
- AllocBuf(g);
-
- // Because Colblk's have been made from a copy of the original TDB in
- // case of Update, we must reset them to point to the original one.
- if (To_Tdb->GetOrig())
- To_Tdb = (PTDB)To_Tdb->GetOrig();
-
- // Set the Column
- Status = (ok) ? BUF_EMPTY : BUF_NO;
- return false;
- } // end of SetBuffer
-
-/***********************************************************************/
-/* ReadColumn: what this routine does is to access the key buffer set */
-/* from the corresponding section, extract from it the key value */
-/* corresponding to this column name and convert it to buffer type. */
-/***********************************************************************/
-void INICOL::ReadColumn(PGLOBAL g)
- {
- PTDBINI tdbp = (PTDBINI)To_Tdb;
-
- if (trace > 1)
- htrc("INI ReadColumn: col %s R%d flag=%d\n",
- Name, tdbp->GetTdb_No(), Flag);
-
- /*********************************************************************/
- /* Get the key value from the INI file. */
- /*********************************************************************/
- switch (Flag) {
- case 1:
- strncpy(Valbuf, tdbp->Section, Long); // Section name
- Valbuf[Long] = '\0';
- break;
- default:
- GetPrivateProfileString(tdbp->Section, Name, "",
- Valbuf, Long + 1, tdbp->Ifile);
- break;
- } // endswitch Flag
-
- Value->SetValue_psz(Valbuf);
- } // end of ReadColumn
-
-/***********************************************************************/
-/* WriteColumn: what this routine does is to access the last line */
-/* read from the corresponding table, and rewrite the field */
-/* corresponding to this column from the column buffer and type. */
-/***********************************************************************/
-void INICOL::WriteColumn(PGLOBAL g)
- {
- char *p;
- PTDBINI tdbp = (PTDBINI)To_Tdb;
-
- if (trace > 1)
- htrc("INI 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 {
- tdbp->Section = p;
- return;
- } // endif Mode
-
- } else if (!tdbp->Section) {
- strcpy(g->Message, MSG(SEC_NAME_FIRST));
- longjmp(g->jumper[g->jump_level], 31);
- } // endif's
-
- /*********************************************************************/
- /* Updating must be done only when not in checking pass. */
- /*********************************************************************/
- if (Status)
- WritePrivateProfileString(tdbp->Section, Name, p, tdbp->Ifile);
-
- } // end of WriteColumn
-
-/* ------------------------------------------------------------------- */
-
-/***********************************************************************/
-/* Implementation of the TDBXIN class. */
-/***********************************************************************/
-TDBXIN::TDBXIN(PINIDEF tdp) : TDBINI(tdp)
- {
- Keylist = NULL;
- Keycur = NULL;
- Keylen = Seclen;
- Oldsec = -1;
- } // end of TDBXIN constructor
-
-TDBXIN::TDBXIN(PTDBXIN tdbp) : TDBINI(tdbp)
- {
- Keylist = tdbp->Keylist;
- Keycur = tdbp->Keycur;
- Keylen = tdbp->Keylen;
- Oldsec = tdbp->Oldsec;
- } // end of TDBXIN copy constructor
-
-// Is this really useful ???
-PTDB TDBXIN::CopyOne(PTABS t)
- {
- PTDB tp;
- PXINCOL cp1, cp2;
- PGLOBAL g = t->G;
-
- tp = new(g) TDBXIN(this);
-
- for (cp1 = (PXINCOL)Columns; cp1; cp1 = (PXINCOL)cp1->GetNext()) {
- cp2 = new(g) XINCOL(cp1, tp); // Make a copy
- NewPointer(t, cp1, cp2);
- } // endfor cp1
-
- return tp;
- } // end of CopyOne
-
-/***********************************************************************/
-/* Get the key list from the INI file. */
-/***********************************************************************/
-char *TDBXIN::GetKeylist(PGLOBAL g, char *sec)
- {
- if (!Keylist)
- Keylist = (char*)PlugSubAlloc(g, NULL, Keylen);
-
- GetPrivateProfileString(sec, NULL, "", Keylist, Keylen, Ifile);
- return Keylist;
- } // end of GetKeylist
-
-/***********************************************************************/
-/* Allocate XIN column description block. */
-/***********************************************************************/
-PCOL TDBXIN::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
- {
- return new(g) XINCOL(cdp, this, cprec, n);
- } // end of MakeCol
-
-/***********************************************************************/
-/* XIN GetMaxSize: returns the number of sections in the XIN file. */
-/***********************************************************************/
-int TDBXIN::GetMaxSize(PGLOBAL g)
- {
- if (MaxSize < 0 && GetSeclist(g)) {
- // Count the number of keys from the section list
- char *p, *k;
-
- for (MaxSize = 0, p = Seclist; *p; p += (strlen(p) + 1))
- for (k = GetKeylist(g, p); *k; k += (strlen(k) + 1))
- MaxSize++;
-
- } // endif MaxSize
-
- return MaxSize;
- } // end of GetMaxSize
-
-/***********************************************************************/
-/* Record position is Section+Key. */
-/***********************************************************************/
-int TDBXIN::GetRecpos(void)
- {
- union {
- short X[2]; // Section and Key offsets
- int Xpos; // File position
- }; // end of union
-
- X[0] = (short)(Section - Seclist);
- X[1] = (short)(Keycur - Keylist);
- return Xpos;
- } // end of GetRecpos
-
-/***********************************************************************/
-/* Record position is Section+Key. */
-/***********************************************************************/
-bool TDBXIN::SetRecpos(PGLOBAL g, int recpos)
- {
- union {
- short X[2]; // Section and Key offsets
- int Xpos; // File position
- }; // end of union
-
- Xpos = recpos;
-
- if (X[0] != Oldsec) {
- Section = Seclist + X[0];
- Keycur = GetKeylist(g, Section) + X[1];
- Oldsec = X[0];
- } else
- Keycur = Keylist + X[1];
-
- return false;
- } // end of SetRecpos
-
-/***********************************************************************/
-/* XIN Access Method opening routine. */
-/***********************************************************************/
-bool TDBXIN::OpenDB(PGLOBAL g)
- {
- Oldsec = -1; // To replace the table at its beginning
- return TDBINI::OpenDB(g);
- } // end of OpenDB
-
-/***********************************************************************/
-/* Data Base read routine for XIN access method. */
-/***********************************************************************/
-int TDBXIN::ReadDB(PGLOBAL g)
- {
- /*********************************************************************/
- /* Now start the pseudo reading process. */
- /*********************************************************************/
- 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:
- SetRecpos(g, recpos);
- } // endswitch recpos
-
- } else {
- do {
- if (!Keycur || !*Keycur) {
- if (!Section)
- Section = Seclist;
- else
- Section += (strlen(Section) + 1);
-
- if (*Section)
- Keycur = GetKeylist(g, Section);
- else
- return RC_EF;
-
- } else
- Keycur += (strlen(Keycur) + 1);
-
- } while (!*Keycur);
-
- N++;
- } // endif To_Kindex
-
- return RC_OK;
- } // end of ReadDB
-
-/***********************************************************************/
-/* WriteDB: Data Base write routine for XIN access methods. */
-/***********************************************************************/
-int TDBXIN::WriteDB(PGLOBAL g)
- {
- // To check that section and key names were given when inserting
- if (Mode == MODE_INSERT) {
- Section = NULL;
- Keycur = NULL;
- } // endif Mode
-
- // Nothing else to do because all was done in WriteColumn
- return RC_OK;
- } // end of WriteDB
-
-/***********************************************************************/
-/* Data Base delete line routine for XIN access methods. */
-/***********************************************************************/
-int TDBXIN::DeleteDB(PGLOBAL g, int irc)
- {
- if (irc == RC_EF) {
- } else if (irc == RC_FX) {
- for (Section = Seclist; *Section; Section += (strlen(Section) + 1))
- WritePrivateProfileString(Section, NULL, NULL, Ifile);
-
- } else if (Section) {
- WritePrivateProfileString(Section, Keycur, NULL, Ifile);
- } else {
- strcpy(g->Message, MSG(NO_SECTION_NAME));
- return RC_FX;
- } // endif's
-
- return RC_OK;
- } // end of DeleteDB
-
-// ------------------------ XINCOL functions ----------------------------
-
-/***********************************************************************/
-/* XINCOL public constructor. */
-/***********************************************************************/
-XINCOL::XINCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am)
- : INICOL(cdp, tdbp, cprec, i, am)
- {
- } // end of XINCOL constructor
-
-/***********************************************************************/
-/* XINCOL constructor used for copying columns. */
-/* tdbp is the pointer to the new table descriptor. */
-/***********************************************************************/
-XINCOL::XINCOL(XINCOL *col1, PTDB tdbp) : INICOL(col1, tdbp)
- {
- } // end of XINCOL copy constructor
-
-/***********************************************************************/
-/* ReadColumn: what this routine does is to access the key buffer set */
-/* from the corresponding section, extract from it the key value */
-/* corresponding to this column name and convert it to buffer type. */
-/***********************************************************************/
-void XINCOL::ReadColumn(PGLOBAL g)
- {
- PTDBXIN tdbp = (PTDBXIN)To_Tdb;
-
- /*********************************************************************/
- /* Get the key value from the XIN file. */
- /*********************************************************************/
- switch (Flag) {
- case 1:
- strncpy(Valbuf, tdbp->Section, Long); // Section name
- Valbuf[Long] = '\0';
- break;
- case 2:
- strncpy(Valbuf, tdbp->Keycur, Long); // Key name
- Valbuf[Long] = '\0';
- break;
- default:
- GetPrivateProfileString(tdbp->Section, tdbp->Keycur, "",
- Valbuf, Long + 1, tdbp->Ifile);
- break;
- } // endswitch Flag
-
- Value->SetValue_psz(Valbuf);
- } // end of ReadColumn
-
-/***********************************************************************/
-/* WriteColumn: what this routine does is to access the last line */
-/* read from the corresponding table, and rewrite the field */
-/* corresponding to this column from the column buffer and type. */
-/***********************************************************************/
-void XINCOL::WriteColumn(PGLOBAL g)
- {
- char *p;
- 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 {
- tdbp->Section = p;
- return;
- } // endif Mode
-
- } else if (Flag == 2) {
- if (tdbp->Mode == MODE_UPDATE) {
- strcpy(g->Message, MSG(NO_KEY_UPDATE));
- longjmp(g->jumper[g->jump_level], 31);
- } else {
- tdbp->Keycur = p;
- return;
- } // endif Mode
-
- } 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)
- WritePrivateProfileString(tdbp->Section, tdbp->Keycur, p, tdbp->Ifile);
-
- } // end of WriteColumn
-
-/* ------------------------ End of System ---------------------------- */
-
-
+/************* TabSys C++ Program Source Code File (.CPP) **************/ +/* PROGRAM NAME: TABSYS */ +/* ------------- */ +/* Version 2.2 */ +/* */ +/* Author Olivier BERTRAND 2004-2013 */ +/* */ +/* This program are the INI/CFG tables classes. */ +/***********************************************************************/ + +/***********************************************************************/ +/* Include relevant sections of the System header files. */ +/***********************************************************************/ +#include "my_global.h" +#if defined(WIN32) +#if defined(__BORLANDC__) +#define __MFC_COMPAT__ // To define min/max as macro +#endif // __BORLANDC__ +//#include <windows.h> +#else // !WIN32 +#if defined(UNIX) +#include <errno.h> +#include <unistd.h> +#else // !UNIX +#include <io.h> +#endif // !UNIX +#include <fcntl.h> +#endif // !WIN32 + +/***********************************************************************/ +/* Include application header files: */ +/* global.h is header containing all global declarations. */ +/* plgdbsem.h is header containing the DB application declarations. */ +/* tabdos.h is header containing the TABDOS class declarations. */ +/***********************************************************************/ +#include "global.h" +#include "plgdbsem.h" +#include "reldef.h" +//#include "xobject.h" +#include "filamtxt.h" +#include "tabdos.h" +#include "tabsys.h" +#include "tabmul.h" +#if defined(UNIX) +#include "osutil.h" +#endif // UNIX + +#define CSZ 36 // Column section name length +#define CDZ 256 // Column definition length + +#if !defined(WIN32) +#define GetPrivateProfileSectionNames(S,L,I) \ + GetPrivateProfileString(NULL,NULL,"",S,L,I) +#endif // !WIN32 + +extern "C" int trace; + +/* -------------- Implementation of the INI classes ------------------ */ + +/***********************************************************************/ +/* Constructor. */ +/***********************************************************************/ +INIDEF::INIDEF(void) + { + Pseudo = 3; + Fn = NULL; + Xname = NULL; + Subtype = '?'; + Layout = '?'; + Ln = 0; + } // end of INIDEF constructor + +/***********************************************************************/ +/* DefineAM: define specific AM block values from XDB file. */ +/***********************************************************************/ +bool INIDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) + { + char buf[8], ds[2]; + void *memp = Cat->GetDescp(); + + if (!stricmp(am, "SYS")) + strcpy(ds, "T"); // SYS tables default to T(able) + else + strcpy(ds, "I"); // INI tables default to I(ni) + + Fn = Cat->GetStringCatInfo(g, Name, "Filename", "?"); + Cat->GetCharCatInfo(Name, "Subtype", ds, buf, sizeof(buf)); + Subtype = toupper(*buf); + Cat->GetCharCatInfo(Name, "Layout", "C", buf, sizeof(buf)); + Layout = toupper(*buf); + + switch (Subtype) { +#if 0 + case 'C': + case 'T': + // Restricted table + Xname = Cat->GetStringCatInfo(g, Name, "Name", "?"); + + if (!strcmp(Xname, "?")) + Xname = NULL; + + if (*Fn == '?') + Fn = Cat->GetStringCatInfo(g, Name, "Database", "?"); + + if (*Fn != '?') { + char *p = (char*)PlugSubAlloc(g, memp, _MAX_PATH); + + if (!PlgSetXdbPath(g, Fn, NULL, p, _MAX_PATH, NULL, 0)) + Fn = p; + + } else + Fn = Cat->GetDescFile(); + + Ln = GetIniSize("Database", "Tabsize", "2K", Fn); + break; +#endif // 0 + case 'I': + if (*Fn != '?') { + char *p = (char*)PlugSubAlloc(g, memp, _MAX_PATH); + + PlugSetPath(p, Fn, GetPath()); + Fn = p; + } else { + strcpy(g->Message, MSG(MISSING_FNAME)); + return true; + } // endif Fn + + Ln = Cat->GetSizeCatInfo((char*)Name, "Secsize", "8K"); + break; + default: + sprintf(g->Message, MSG(INV_SUBTYPE), buf); + return true; + } // endswitch Subtype + + Desc = Fn; + return false; + } // end of DefineAM + +/***********************************************************************/ +/* GetTable: makes a new TDB of the proper type. */ +/***********************************************************************/ +PTDB INIDEF::GetTable(PGLOBAL g, MODE m) + { + PTDBASE tdbp; + + switch (Subtype) { + case 'I': + if (Layout == 'C') + tdbp = new(g) TDBINI(this); + else + tdbp = new(g) TDBXIN(this); + + break; + default: + return NULL; + } // endswitch Subtype + + if (Multiple) + tdbp = new(g) TDBMUL(tdbp); // No block optimization yet + + return tdbp; + } // end of GetTable + +/***********************************************************************/ +/* DeleteTableFile: Delete INI table files using platform API. */ +/* SysTable and SysColumn tables are readonly and not erasable. */ +/***********************************************************************/ +bool INIDEF::DeleteTableFile(PGLOBAL g) + { + char filename[_MAX_PATH]; + bool rc; + + // Delete the INI table file if not protected + if (Subtype == 'I' && !IsReadOnly()) { + PlugSetPath(filename, Fn, GetPath()); +#if defined(WIN32) + rc = !DeleteFile(filename); +#else // UNIX + rc = remove(filename); +#endif // UNIX + } else + rc =true; + + return rc; // Return true if error + } // end of DeleteTableFile + +/* ------------------------------------------------------------------- */ + +/***********************************************************************/ +/* Implementation of the TDBINI class. */ +/***********************************************************************/ +TDBINI::TDBINI(PINIDEF tdp) : TDBASE(tdp) + { + Ifile = tdp->Fn; + Seclist = NULL; + Section = NULL; + Seclen = tdp->Ln; + N = 0; + } // end of TDBINI constructor + +TDBINI::TDBINI(PTDBINI tdbp) : TDBASE(tdbp) + { + Ifile = tdbp->Ifile; + Seclist = tdbp->Seclist; + Section = tdbp->Section; + Seclen = tdbp->Seclen; + N = tdbp->N; + } // end of TDBINI copy constructor + +// Is this really useful ??? +PTDB TDBINI::CopyOne(PTABS t) + { + PTDB tp; + PINICOL cp1, cp2; + PGLOBAL g = t->G; + + tp = new(g) TDBINI(this); + + for (cp1 = (PINICOL)Columns; cp1; cp1 = (PINICOL)cp1->GetNext()) { + cp2 = new(g) INICOL(cp1, tp); // Make a copy + NewPointer(t, cp1, cp2); + } // endfor cp1 + + return tp; + } // end of CopyOne + +/***********************************************************************/ +/* Get the section list from the INI file. */ +/***********************************************************************/ +char *TDBINI::GetSeclist(PGLOBAL g) + { + if (trace) + htrc("GetSeclist: Seclist=%p\n", Seclist); + + if (!Seclist) { + // Result will be retrieved from the INI file + Seclist = (char*)PlugSubAlloc(g, NULL, Seclen); + GetPrivateProfileSectionNames(Seclist, Seclen, Ifile); + } // endif Seclist + + return Seclist; + } // end of GetSeclist + +/***********************************************************************/ +/* Allocate INI column description block. */ +/***********************************************************************/ +PCOL TDBINI::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n) + { + return new(g) INICOL(cdp, this, cprec, n); + } // end of MakeCol + +/***********************************************************************/ +/* INI GetMaxSize: returns the number of sections in the INI file. */ +/***********************************************************************/ +int TDBINI::GetMaxSize(PGLOBAL g) + { + if (MaxSize < 0 && GetSeclist(g)) { + // Count the number of sections from the section list + char *p; + + for (MaxSize = 0, p = Seclist; *p; p += (strlen(p) + 1)) + MaxSize++; + + } // endif MaxSize + + return MaxSize; + } // end of GetMaxSize + +/***********************************************************************/ +/* INI Access Method opening routine. */ +/***********************************************************************/ +bool TDBINI::OpenDB(PGLOBAL g) + { + PINICOL colp; + + if (Use == USE_OPEN) { + if (To_Kindex) + /*****************************************************************/ + /* Table is to be accessed through a sorted index table. */ + /*****************************************************************/ + To_Kindex->Reset(); + + Section = NULL; + N = 0; + return false; + } // endif use + + /*********************************************************************/ + /* OpenDB: initialize the INI file processing. */ + /*********************************************************************/ + GetSeclist(g); + Use = USE_OPEN; // Do it now in case we are recursively called + + /*********************************************************************/ + /* Allocate the buffers that will contain key values. */ + /*********************************************************************/ + for (colp = (PINICOL)Columns; colp; colp = (PINICOL)colp->GetNext()) + if (!colp->IsSpecial()) // Not a pseudo column + colp->AllocBuf(g); + + if (trace) + htrc("INI OpenDB: seclist=%s seclen=%d ifile=%s\n", + Seclist, Seclen, Ifile); + + return false; + } // end of OpenDB + +/***********************************************************************/ +/* Data Base read routine for INI access method. */ +/***********************************************************************/ +int TDBINI::ReadDB(PGLOBAL g) + { + /*********************************************************************/ + /* Now start the pseudo reading process. */ + /*********************************************************************/ + 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; + } // endswitch recpos + + } else { + 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) + WritePrivateProfileString(Section, NULL, NULL, Ifile); + + break; + default: + if (!Section) { + strcpy(g->Message, MSG(NO_SECTION_NAME)); + return RC_FX; + } else + WritePrivateProfileString(Section, NULL, NULL, Ifile); + + } // endswitch irc + + return RC_OK; + } // end of DeleteDB + +/***********************************************************************/ +/* Data Base close routine for INI access methods. */ +/***********************************************************************/ +void TDBINI::CloseDB(PGLOBAL g) + { + // Nothing to do + } // end of CloseDB + +// ------------------------ INICOL functions ---------------------------- + +/***********************************************************************/ +/* INICOL public constructor. */ +/***********************************************************************/ +INICOL::INICOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am) + : COLBLK(cdp, tdbp, i) + { + if (cprec) { + Next = cprec->GetNext(); + cprec->SetNext(this); + } else { + Next = tdbp->GetColumns(); + tdbp->SetColumns(this); + } // endif cprec + + // Set additional INI access method information for column. + Valbuf = NULL; + Flag = cdp->GetOffset(); + Long = cdp->GetLong(); + To_Val = NULL; + } // end of INICOL constructor + +/***********************************************************************/ +/* INICOL constructor used for copying columns. */ +/* tdbp is the pointer to the new table descriptor. */ +/***********************************************************************/ +INICOL::INICOL(INICOL *col1, PTDB tdbp) : COLBLK(col1, tdbp) + { + Valbuf = col1->Valbuf; + Flag = col1->Flag; + Long = col1->Long; + To_Val = col1->To_Val; + } // end of INICOL copy constructor + +/***********************************************************************/ +/* Allocate a buffer of the proper size. */ +/***********************************************************************/ +void INICOL::AllocBuf(PGLOBAL g) + { + if (!Valbuf) + Valbuf = (char*)PlugSubAlloc(g, NULL, Long + 1); + + } // end of AllocBuf + +/***********************************************************************/ +/* SetBuffer: prepare a column block for write operation. */ +/***********************************************************************/ +bool INICOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check) + { + if (!(To_Val = value)) { + sprintf(g->Message, MSG(VALUE_ERROR), Name); + return true; + } else if (Buf_Type == value->GetType()) { + // Values are of the (good) column type + if (Buf_Type == TYPE_DATE) { + // If any of the date values is formatted + // output format must be set for the receiving table + if (GetDomain() || ((DTVAL *)value)->IsFormatted()) + goto newval; // This will make a new value; + + } else if (Buf_Type == TYPE_FLOAT) + // Float values must be written with the correct (column) precision + // Note: maybe this should be forced by ShowValue instead of this ? + ((DFVAL *)value)->SetPrec(GetPrecision()); + + Value = value; // Directly access the external value + } else { + // Values are not of the (good) column type + if (check) { + sprintf(g->Message, MSG(TYPE_VALUE_ERR), Name, + GetTypeName(Buf_Type), GetTypeName(value->GetType())); + return true; + } // endif check + + newval: + if (InitValue(g)) // Allocate the matching value block + return true; + + } // endif's Value, Buf_Type + + // Allocate the internal value buffer + AllocBuf(g); + + // Because Colblk's have been made from a copy of the original TDB in + // case of Update, we must reset them to point to the original one. + if (To_Tdb->GetOrig()) + To_Tdb = (PTDB)To_Tdb->GetOrig(); + + // Set the Column + Status = (ok) ? BUF_EMPTY : BUF_NO; + return false; + } // end of SetBuffer + +/***********************************************************************/ +/* ReadColumn: what this routine does is to access the key buffer set */ +/* from the corresponding section, extract from it the key value */ +/* corresponding to this column name and convert it to buffer type. */ +/***********************************************************************/ +void INICOL::ReadColumn(PGLOBAL g) + { + PTDBINI tdbp = (PTDBINI)To_Tdb; + + if (trace > 1) + htrc("INI ReadColumn: col %s R%d flag=%d\n", + Name, tdbp->GetTdb_No(), Flag); + + /*********************************************************************/ + /* Get the key value from the INI file. */ + /*********************************************************************/ + switch (Flag) { + case 1: + strncpy(Valbuf, tdbp->Section, Long); // Section name + Valbuf[Long] = '\0'; + break; + default: + GetPrivateProfileString(tdbp->Section, Name, "", + Valbuf, Long + 1, tdbp->Ifile); + break; + } // endswitch Flag + + Value->SetValue_psz(Valbuf); + } // end of ReadColumn + +/***********************************************************************/ +/* WriteColumn: what this routine does is to access the last line */ +/* read from the corresponding table, and rewrite the field */ +/* corresponding to this column from the column buffer and type. */ +/***********************************************************************/ +void INICOL::WriteColumn(PGLOBAL g) + { + char *p; + PTDBINI tdbp = (PTDBINI)To_Tdb; + + if (trace > 1) + htrc("INI 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 { + tdbp->Section = p; + return; + } // endif Mode + + } else if (!tdbp->Section) { + strcpy(g->Message, MSG(SEC_NAME_FIRST)); + longjmp(g->jumper[g->jump_level], 31); + } // endif's + + /*********************************************************************/ + /* Updating must be done only when not in checking pass. */ + /*********************************************************************/ + if (Status) + WritePrivateProfileString(tdbp->Section, Name, p, tdbp->Ifile); + + } // end of WriteColumn + +/* ------------------------------------------------------------------- */ + +/***********************************************************************/ +/* Implementation of the TDBXIN class. */ +/***********************************************************************/ +TDBXIN::TDBXIN(PINIDEF tdp) : TDBINI(tdp) + { + Keylist = NULL; + Keycur = NULL; + Keylen = Seclen; + Oldsec = -1; + } // end of TDBXIN constructor + +TDBXIN::TDBXIN(PTDBXIN tdbp) : TDBINI(tdbp) + { + Keylist = tdbp->Keylist; + Keycur = tdbp->Keycur; + Keylen = tdbp->Keylen; + Oldsec = tdbp->Oldsec; + } // end of TDBXIN copy constructor + +// Is this really useful ??? +PTDB TDBXIN::CopyOne(PTABS t) + { + PTDB tp; + PXINCOL cp1, cp2; + PGLOBAL g = t->G; + + tp = new(g) TDBXIN(this); + + for (cp1 = (PXINCOL)Columns; cp1; cp1 = (PXINCOL)cp1->GetNext()) { + cp2 = new(g) XINCOL(cp1, tp); // Make a copy + NewPointer(t, cp1, cp2); + } // endfor cp1 + + return tp; + } // end of CopyOne + +/***********************************************************************/ +/* Get the key list from the INI file. */ +/***********************************************************************/ +char *TDBXIN::GetKeylist(PGLOBAL g, char *sec) + { + if (!Keylist) + Keylist = (char*)PlugSubAlloc(g, NULL, Keylen); + + GetPrivateProfileString(sec, NULL, "", Keylist, Keylen, Ifile); + return Keylist; + } // end of GetKeylist + +/***********************************************************************/ +/* Allocate XIN column description block. */ +/***********************************************************************/ +PCOL TDBXIN::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n) + { + return new(g) XINCOL(cdp, this, cprec, n); + } // end of MakeCol + +/***********************************************************************/ +/* XIN GetMaxSize: returns the number of sections in the XIN file. */ +/***********************************************************************/ +int TDBXIN::GetMaxSize(PGLOBAL g) + { + if (MaxSize < 0 && GetSeclist(g)) { + // Count the number of keys from the section list + char *p, *k; + + for (MaxSize = 0, p = Seclist; *p; p += (strlen(p) + 1)) + for (k = GetKeylist(g, p); *k; k += (strlen(k) + 1)) + MaxSize++; + + } // endif MaxSize + + return MaxSize; + } // end of GetMaxSize + +/***********************************************************************/ +/* Record position is Section+Key. */ +/***********************************************************************/ +int TDBXIN::GetRecpos(void) + { + union { + short X[2]; // Section and Key offsets + int Xpos; // File position + }; // end of union + + X[0] = (short)(Section - Seclist); + X[1] = (short)(Keycur - Keylist); + return Xpos; + } // end of GetRecpos + +/***********************************************************************/ +/* Record position is Section+Key. */ +/***********************************************************************/ +bool TDBXIN::SetRecpos(PGLOBAL g, int recpos) + { + union { + short X[2]; // Section and Key offsets + int Xpos; // File position + }; // end of union + + Xpos = recpos; + + if (X[0] != Oldsec) { + Section = Seclist + X[0]; + Keycur = GetKeylist(g, Section) + X[1]; + Oldsec = X[0]; + } else + Keycur = Keylist + X[1]; + + return false; + } // end of SetRecpos + +/***********************************************************************/ +/* XIN Access Method opening routine. */ +/***********************************************************************/ +bool TDBXIN::OpenDB(PGLOBAL g) + { + Oldsec = -1; // To replace the table at its beginning + return TDBINI::OpenDB(g); + } // end of OpenDB + +/***********************************************************************/ +/* Data Base read routine for XIN access method. */ +/***********************************************************************/ +int TDBXIN::ReadDB(PGLOBAL g) + { + /*********************************************************************/ + /* Now start the pseudo reading process. */ + /*********************************************************************/ + 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: + SetRecpos(g, recpos); + } // endswitch recpos + + } else { + do { + if (!Keycur || !*Keycur) { + if (!Section) + Section = Seclist; + else + Section += (strlen(Section) + 1); + + if (*Section) + Keycur = GetKeylist(g, Section); + else + return RC_EF; + + } else + Keycur += (strlen(Keycur) + 1); + + } while (!*Keycur); + + N++; + } // endif To_Kindex + + return RC_OK; + } // end of ReadDB + +/***********************************************************************/ +/* WriteDB: Data Base write routine for XIN access methods. */ +/***********************************************************************/ +int TDBXIN::WriteDB(PGLOBAL g) + { + // To check that section and key names were given when inserting + if (Mode == MODE_INSERT) { + Section = NULL; + Keycur = NULL; + } // endif Mode + + // Nothing else to do because all was done in WriteColumn + return RC_OK; + } // end of WriteDB + +/***********************************************************************/ +/* Data Base delete line routine for XIN access methods. */ +/***********************************************************************/ +int TDBXIN::DeleteDB(PGLOBAL g, int irc) + { + if (irc == RC_EF) { + } else if (irc == RC_FX) { + for (Section = Seclist; *Section; Section += (strlen(Section) + 1)) + WritePrivateProfileString(Section, NULL, NULL, Ifile); + + } else if (Section) { + WritePrivateProfileString(Section, Keycur, NULL, Ifile); + } else { + strcpy(g->Message, MSG(NO_SECTION_NAME)); + return RC_FX; + } // endif's + + return RC_OK; + } // end of DeleteDB + +// ------------------------ XINCOL functions ---------------------------- + +/***********************************************************************/ +/* XINCOL public constructor. */ +/***********************************************************************/ +XINCOL::XINCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am) + : INICOL(cdp, tdbp, cprec, i, am) + { + } // end of XINCOL constructor + +/***********************************************************************/ +/* XINCOL constructor used for copying columns. */ +/* tdbp is the pointer to the new table descriptor. */ +/***********************************************************************/ +XINCOL::XINCOL(XINCOL *col1, PTDB tdbp) : INICOL(col1, tdbp) + { + } // end of XINCOL copy constructor + +/***********************************************************************/ +/* ReadColumn: what this routine does is to access the key buffer set */ +/* from the corresponding section, extract from it the key value */ +/* corresponding to this column name and convert it to buffer type. */ +/***********************************************************************/ +void XINCOL::ReadColumn(PGLOBAL g) + { + PTDBXIN tdbp = (PTDBXIN)To_Tdb; + + /*********************************************************************/ + /* Get the key value from the XIN file. */ + /*********************************************************************/ + switch (Flag) { + case 1: + strncpy(Valbuf, tdbp->Section, Long); // Section name + Valbuf[Long] = '\0'; + break; + case 2: + strncpy(Valbuf, tdbp->Keycur, Long); // Key name + Valbuf[Long] = '\0'; + break; + default: + GetPrivateProfileString(tdbp->Section, tdbp->Keycur, "", + Valbuf, Long + 1, tdbp->Ifile); + break; + } // endswitch Flag + + Value->SetValue_psz(Valbuf); + } // end of ReadColumn + +/***********************************************************************/ +/* WriteColumn: what this routine does is to access the last line */ +/* read from the corresponding table, and rewrite the field */ +/* corresponding to this column from the column buffer and type. */ +/***********************************************************************/ +void XINCOL::WriteColumn(PGLOBAL g) + { + char *p; + 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 { + tdbp->Section = p; + return; + } // endif Mode + + } else if (Flag == 2) { + if (tdbp->Mode == MODE_UPDATE) { + strcpy(g->Message, MSG(NO_KEY_UPDATE)); + longjmp(g->jumper[g->jump_level], 31); + } else { + tdbp->Keycur = p; + return; + } // endif Mode + + } 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) + WritePrivateProfileString(tdbp->Section, tdbp->Keycur, p, tdbp->Ifile); + + } // end of WriteColumn + +/* ------------------------ End of System ---------------------------- */ + + |