1/************* tdbvir C++ Program Source Code File (.CPP) **************/
2/* PROGRAM NAME: tdbvir.cpp Version 1.2 */
3/* (C) Copyright to the author Olivier BERTRAND 2014-2017 */
4/* This program are the VIR classes DB execution routines. */
5/***********************************************************************/
6
7/***********************************************************************/
8/* Include relevant sections of the MariaDB header file. */
9/***********************************************************************/
10#include <my_global.h>
11
12/***********************************************************************/
13/* Include application header files: */
14/* global.h is header containing all global declarations. */
15/* plgdbsem.h is header containing the DB application declarations. */
16/* xtable.h is header containing the TDBASE declarations. */
17/* tdbvir.h is header containing the VIR classes declarations. */
18/***********************************************************************/
19#include "global.h"
20#include "plgdbsem.h"
21#include "filter.h"
22#include "xtable.h"
23//#include "reldef.h"
24#include "colblk.h"
25#include "mycat.h" // for FNC_COL
26#include "tabvir.h"
27#include "resource.h" // for IDS_COLUMNS
28
29/***********************************************************************/
30/* Return the unique column definition to MariaDB. */
31/***********************************************************************/
32PQRYRES VirColumns(PGLOBAL g, bool info)
33 {
34 int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING,
35 TYPE_INT, TYPE_STRING, TYPE_STRING};
36 XFLD fldtyp[] = {FLD_NAME, FLD_TYPE, FLD_TYPENAME,
37 FLD_PREC, FLD_KEY, FLD_EXTRA};
38 unsigned int length[] = {8, 4, 16, 4, 16, 16};
39 int i, n, ncol = sizeof(buftyp) / sizeof(int);
40 PQRYRES qrp;
41 PCOLRES crp;
42
43 n = (info) ? 0 : 1;
44
45 /**********************************************************************/
46 /* Allocate the structures used to refer to the result set. */
47 /**********************************************************************/
48 if (!(qrp = PlgAllocResult(g, ncol, n, IDS_COLUMNS + 3,
49 buftyp, fldtyp, length, false, true)))
50 return NULL;
51
52 // Some columns must be renamed before info
53 for (i = 0, crp = qrp->Colresp; crp; crp = crp->Next)
54 switch (++i) {
55 case 5: crp->Name = "Key"; break;
56 case 6: crp->Name = "Extra"; break;
57 } // endswitch i
58
59 if (info)
60 return qrp;
61
62 /**********************************************************************/
63 /* Now get the results into blocks. */
64 /**********************************************************************/
65 // Set column name
66 crp = qrp->Colresp; // Column_Name
67 crp->Kdata->SetValue("n", 0);
68
69 // Set type, type name, precision
70 crp = crp->Next; // Data_Type
71 crp->Kdata->SetValue(TYPE_INT, 0);
72
73 crp = crp->Next; // Type_Name
74 crp->Kdata->SetValue(GetTypeName(TYPE_INT), 0);
75
76 crp = crp->Next; // Precision
77 crp->Kdata->SetValue(11, 0);
78
79 crp = crp->Next; // Key
80 crp->Kdata->SetValue("KEY", 0);
81
82 crp = crp->Next; // Extra
83 crp->Kdata->SetValue("SPECIAL=ROWID", 0);
84
85 qrp->Nblin = 1;
86
87 /**********************************************************************/
88 /* Return the result pointer for use by discovery routines. */
89 /**********************************************************************/
90 return qrp;
91 } // end of VirColumns
92
93/* --------------------------- Class VIRDEF --------------------------- */
94
95/***********************************************************************/
96/* GetTable: makes a new Table Description Block. */
97/***********************************************************************/
98PTDB VIRDEF::GetTable(PGLOBAL g, MODE)
99 {
100 // Column blocks will be allocated only when needed.
101 if (Catfunc == FNC_COL)
102 return new(g) TDBVICL(this);
103 else
104 return new(g) TDBVIR(this);
105
106 } // end of GetTable
107
108/* ------------------------ TDBVIR functions ------------------------- */
109
110/***********************************************************************/
111/* Implementation of the TDBVIR class. */
112/***********************************************************************/
113TDBVIR::TDBVIR(PVIRDEF tdp) : TDBASE(tdp)
114 {
115 Size = (tdp->GetElemt()) ? tdp->GetElemt() : 1;
116 N = -1;
117 } // end of TDBVIR constructor
118
119/***********************************************************************/
120/* Analyze the filter and reset the size limit accordingly. */
121/* This is possible when a filter contains predicates implying the */
122/* special column ROWID. Here we just test for when no more good */
123/* records can be met in the remaining of the table. */
124/***********************************************************************/
125int TDBVIR::TestFilter(PFIL filp, bool nop)
126 {
127 int i, op = filp->GetOpc(), n = 0, type[2] = {0,0};
128 int l1 = 0, l2, limit = Size;
129 PXOB arg[2] = {NULL,NULL};
130
131 if (op == OP_GT || op == OP_GE || op == OP_LT || op == OP_LE) {
132 for (i = 0; i < 2; i++) {
133 arg[i] = filp->Arg(i);
134
135 switch (filp->GetArgType(i)) {
136 case TYPE_CONST:
137 if ((l1 = arg[i]->GetIntValue()) >= 0)
138 type[i] = 1;
139
140 break;
141 case TYPE_COLBLK:
142 if (((PCOL)arg[i])->GetTo_Tdb() == this &&
143 ((PCOL)arg[i])->GetAmType() == TYPE_AM_ROWID)
144 type[i] = 2;
145
146 break;
147 default:
148 break;
149 } // endswitch ArgType
150
151 if (!type[i])
152 break;
153
154 n += type[i];
155 } // endfor i
156
157 if (n == 3) {
158 // If true it will be ok to delete the filter
159 BOOL ok = (filp == To_Filter);
160
161 if (type[0] == 1)
162 // Make it always a Column-op-Value
163 switch (op) {
164 case OP_GT: op = OP_LT; break;
165 case OP_GE: op = OP_LE; break;
166 case OP_LT: op = OP_GT; break;
167 case OP_LE: op = OP_GE; break;
168 } // endswitch op
169
170 if (!nop) switch (op) {
171 case OP_LT: l1--;
172 case OP_LE: limit = l1; break;
173 default: ok = false;
174 } // endswitch op
175
176 else switch (op) {
177 case OP_GE: l1--;
178 case OP_GT: limit = l1; break;
179 default: ok = false;
180 } // endswitch op
181
182 limit = MY_MIN(MY_MAX(0, limit), Size);
183
184 // Just one where clause such as Rowid < limit;
185 if (ok)
186 To_Filter = NULL;
187
188 } else
189 limit = Size;
190
191 } else if ((op == OP_AND && !nop) || (op == OP_OR && nop)) {
192 l1 = TestFilter((PFIL)filp->Arg(0), nop);
193 l2 = TestFilter((PFIL)filp->Arg(1), nop);
194 limit = MY_MIN(l1, l2);
195 } else if (op == OP_NOT)
196 limit = TestFilter((PFIL)filp->Arg(0), !nop);
197
198 return limit;
199 } // end of TestFilter
200
201/***********************************************************************/
202/* Allocate source column description block. */
203/***********************************************************************/
204PCOL TDBVIR::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
205 {
206 PCOL colp = NULL;
207
208 if (cdp->IsVirtual()) {
209 colp = new(g) VIRCOL(cdp, this, cprec, n);
210 } else strcpy(g->Message,
211 "Virtual tables accept only special or virtual columns");
212
213 return colp;
214 } // end of MakeCol
215
216/***********************************************************************/
217/* VIR Access Method opening routine. */
218/***********************************************************************/
219bool TDBVIR::OpenDB(PGLOBAL g)
220 {
221 if (Use == USE_OPEN) {
222 // Table already open
223 N = -1;
224 return false;
225 } // endif use
226
227 if (Mode != MODE_READ) {
228 strcpy(g->Message, "Virtual tables are read only");
229 return true;
230 } // endif Mode
231
232 /*********************************************************************/
233 /* Analyze the filter and refine Size accordingly. */
234 /*********************************************************************/
235 if (To_Filter)
236 Size = TestFilter(To_Filter, false);
237
238 return false;
239 } // end of OpenDB
240
241/***********************************************************************/
242/* Data Base read routine for the VIR access method. */
243/***********************************************************************/
244int TDBVIR::ReadDB(PGLOBAL)
245 {
246 return (++N >= Size) ? RC_EF : RC_OK;
247 } // end of ReadDB
248
249/***********************************************************************/
250/* WriteDB: Data Base write routine for the VIR access methods. */
251/***********************************************************************/
252int TDBVIR::WriteDB(PGLOBAL g)
253 {
254 sprintf(g->Message, MSG(VIR_READ_ONLY), To_Def->GetType());
255 return RC_FX;
256 } // end of WriteDB
257
258/***********************************************************************/
259/* Data Base delete line routine for the VIR access methods. */
260/***********************************************************************/
261int TDBVIR::DeleteDB(PGLOBAL g, int)
262 {
263 sprintf(g->Message, MSG(VIR_NO_DELETE), To_Def->GetType());
264 return RC_FX;
265 } // end of DeleteDB
266
267/* ---------------------------- VIRCOL ------------------------------- */
268
269/***********************************************************************/
270/* VIRCOL public constructor. */
271/***********************************************************************/
272VIRCOL::VIRCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ)
273 : COLBLK(cdp, tdbp, i)
274 {
275 if (cprec) {
276 Next = cprec->GetNext();
277 cprec->SetNext(this);
278 } else {
279 Next = tdbp->GetColumns();
280 tdbp->SetColumns(this);
281 } // endif cprec
282
283 } // end of VIRCOL constructor
284
285/***********************************************************************/
286/* ReadColumn: */
287/***********************************************************************/
288void VIRCOL::ReadColumn(PGLOBAL g)
289 {
290 // This should never be called
291 sprintf(g->Message, "ReadColumn: Column %s is not virtual", Name);
292 throw (int)TYPE_COLBLK;
293} // end of ReadColumn
294
295/* ---------------------------TDBVICL class -------------------------- */
296
297/***********************************************************************/
298/* GetResult: Get the list the VIRTUAL table columns. */
299/***********************************************************************/
300PQRYRES TDBVICL::GetResult(PGLOBAL g)
301 {
302 return VirColumns(g, false);
303 } // end of GetResult
304
305/* ------------------------- End of Virtual -------------------------- */
306