diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 18:00:34 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 18:00:34 +0000 |
commit | 3f619478f796eddbba6e39502fe941b285dd97b1 (patch) | |
tree | e2c7b5777f728320e5b5542b6213fd3591ba51e2 /storage/connect/tabsys.cpp | |
parent | Initial commit. (diff) | |
download | mariadb-upstream.tar.xz mariadb-upstream.zip |
Adding upstream version 1:10.11.6.upstream/1%10.11.6upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'storage/connect/tabsys.cpp')
-rw-r--r-- | storage/connect/tabsys.cpp | 884 |
1 files changed, 884 insertions, 0 deletions
diff --git a/storage/connect/tabsys.cpp b/storage/connect/tabsys.cpp new file mode 100644 index 00000000..9e8a7d9d --- /dev/null +++ b/storage/connect/tabsys.cpp @@ -0,0 +1,884 @@ +/************* TabSys C++ Program Source Code File (.CPP) **************/ +/* PROGRAM NAME: TABSYS */ +/* ------------- */ +/* Version 2.4 */ +/* */ +/* Author Olivier BERTRAND 2004-2017 */ +/* */ +/* 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" +#if !defined(_WIN32) +#include "osutil.h" +#endif // !_WIN32 +#include "filamtxt.h" +#include "tabdos.h" +#include "tabsys.h" +#include "tabmul.h" +#include "inihandl.h" + +#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 + +/* -------------- Implementation of the INI classes ------------------ */ + +/***********************************************************************/ +/* Constructor. */ +/***********************************************************************/ +INIDEF::INIDEF(void) + { + Pseudo = 3; + Fn = NULL; + Xname = NULL; + Layout = '?'; + Ln = 0; + } // end of INIDEF constructor + +/***********************************************************************/ +/* DefineAM: define specific AM block values from XDB file. */ +/***********************************************************************/ +bool INIDEF::DefineAM(PGLOBAL g, LPCSTR, int) + { + char buf[8]; + + Fn = GetStringCatInfo(g, "Filename", NULL); + GetCharCatInfo("Layout", "C", buf, sizeof(buf)); + Layout = toupper(*buf); + + if (Fn) { + char *p = (char*)PlugSubAlloc(g, NULL, _MAX_PATH); + + PlugSetPath(p, Fn, GetPath()); + Fn = p; + } else { + snprintf(g->Message, sizeof(g->Message), MSG(MISSING_FNAME)); + return true; + } // endif Fn + + Ln = GetSizeCatInfo("Secsize", "8K"); + Desc = Fn; + return false; + } // end of DefineAM + +/***********************************************************************/ +/* GetTable: makes a new TDB of the proper type. */ +/***********************************************************************/ +PTDB INIDEF::GetTable(PGLOBAL g, MODE) + { + PTDBASE tdbp; + + if (Layout == 'C') + tdbp = new(g) TDBINI(this); + else + tdbp = new(g) TDBXIN(this); + + if (Multiple) + tdbp = new(g) TDBMUL(tdbp); // No block optimization yet + + return tdbp; + } // end of GetTable + +#if 0 +/***********************************************************************/ +/* DeleteTableFile: Delete INI table files using platform API. */ +/***********************************************************************/ +bool INIDEF::DeleteTableFile(PGLOBAL g) + { + char filename[_MAX_PATH]; + bool rc; + + // Delete the INI table file if not protected + if (!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 +#endif // 0 + +/* ------------------------------------------------------------------- */ + +/***********************************************************************/ +/* 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::Clone(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 Clone + +/***********************************************************************/ +/* Get the section list from the INI file. */ +/***********************************************************************/ +char *TDBINI::GetSeclist(PGLOBAL g) + { + if (trace(1)) + 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 Cardinality: returns the number of sections in the INI file. */ +/***********************************************************************/ +int TDBINI::Cardinality(PGLOBAL g) + { + if (!g) + return 1; + + if (Cardinal < 0) { + // Count the number of sections from the section list + char *p = GetSeclist(g); + + Cardinal = 0; + + if (p) + for (; *p; p += (strlen(p) + 1)) + Cardinal++; + + } // endif Cardinal + + return Cardinal; + } // end of Cardinality + +/***********************************************************************/ +/* INI GetMaxSize: returns the table cardinality. */ +/***********************************************************************/ +int TDBINI::GetMaxSize(PGLOBAL g) + { + if (MaxSize < 0) + MaxSize = Cardinality(g); + + return MaxSize; + } // end of GetMaxSize + +/***********************************************************************/ +/* INI Access Method opening routine. */ +/***********************************************************************/ +bool TDBINI::OpenDB(PGLOBAL g) + { + PINICOL colp; + + if (Use == USE_OPEN) { +#if 0 + if (To_Kindex) + /*****************************************************************/ + /* Table is to be accessed through a sorted index table. */ + /*****************************************************************/ + To_Kindex->Reset(); +#endif // 0 + 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(1)) + 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) + { + /*********************************************************************/ + /* Now start the pseudo reading process. */ + /*********************************************************************/ + if (!Section) + Section = Seclist; + else + Section += (strlen(Section) + 1); + + if (trace(2)) + htrc("INI ReadDB: section=%s N=%d\n", Section, N); + + N++; + return (*Section) ? RC_OK : RC_EF; + } // end of ReadDB + +/***********************************************************************/ +/* WriteDB: Data Base write routine for INI access methods. */ +/***********************************************************************/ +int TDBINI::WriteDB(PGLOBAL) + { + // This is to check that section name was given when inserting + if (Mode == MODE_INSERT) + Section = NULL; + + // Nothing else to do because all was done in WriteColumn + return RC_OK; + } // end of WriteDB + +/***********************************************************************/ +/* Data Base delete line routine for INI access methods. */ +/***********************************************************************/ +int TDBINI::DeleteDB(PGLOBAL g, int irc) + { + switch (irc) { + case RC_EF: + break; + case RC_FX: + while (ReadDB(g) == RC_OK) + if (!WritePrivateProfileString(Section, NULL, NULL, Ifile)) { + snprintf(g->Message, sizeof(g->Message), "Error %d accessing %s", + GetLastError(), Ifile); + return RC_FX; + } // endif + + break; + default: + if (!Section) { + snprintf(g->Message, sizeof(g->Message), MSG(NO_SECTION_NAME)); + return RC_FX; + } else + if (!WritePrivateProfileString(Section, NULL, NULL, Ifile)) { + snprintf(g->Message, sizeof(g->Message), "Error %d accessing %s", + GetLastError(), Ifile); + return RC_FX; + } // endif rc + + } // endswitch irc + + return RC_OK; + } // end of DeleteDB + +/***********************************************************************/ +/* Data Base close routine for INI access methods. */ +/***********************************************************************/ +void TDBINI::CloseDB(PGLOBAL) + { +#if !defined(_WIN32) + PROFILE_Close(Ifile); +#endif // !_WIN32 + } // end of CloseDB + +// ------------------------ INICOL functions ---------------------------- + +/***********************************************************************/ +/* INICOL public constructor. */ +/***********************************************************************/ +INICOL::INICOL(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 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)) { + snprintf(g->Message, sizeof(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_DOUBLE || Buf_Type == TYPE_DECIM) + // Float values must be written with the correct (column) precision + // Note: maybe this should be forced by ShowValue instead of this ? + value->SetPrec(GetScale()); + + Value = value; // Directly access the external value + } else { + // Values are not of the (good) column type + if (check) { + snprintf(g->Message, sizeof(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) + { + PTDBINI tdbp = (PTDBINI)To_Tdb; + + if (trace(2)) + 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, "\b", + Valbuf, Long + 1, tdbp->Ifile); + break; + } // endswitch Flag + + // Missing keys are interpreted as null values + if (!strcmp(Valbuf, "\b")) { + if (Nullable) + Value->SetNull(true); + + Value->Reset(); // Null value + } else + 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; + bool rc; + PTDBINI tdbp = (PTDBINI)To_Tdb; + + if (trace(2)) + 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 + + // Null key are missing keys + if (Value->IsNull()) + return; + + p = Value->GetCharString(Valbuf); + + if (strlen(p) > (unsigned)Long) { + snprintf(g->Message, sizeof(g->Message), MSG(VALUE_TOO_LONG), p, Name, Long); + throw 31; + } else if (Flag == 1) { + if (tdbp->Mode == MODE_UPDATE) { + snprintf(g->Message, sizeof(g->Message), MSG(NO_SEC_UPDATE)); + throw 31; + } else if (*p) { + tdbp->Section = p; + } else + tdbp->Section = NULL; + + return; + } else if (!tdbp->Section) { + snprintf(g->Message, sizeof(g->Message), MSG(SEC_NAME_FIRST)); + throw 31; + } // endif's + + /*********************************************************************/ + /* Updating must be done only when not in checking pass. */ + /*********************************************************************/ + if (Status) { + rc = WritePrivateProfileString(tdbp->Section, Name, p, tdbp->Ifile); + + if (!rc) { + snprintf(g->Message, sizeof(g->Message), "Error %d writing to %s", + GetLastError(), tdbp->Ifile); + throw 31; + } // endif rc + + } // endif Status + + } // 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::Clone(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 Clone + +/***********************************************************************/ +/* 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 Cardinality: returns the number of keys in the XIN file. */ +/***********************************************************************/ +int TDBXIN::Cardinality(PGLOBAL g) + { + if (!g) + return 1; + + if (Cardinal < 0) { + // Count the number of keys from the section list + char *k, *p = GetSeclist(g); + + Cardinal = 0; + + if (p) + for (; *p; p += (strlen(p) + 1)) + for (k = GetKeylist(g, p); *k; k += (strlen(k) + 1)) + Cardinal++; + + } // endif Cardinal + + return Cardinal; + } // end of Cardinality + +/***********************************************************************/ +/* 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 0 // XIN tables are not indexable + if (To_Kindex) { + /*******************************************************************/ + /* Reading is by an index table. */ + /*******************************************************************/ + int recpos = To_Kindex->Fetch(g); + + switch (recpos) { + case -1: // End of file reached + return RC_EF; + case -2: // No match for join + return RC_NF; + case -3: // Same record as last non null one + return RC_OK; + default: + SetRecpos(g, recpos); + } // endswitch recpos + + } else { +#endif // 0 + 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) + { + // 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)) + if (!WritePrivateProfileString(Section, NULL, NULL, Ifile)) { + snprintf(g->Message, sizeof(g->Message), "Error %d accessing %s", + GetLastError(), Ifile); + return RC_FX; + } // endif + + } else if (!Section) { + snprintf(g->Message, sizeof(g->Message), MSG(NO_SECTION_NAME)); + return RC_FX; + } else + if (!WritePrivateProfileString(Section, Keycur, NULL, Ifile)) { + snprintf(g->Message, sizeof(g->Message), "Error %d accessing %s", + GetLastError(), Ifile); + return RC_FX; + } // endif + + return RC_OK; + } // end of DeleteDB + +// ------------------------ XINCOL functions ---------------------------- + +/***********************************************************************/ +/* XINCOL public constructor. */ +/***********************************************************************/ +XINCOL::XINCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ 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) + { + 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; + bool rc; + PTDBXIN tdbp = (PTDBXIN)To_Tdb; + + if (trace(2)) + 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) { + snprintf(g->Message, sizeof(g->Message), MSG(VALUE_TOO_LONG), p, Name, Long); + throw 31; + } else if (Flag == 1) { + if (tdbp->Mode == MODE_UPDATE) { + snprintf(g->Message, sizeof(g->Message), MSG(NO_SEC_UPDATE)); + throw 31; + } else if (*p) { + tdbp->Section = p; + } else + tdbp->Section = NULL; + + return; + } else if (Flag == 2) { + if (tdbp->Mode == MODE_UPDATE) { + snprintf(g->Message, sizeof(g->Message), MSG(NO_KEY_UPDATE)); + throw 31; + } else if (*p) { + tdbp->Keycur = p; + } else + tdbp->Keycur = NULL; + + return; + } else if (!tdbp->Section || !tdbp->Keycur) { + snprintf(g->Message, sizeof(g->Message), MSG(SEC_KEY_FIRST)); + throw 31; + } // endif's + + /*********************************************************************/ + /* Updating must be done only when not in checking pass. */ + /*********************************************************************/ + if (Status) { + rc = WritePrivateProfileString(tdbp->Section, tdbp->Keycur, p, tdbp->Ifile); + + if (!rc) { + snprintf(g->Message, sizeof(g->Message), "Error %d writing to %s", + GetLastError(), tdbp->Ifile); + throw 31; + } // endif rc + + } // endif Status + + } // end of WriteColumn + +/* ------------------------ End of System ---------------------------- */ + + |