diff options
Diffstat (limited to 'storage/connect/tabvir.cpp')
-rw-r--r-- | storage/connect/tabvir.cpp | 305 |
1 files changed, 305 insertions, 0 deletions
diff --git a/storage/connect/tabvir.cpp b/storage/connect/tabvir.cpp new file mode 100644 index 00000000..0c4a41be --- /dev/null +++ b/storage/connect/tabvir.cpp @@ -0,0 +1,305 @@ +/************* tdbvir C++ Program Source Code File (.CPP) **************/ +/* PROGRAM NAME: tdbvir.cpp Version 1.2 */ +/* (C) Copyright to the author Olivier BERTRAND 2014-2017 */ +/* This program are the VIR classes DB execution routines. */ +/***********************************************************************/ + +/***********************************************************************/ +/* Include relevant sections of the MariaDB header file. */ +/***********************************************************************/ +#include <my_global.h> + +/***********************************************************************/ +/* Include application header files: */ +/* global.h is header containing all global declarations. */ +/* plgdbsem.h is header containing the DB application declarations. */ +/* xtable.h is header containing the TDBASE declarations. */ +/* tdbvir.h is header containing the VIR classes declarations. */ +/***********************************************************************/ +#include "global.h" +#include "plgdbsem.h" +#include "filter.h" +#include "xtable.h" +//#include "reldef.h" +#include "colblk.h" +#include "mycat.h" // for FNC_COL +#include "tabvir.h" +#include "resource.h" // for IDS_COLUMNS + +/***********************************************************************/ +/* Return the unique column definition to MariaDB. */ +/***********************************************************************/ +PQRYRES VirColumns(PGLOBAL g, bool info) + { + int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING, + TYPE_INT, TYPE_STRING, TYPE_STRING}; + XFLD fldtyp[] = {FLD_NAME, FLD_TYPE, FLD_TYPENAME, + FLD_PREC, FLD_KEY, FLD_EXTRA}; + unsigned int length[] = {8, 4, 16, 4, 16, 16}; + int i, n, ncol = sizeof(buftyp) / sizeof(int); + PQRYRES qrp; + PCOLRES crp; + + n = (info) ? 0 : 1; + + /**********************************************************************/ + /* Allocate the structures used to refer to the result set. */ + /**********************************************************************/ + if (!(qrp = PlgAllocResult(g, ncol, n, IDS_COLUMNS + 3, + buftyp, fldtyp, length, false, true))) + return NULL; + + // Some columns must be renamed before info + for (i = 0, crp = qrp->Colresp; crp; crp = crp->Next) + switch (++i) { + case 5: crp->Name = "Key"; break; + case 6: crp->Name = "Extra"; break; + } // endswitch i + + if (info) + return qrp; + + /**********************************************************************/ + /* Now get the results into blocks. */ + /**********************************************************************/ + // Set column name + crp = qrp->Colresp; // Column_Name + crp->Kdata->SetValue("n", 0); + + // Set type, type name, precision + crp = crp->Next; // Data_Type + crp->Kdata->SetValue(TYPE_INT, 0); + + crp = crp->Next; // Type_Name + crp->Kdata->SetValue(GetTypeName(TYPE_INT), 0); + + crp = crp->Next; // Precision + crp->Kdata->SetValue(11, 0); + + crp = crp->Next; // Key + crp->Kdata->SetValue("KEY", 0); + + crp = crp->Next; // Extra + crp->Kdata->SetValue("SPECIAL=ROWID", 0); + + qrp->Nblin = 1; + + /**********************************************************************/ + /* Return the result pointer for use by discovery routines. */ + /**********************************************************************/ + return qrp; + } // end of VirColumns + +/* --------------------------- Class VIRDEF --------------------------- */ + +/***********************************************************************/ +/* GetTable: makes a new Table Description Block. */ +/***********************************************************************/ +PTDB VIRDEF::GetTable(PGLOBAL g, MODE) + { + // Column blocks will be allocated only when needed. + if (Catfunc == FNC_COL) + return new(g) TDBVICL(this); + else + return new(g) TDBVIR(this); + + } // end of GetTable + +/* ------------------------ TDBVIR functions ------------------------- */ + +/***********************************************************************/ +/* Implementation of the TDBVIR class. */ +/***********************************************************************/ +TDBVIR::TDBVIR(PVIRDEF tdp) : TDBASE(tdp) + { + Size = (tdp->GetElemt()) ? tdp->GetElemt() : 1; + N = -1; + } // end of TDBVIR constructor + +/***********************************************************************/ +/* Analyze the filter and reset the size limit accordingly. */ +/* This is possible when a filter contains predicates implying the */ +/* special column ROWID. Here we just test for when no more good */ +/* records can be met in the remaining of the table. */ +/***********************************************************************/ +int TDBVIR::TestFilter(PFIL filp, bool nop) + { + int i, op = filp->GetOpc(), n = 0, type[2] = {0,0}; + int l1 = 0, l2, limit = Size; + PXOB arg[2] = {NULL,NULL}; + + if (op == OP_GT || op == OP_GE || op == OP_LT || op == OP_LE) { + for (i = 0; i < 2; i++) { + arg[i] = filp->Arg(i); + + switch (filp->GetArgType(i)) { + case TYPE_CONST: + if ((l1 = arg[i]->GetIntValue()) >= 0) + type[i] = 1; + + break; + case TYPE_COLBLK: + if (((PCOL)arg[i])->GetTo_Tdb() == this && + ((PCOL)arg[i])->GetAmType() == TYPE_AM_ROWID) + type[i] = 2; + + break; + default: + break; + } // endswitch ArgType + + if (!type[i]) + break; + + n += type[i]; + } // endfor i + + if (n == 3) { + // If true it will be ok to delete the filter + BOOL ok = (filp == To_Filter); + + if (type[0] == 1) + // Make it always a Column-op-Value + switch (op) { + case OP_GT: op = OP_LT; break; + case OP_GE: op = OP_LE; break; + case OP_LT: op = OP_GT; break; + case OP_LE: op = OP_GE; break; + } // endswitch op + + if (!nop) switch (op) { + case OP_LT: l1--; /* fall through */ + case OP_LE: limit = l1; break; + default: ok = false; + } // endswitch op + + else switch (op) { + case OP_GE: l1--; /* fall through */ + case OP_GT: limit = l1; break; + default: ok = false; + } // endswitch op + + limit = MY_MIN(MY_MAX(0, limit), Size); + + // Just one where clause such as Rowid < limit; + if (ok) + To_Filter = NULL; + + } else + limit = Size; + + } else if ((op == OP_AND && !nop) || (op == OP_OR && nop)) { + l1 = TestFilter((PFIL)filp->Arg(0), nop); + l2 = TestFilter((PFIL)filp->Arg(1), nop); + limit = MY_MIN(l1, l2); + } else if (op == OP_NOT) + limit = TestFilter((PFIL)filp->Arg(0), !nop); + + return limit; + } // end of TestFilter + +/***********************************************************************/ +/* Allocate source column description block. */ +/***********************************************************************/ +PCOL TDBVIR::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n) + { + PCOL colp = NULL; + + if (cdp->IsVirtual()) { + colp = new(g) VIRCOL(cdp, this, cprec, n); + } else strcpy(g->Message, + "Virtual tables accept only special or virtual columns"); + + return colp; + } // end of MakeCol + +/***********************************************************************/ +/* VIR Access Method opening routine. */ +/***********************************************************************/ +bool TDBVIR::OpenDB(PGLOBAL g) + { + if (Use == USE_OPEN) { + // Table already open + N = -1; + return false; + } // endif use + + if (Mode != MODE_READ) { + strcpy(g->Message, "Virtual tables are read only"); + return true; + } // endif Mode + + /*********************************************************************/ + /* Analyze the filter and refine Size accordingly. */ + /*********************************************************************/ + if (To_Filter) + Size = TestFilter(To_Filter, false); + + return false; + } // end of OpenDB + +/***********************************************************************/ +/* Data Base read routine for the VIR access method. */ +/***********************************************************************/ +int TDBVIR::ReadDB(PGLOBAL) + { + return (++N >= Size) ? RC_EF : RC_OK; + } // end of ReadDB + +/***********************************************************************/ +/* WriteDB: Data Base write routine for the VIR access methods. */ +/***********************************************************************/ +int TDBVIR::WriteDB(PGLOBAL g) + { + snprintf(g->Message, sizeof(g->Message), MSG(VIR_READ_ONLY), To_Def->GetType()); + return RC_FX; + } // end of WriteDB + +/***********************************************************************/ +/* Data Base delete line routine for the VIR access methods. */ +/***********************************************************************/ +int TDBVIR::DeleteDB(PGLOBAL g, int) + { + snprintf(g->Message, sizeof(g->Message), MSG(VIR_NO_DELETE), To_Def->GetType()); + return RC_FX; + } // end of DeleteDB + +/* ---------------------------- VIRCOL ------------------------------- */ + +/***********************************************************************/ +/* VIRCOL public constructor. */ +/***********************************************************************/ +VIRCOL::VIRCOL(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 + + } // end of VIRCOL constructor + +/***********************************************************************/ +/* ReadColumn: */ +/***********************************************************************/ +void VIRCOL::ReadColumn(PGLOBAL g) + { + // This should never be called + snprintf(g->Message, sizeof(g->Message), "ReadColumn: Column %s is not virtual", Name); + throw (int)TYPE_COLBLK; +} // end of ReadColumn + +/* ---------------------------TDBVICL class -------------------------- */ + +/***********************************************************************/ +/* GetResult: Get the list the VIRTUAL table columns. */ +/***********************************************************************/ +PQRYRES TDBVICL::GetResult(PGLOBAL g) + { + return VirColumns(g, false); + } // end of GetResult + +/* ------------------------- End of Virtual -------------------------- */ |