mirror of
https://github.com/MariaDB/server.git
synced 2025-01-17 12:32:27 +01:00
305 lines
11 KiB
C++
305 lines
11 KiB
C++
/************* 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--;
|
|
case OP_LE: limit = l1; break;
|
|
default: ok = false;
|
|
} // endswitch op
|
|
|
|
else switch (op) {
|
|
case OP_GE: l1--;
|
|
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)
|
|
{
|
|
sprintf(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)
|
|
{
|
|
sprintf(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
|
|
sprintf(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 -------------------------- */
|