diff options
Diffstat (limited to 'storage/connect/tabvct.cpp')
-rw-r--r-- | storage/connect/tabvct.cpp | 588 |
1 files changed, 588 insertions, 0 deletions
diff --git a/storage/connect/tabvct.cpp b/storage/connect/tabvct.cpp new file mode 100644 index 00000000..9cf5f41d --- /dev/null +++ b/storage/connect/tabvct.cpp @@ -0,0 +1,588 @@ +/************* TabVct C++ Program Source Code File (.CPP) **************/ +/* PROGRAM NAME: TABVCT */ +/* ------------- */ +/* Version 3.9 */ +/* */ +/* COPYRIGHT: */ +/* ---------- */ +/* (C) Copyright to the author Olivier BERTRAND 1999-2017 */ +/* */ +/* WHAT THIS PROGRAM DOES: */ +/* ----------------------- */ +/* This is the TDBVCT and VCTCOL classes implementation routines. */ +/* */ +/* WHAT YOU NEED TO COMPILE THIS PROGRAM: */ +/* -------------------------------------- */ +/* */ +/* REQUIRED FILES: */ +/* --------------- */ +/* TABVCT.C - Source code */ +/* PLGDBSEM.H - DB application declaration file */ +/* TABDOS.H - TABDOS 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 MariaDB header file. */ +/***********************************************************************/ +#include "my_global.h" +#if defined(_WIN32) +#include <io.h> +#include <fcntl.h> +#if defined(__BORLANDC__) +#define __MFC_COMPAT__ // To define min/max as macro +#endif +//#include <windows.h> +#include <sys/stat.h> +#else +#if defined(UNIX) +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <errno.h> +#define NO_ERROR 0 +#else +#include <io.h> +#endif +#include <fcntl.h> +#endif + +/***********************************************************************/ +/* 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 "osutil.h" +#include "filamvct.h" +#include "tabdos.h" +#include "tabvct.h" +#include "valblk.h" + +#if defined(UNIX) +//add dummy strerror (NGC) +char *strerror(int num); +#endif // UNIX + +/***********************************************************************/ +/* External function. */ +/***********************************************************************/ +USETEMP UseTemp(void); + +/***********************************************************************/ +/* Char VCT column blocks are right filled with blanks (blank = true) */ +/* Conversion of block values allowed conditionally for insert only. */ +/***********************************************************************/ +PVBLK AllocValBlock(PGLOBAL, void *, int, int, int, int, + bool check = true, bool blank = true, bool un = false); + + +/* --------------------------- Class VCTDEF -------------------------- */ + +/***********************************************************************/ +/* DefineAM: define specific AM block values from XDB file. */ +/***********************************************************************/ +bool VCTDEF::DefineAM(PGLOBAL g, LPCSTR, int poff) + { + DOSDEF::DefineAM(g, "BIN", poff); + + if ((Estimate = GetIntCatInfo("Estimate", 0))) + Elemt = MY_MIN(Elemt, Estimate); + + // Split treated as INT to get default value + Split = GetIntCatInfo("Split", (Estimate) ? 0 : 1); + Header = GetIntCatInfo("Header", 0); + + // CONNECT must have Block/Last info for VEC tables + if (Estimate && !Split && !Header) { + char *fn = GetStringCatInfo(g, "Filename", "?"); + + // No separate header file for urbi tables + Header = (*fn == '?') ? 3 : 2; + } // endif Estimate + + Recfm = RECFM_VCT; + + // poff is no more in use; This will have to be revisited +#if 0 + // For packed files the logical record length is calculated in poff + if (poff != Lrecl) { + Lrecl = poff; + SetIntCatInfo("Lrecl", poff); + } // endif poff +#endif // 0 + + Padded = false; + Blksize = 0; + return false; + } // end of DefineAM + +#if 0 +/***********************************************************************/ +/* Erase: This was made a separate routine because a strange thing */ +/* happened when DeleteTablefile was defined for the VCTDEF class: */ +/* when called from Catalog, the DOSDEF routine was still called even */ +/* for a VCTDEF class. It also minimizes the specific code. */ +/***********************************************************************/ +bool VCTDEF::Erase(char *filename) + { + bool rc = false; + + if (Split) { + char fpat[_MAX_PATH]; + int i; + PCOLDEF cdp; + + MakeFnPattern(fpat); + + for (i = 1, cdp = To_Cols; cdp; i++, cdp = cdp->GetNext()) { + sprintf(filename, fpat, i); +//#if defined(_WIN32) +// rc |= !DeleteFile(filename); +//#else // UNIX + rc |= remove(filename); +//#endif // UNIX + } // endfor cdp + + } else { + rc = DOSDEF::Erase(filename); + + if (Estimate && Header == 2) { + PlugSetPath(filename, Fn, GetPath()); + strcat(PlugRemoveType(filename, filename), ".blk"); + rc |= remove(filename); + } // endif Header + + } // endif Split + + return rc; // Return true if error + } // end of Erase +#endif // 0 + +/***********************************************************************/ +/* Prepare the column file name pattern for a split table. */ +/* This function returns the number of columns of the table. */ +/***********************************************************************/ +int VCTDEF::MakeFnPattern(char *fpat) + { + char pat[16]; +#if defined(_WIN32) + char drive[_MAX_DRIVE]; +#else + char *drive = NULL; +#endif + char direc[_MAX_DIR]; + char fname[_MAX_FNAME]; + char ftype[_MAX_EXT]; // File extention + int n, m, ncol = 0; + PCOLDEF cdp; + + for (cdp = To_Cols; cdp; cdp = cdp->GetNext()) + ncol++; + + for (n = 1, m = ncol; m /= 10; n++) ; + + sprintf(pat, "%%0%dd", n); + _splitpath(Fn, drive, direc, fname, ftype); + strcat(fname, pat); + _makepath(fpat, drive, direc, fname, ftype); + PlugSetPath(fpat, fpat, GetPath()); + return ncol; + } // end of MakeFnPattern + +/***********************************************************************/ +/* GetTable: makes a new Table Description Block. */ +/***********************************************************************/ +PTDB VCTDEF::GetTable(PGLOBAL g, MODE mode) + { + /*********************************************************************/ + /* Allocate a TDB of the proper type. */ + /* Column blocks will be allocated only when needed. */ + /*********************************************************************/ + // Mapping not used for insert (except for true VEC not split tables) + // or when UseTemp is forced + bool map = Mapped && (Estimate || mode != MODE_INSERT) && + !(UseTemp() == TMP_FORCE && + (mode == MODE_UPDATE || mode == MODE_DELETE)); + PTXF txfp; + PTDB tdbp; + + if (Multiple) { + strcpy(g->Message, MSG(NO_MUL_VCT)); + return NULL; + } // endif Multiple + + if (Split) { + if (map) + txfp = new(g) VMPFAM(this); + else + txfp = new(g) VECFAM(this); + + } else if (Huge) + txfp = new(g) BGVFAM(this); + else if (map) + txfp = new(g) VCMFAM(this); + else + txfp = new(g) VCTFAM(this); + + tdbp = new(g) TDBVCT(this, txfp); + + /*********************************************************************/ + /* For block tables, get eventually saved optimization values. */ + /*********************************************************************/ + if (mode != MODE_INSERT) + if (tdbp->GetBlockValues(g)) + PushWarning(g, tdbp); +// return NULL; // causes a crash when deleting index + + return tdbp; + } // end of GetTable + +/* --------------------------- Class TDBVCT -------------------------- */ + +/***********************************************************************/ +/* Implementation of the TDBVCT class. */ +/***********************************************************************/ +TDBVCT::TDBVCT(PVCTDEF tdp, PTXF txfp) : TDBFIX(tdp, txfp) + { + To_SetCols = NULL; + } // end of TDBVCT standard constructor + +TDBVCT::TDBVCT(PGLOBAL g, PTDBVCT tdbp) : TDBFIX(g, tdbp) + { + To_SetCols = tdbp->To_SetCols; + } // end of TDBVCT copy constructor + +// Method +PTDB TDBVCT::Clone(PTABS t) + { + PTDB tp; + PVCTCOL cp1, cp2; + PGLOBAL g = t->G; // Is this really useful ??? + + tp = new(g) TDBVCT(g, this); + + for (cp1 = (PVCTCOL)Columns; cp1; cp1 = (PVCTCOL)cp1->Next) { + cp2 = new(g) VCTCOL(cp1, tp); // Make a copy + NewPointer(t, cp1, cp2); + } // endfor cp1 + + return tp; + } // end of Clone + +/***********************************************************************/ +/* Allocate VCT column description block. */ +/***********************************************************************/ +PCOL TDBVCT::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n) + { + return new(g) VCTCOL(g, cdp, this, cprec, n); + } // end of MakeCol + +/***********************************************************************/ +/* VEC tables are not ready yet to use temporary files. */ +/***********************************************************************/ +bool TDBVCT::IsUsingTemp(PGLOBAL) + { + // For developpers + return (UseTemp() == TMP_TEST); + } // end of IsUsingTemp + +/***********************************************************************/ +/* VCT Access Method opening routine. */ +/* New method now that this routine is called recursively (last table */ +/* first in reverse order): index blocks are immediately linked to */ +/* join block of next table if it exists or else are discarted. */ +/***********************************************************************/ +bool TDBVCT::OpenDB(PGLOBAL g) + { + if (trace(1)) + htrc("VCT 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, just replace it at its beginning. */ + /*******************************************************************/ + if (To_Kindex) + // Table is to be accessed through a sorted index table + To_Kindex->Reset(); + + Txfp->Rewind(); + ResetBlockFilter(g); + return false; + } // endif Use + + /*********************************************************************/ + /* Delete all is not handled using file mapping. */ + /*********************************************************************/ + if (Mode == MODE_DELETE && !Next && Txfp->GetAmType() == TYPE_AM_VMP) { + if (IsSplit()) + Txfp = new(g) VECFAM((PVCTDEF)To_Def); + else + Txfp = new(g) VCTFAM((PVCTDEF)To_Def); + + Txfp->SetTdbp(this); + } // endif Mode + + /*********************************************************************/ + /* Open according to input/output mode required and */ + /* allocate the block buffers for columns used in the query. */ + /*********************************************************************/ + if (Txfp->OpenTableFile(g)) + return true; + + // This was not done in previous version + Use = USE_OPEN; // Do it now in case we are recursively called + + /*********************************************************************/ + /* Allocate the block filter tree if evaluation is possible. */ + /*********************************************************************/ + To_BlkFil = InitBlockFilter(g, To_Filter); + + /*********************************************************************/ + /* Reset buffer access according to indexing and to mode. */ + /*********************************************************************/ + Txfp->ResetBuffer(g); + + return false; + } // end of OpenDB + +/***********************************************************************/ +/* Data Base read routine for VCT access method. */ +/* This routine just set the new block index and record position. */ +/* For index accessed tables the physical reading is deferred to the */ +/* ReadColumn routine so only really used column are physically read. */ +/***********************************************************************/ +int TDBVCT::ReadDB(PGLOBAL g) + { + if (trace(1)) + htrc("VCT ReadDB: R%d Mode=%d CurBlk=%d CurNum=%d key=%p link=%p Kindex=%p\n", + GetTdb_No(), Mode, Txfp->CurBlk, Txfp->CurNum, + To_Key_Col, To_Link, To_Kindex); + + 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 +// num_there++; + return RC_OK; + default: + /***************************************************************/ + /* Set the file position according to record to read. */ + /***************************************************************/ + if (SetRecpos(g, recpos)) + return RC_FX; + + } // endswitch recpos + + } // endif To_Kindex + + return ReadBuffer(g); + } // end of ReadDB + +/***********************************************************************/ +/* Data Base close routine for VEC access method. */ +/***********************************************************************/ +void TDBVCT::CloseDB(PGLOBAL g) + { + if (To_Kindex) { + To_Kindex->Close(); + To_Kindex = NULL; + } // endif + + Txfp->CloseTableFile(g, false); + } // end of CloseDB + +// ------------------------ VCTCOL functions ---------------------------- + +/***********************************************************************/ +/* VCTCOL public constructor. */ +/***********************************************************************/ +VCTCOL::VCTCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i) + : DOSCOL(g, cdp, tdbp, cprec, i, "VCT") + { + Deplac = cdp->GetPoff(); + Clen = cdp->GetClen(); // Length of the field in the file + ColBlk = -1; + ColPos = -1; + Blk = NULL; + Modif = 0; + } // end of VCTCOL constructor + +/***********************************************************************/ +/* VCTCOL constructor used for copying columns. */ +/* tdbp is the pointer to the new table descriptor. */ +/***********************************************************************/ +VCTCOL::VCTCOL(VCTCOL *col1, PTDB tdbp) : DOSCOL(col1, tdbp) + { + ColBlk = col1->ColBlk; + ColPos = col1->ColPos; + Blk = col1->Blk; // Should be NULL when copying ???? + Modif = col1->Modif; // Should be 0 ???? + } // end of VCTCOL copy constructor + +/***********************************************************************/ +/* SetBuffer: allocate and set the buffers needed for write operation.*/ +/***********************************************************************/ +bool VCTCOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check) + { + // Eventual conversion will be done when setting ValBlk from Value. + Value = value; // Force To_Val == Value + + if (DOSCOL::SetBuffer(g, value, ok, check)) + return true; + + if (To_Tdb->GetMode() != MODE_INSERT) { + // Allocate the block buffer to use for read/writing except when + // updating a mapped VCT table and Ok is true. + PTDBVCT tdbp = (PTDBVCT)To_Tdb; + + if (tdbp->Txfp->GetAmType() == TYPE_AM_VMP && ok) { + Blk = AllocValBlock(g, (void*)1, Buf_Type, tdbp->Txfp->Nrec, + Format.Length, Format.Prec, check, true, Unsigned); + Status |= BUF_MAPPED; // Will point into mapped file + } else + Blk = AllocValBlock(g, NULL, Buf_Type, tdbp->Txfp->Nrec, + Format.Length, Format.Prec, check, true, Unsigned); + } // endif Mode + + return false; + } // end of SetBuffer + +/***********************************************************************/ +/* ReadBlock: Indicate it is Ok to make updates. */ +/***********************************************************************/ +void VCTCOL::SetOk(void) + { + if (((PTDBVCT)To_Tdb)->Txfp->GetAmType() == TYPE_AM_VMP) + Status |= BUF_MAPPED; + + Status |= BUF_EMPTY; + Modif = 0; + } // end of SetOk + +/***********************************************************************/ +/* ReadBlock: Read column values from current block. */ +/***********************************************************************/ +void VCTCOL::ReadBlock(PGLOBAL g) + { + PVCTFAM txfp = (PVCTFAM)((PTDBVCT)To_Tdb)->Txfp; + +#if defined(_DEBUG) + if (!Blk) { + strcpy(g->Message, MSG(TO_BLK_IS_NULL)); + throw 58; + } // endif +#endif + + /*********************************************************************/ + /* Read column block according to used access method. */ + /*********************************************************************/ + if (txfp->ReadBlock(g, this)) + throw 6; + + ColBlk = txfp->CurBlk; + ColPos = -1; // Any invalid position + } // end of ReadBlock + +/***********************************************************************/ +/* WriteBlock: Write back current column values for one block. */ +/* Note: the test of Status is meant to prevent physical writing of */ +/* the block during the checking loop in mode Update. It is set to */ +/* BUF_EMPTY when reopening the table between the two loops. */ +/***********************************************************************/ +void VCTCOL::WriteBlock(PGLOBAL g) + { + if (Modif && (Status & BUF_EMPTY)) { + PVCTFAM txfp = (PVCTFAM)((PTDBVCT)To_Tdb)->Txfp; + +#if defined(_DEBUG) + if (!Blk) { + strcpy(g->Message, MSG(BLK_IS_NULL)); + throw 56; + } // endif +#endif + + /*******************************************************************/ + /* Write column block according to used access method. */ + /*******************************************************************/ + if (txfp->WriteBlock(g, this)) + throw 6; + + Modif = 0; + } // endif Modif + + } // end of WriteBlock + +/***********************************************************************/ +/* ReadColumn: what this routine does is to check whether a column */ +/* block has been read from the file, then to extract from it the */ +/* field corresponding to this column and convert it to buffer type. */ +/***********************************************************************/ +void VCTCOL::ReadColumn(PGLOBAL g) + { + PTXF txfp = ((PTDBVCT)To_Tdb)->Txfp; + +#if defined(_DEBUG) + assert (!To_Kcol); +#endif + + if (trace(2)) + htrc("VCT ReadColumn: col %s R%d coluse=%.4X status=%.4X buf_type=%d\n", + Name, To_Tdb->GetTdb_No(), ColUse, Status, Buf_Type); + + if (ColBlk != txfp->CurBlk) + ReadBlock(g); + else if (ColPos == txfp->CurNum) + return; // Value is already there + +//ColBlk = txfp->CurBlk; done in ReadBlock + ColPos = txfp->CurNum; + Value->SetValue_pvblk(Blk, ColPos); + + // Set null when applicable + if (Nullable) + Value->SetNull(Value->IsZero()); + + } // end of ReadColumn + +/***********************************************************************/ +/* WriteColumn: Modifications are written back into column buffer. */ +/* On each change of block the buffer is written back to file and */ +/* in mode Insert the buffer is filled with the block to update. */ +/***********************************************************************/ +void VCTCOL::WriteColumn(PGLOBAL) + { + PTXF txfp = ((PTDBVCT)To_Tdb)->Txfp;; + + if (trace(2)) + htrc("VCT WriteColumn: col %s R%d coluse=%.4X status=%.4X buf_type=%d\n", + Name, To_Tdb->GetTdb_No(), ColUse, Status, Buf_Type); + + ColBlk = txfp->CurBlk; + ColPos = txfp->CurNum; + Blk->SetValue(Value, ColPos); + Modif++; + } // end of WriteColumn + +/* ------------------------ End of TabVct ---------------------------- */ |