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