summaryrefslogtreecommitdiffstats
path: root/storage/connect/tabvct.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'storage/connect/tabvct.cpp')
-rw-r--r--storage/connect/tabvct.cpp588
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 ---------------------------- */