| 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 | /***********************************************************************/ |
| 32 | PQRYRES 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 | /***********************************************************************/ |
| 98 | PTDB 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 | /***********************************************************************/ |
| 113 | TDBVIR::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 | /***********************************************************************/ |
| 125 | int 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 | /***********************************************************************/ |
| 204 | PCOL 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 | /***********************************************************************/ |
| 219 | bool 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 | /***********************************************************************/ |
| 244 | int 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 | /***********************************************************************/ |
| 252 | int 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 | /***********************************************************************/ |
| 261 | int 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 | /***********************************************************************/ |
| 272 | VIRCOL::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 | /***********************************************************************/ |
| 288 | void 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 | /***********************************************************************/ |
| 300 | PQRYRES TDBVICL::GetResult(PGLOBAL g) |
| 301 | { |
| 302 | return VirColumns(g, false); |
| 303 | } // end of GetResult |
| 304 | |
| 305 | /* ------------------------- End of Virtual -------------------------- */ |
| 306 | |