You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

606 lines
20 KiB

  1. /************** Table C++ Functions Source Code File (.CPP) ************/
  2. /* Name: TABLE.CPP Version 2.6 */
  3. /* */
  4. /* (C) Copyright to the author Olivier BERTRAND 1999-2013 */
  5. /* */
  6. /* This file contains the TBX, TDB and OPJOIN classes functions. */
  7. /***********************************************************************/
  8. /***********************************************************************/
  9. /* Include relevant MariaDB header file. */
  10. /***********************************************************************/
  11. #include "my_global.h"
  12. /***********************************************************************/
  13. /* Include required application header files */
  14. /* global.h is header containing all global Plug declarations. */
  15. /* plgdbsem.h is header containing the DB applic. declarations. */
  16. /* xobject.h is header containing XOBJECT derived classes declares. */
  17. /***********************************************************************/
  18. #include "global.h"
  19. #include "plgdbsem.h"
  20. #include "xtable.h"
  21. #include "tabcol.h"
  22. #include "filamtxt.h"
  23. #include "tabdos.h"
  24. //#include "catalog.h"
  25. #include "reldef.h"
  26. int TDB::Tnum = 0;
  27. extern "C" int trace; // The general trace value
  28. /***********************************************************************/
  29. /* Utility routines. */
  30. /***********************************************************************/
  31. void NewPointer(PTABS, void *, void *);
  32. void AddPointer(PTABS, void *);
  33. /* ---------------------------- class TBX ---------------------------- */
  34. /***********************************************************************/
  35. /* TBX public constructors. */
  36. /***********************************************************************/
  37. TBX::TBX(void)
  38. {
  39. Use = USE_NO;
  40. To_Orig = NULL;
  41. To_Filter = NULL;
  42. } // end of TBX constructor
  43. TBX::TBX(PTBX txp)
  44. {
  45. Use = txp->Use;
  46. To_Orig = txp;
  47. To_Filter = NULL;
  48. } // end of TBX copy constructor
  49. // Methods
  50. /* ---------------------------- class TDB ---------------------------- */
  51. /***********************************************************************/
  52. /* TDB public constructors. */
  53. /***********************************************************************/
  54. TDB::TDB(PTABDEF tdp) : Tdb_No(++Tnum)
  55. {
  56. Next = NULL;
  57. Name = (tdp) ? tdp->GetName() : NULL;
  58. To_Table = NULL;
  59. Columns = NULL;
  60. Degree = (tdp) ? tdp->GetDegree() : 0;
  61. Mode = MODE_READ;
  62. } // end of TDB standard constructor
  63. TDB::TDB(PTDB tdbp) : TBX(tdbp), Tdb_No(++Tnum)
  64. {
  65. Next = NULL;
  66. Name = tdbp->Name;
  67. To_Table = tdbp->To_Table;
  68. Columns = NULL;
  69. Degree = tdbp->Degree;
  70. Mode = tdbp->Mode;
  71. } // end of TDB copy constructor
  72. /***********************************************************************/
  73. /* OpenTable: Call AM open routine. */
  74. /***********************************************************************/
  75. bool TDB::OpenTable(PGLOBAL g, PSQL sqlp, MODE mode)
  76. {
  77. if (trace)
  78. htrc("Open Tdb_No=%d use=%d type=%d tdb.Mode=%d mode=%d\n",
  79. Tdb_No, Use, GetAmType(), Mode, mode);
  80. switch (Use) {
  81. case USE_LIN:
  82. /*****************************************************************/
  83. /* If table is read/only, only MODE_READ is allowed. */
  84. /*****************************************************************/
  85. if (IsReadOnly() && mode != MODE_READ) {
  86. strcpy(g->Message, MSG(READ_ONLY));
  87. return true;
  88. } // endif ReadOnly
  89. /*****************************************************************/
  90. /* This could be done in any order. */
  91. /* Note: for not Read only first table in open in that mode. */
  92. /*****************************************************************/
  93. if (Next)
  94. Next->OpenTable(g, sqlp, MODE_READ);
  95. Mode = mode;
  96. /*****************************************************************/
  97. /* Pre-opening is done, allocate select buffers now. */
  98. /*****************************************************************/
  99. Use = USE_READY;
  100. break;
  101. case USE_READY:
  102. /*****************************************************************/
  103. /* This is to open files in reverse order. */
  104. /*****************************************************************/
  105. if (Next)
  106. if (Next->OpenTable(g, sqlp, mode))
  107. return true;
  108. /*****************************************************************/
  109. /* This was moved after filter conversion so filtering can be */
  110. /* done when making index tables for DOS files. */
  111. /* Also it was moved after allocating select buffers so some */
  112. /* data can be pre-read during open to allow storage sorting. */
  113. /*****************************************************************/
  114. if (OpenDB(g)) // Do open the table file
  115. return true;
  116. Use = USE_OPEN;
  117. break;
  118. case USE_OPEN:
  119. /*****************************************************************/
  120. /* Table is already open. */
  121. /* Call open routine that will just "rewind" the files. */
  122. /*****************************************************************/
  123. if (OpenDB(g)) // Rewind the table file
  124. return true;
  125. break;
  126. default:
  127. sprintf(g->Message, MSG(TDB_USE_ERROR), Use);
  128. return true;
  129. } // endswitch Use
  130. return false;
  131. } // end of OpenTable
  132. /***********************************************************************/
  133. /* CloseTable: Close a table of any AM type. */
  134. /***********************************************************************/
  135. void TDB::CloseTable(PGLOBAL g)
  136. {
  137. if (trace)
  138. htrc("CloseTable: tdb_no %d use=%d amtype=%d am.Mode=%d\n",
  139. Tdb_No, Use, GetAmType(), Mode);
  140. CloseDB(g);
  141. Use = USE_READY; // x'7FFD'
  142. Mode = MODE_ANY;
  143. } // end of CloseTable
  144. // Methods
  145. /***********************************************************************/
  146. /* RowNumber: returns the current row ordinal number. */
  147. /***********************************************************************/
  148. int TDB::RowNumber(PGLOBAL g, bool b)
  149. {
  150. sprintf(g->Message, MSG(ROWID_NOT_IMPL), GetAmName(g, GetAmType()));
  151. return 0;
  152. } // end of RowNumber
  153. PTBX TDB::Copy(PTABS t)
  154. {
  155. PTDB tp, tdb1, tdb2 = NULL, outp = NULL;
  156. //PGLOBAL g = t->G; // Is this really useful ???
  157. for (tdb1 = this; tdb1; tdb1 = tdb1->Next) {
  158. tp = tdb1->CopyOne(t);
  159. if (!outp)
  160. outp = tp;
  161. else
  162. tdb2->Next = tp;
  163. tdb2 = tp;
  164. NewPointer(t, tdb1, tdb2);
  165. } // endfor tdb1
  166. return outp;
  167. } // end of Copy
  168. void TDB::Print(PGLOBAL g, FILE *f, uint n)
  169. {
  170. PCOL cp;
  171. char m[64];
  172. memset(m, ' ', n); // Make margin string
  173. m[n] = '\0';
  174. for (PTDB tp = this; tp; tp = tp->Next) {
  175. fprintf(f, "%sTDB (%p) %s no=%d use=%d type=%d\n", m,
  176. tp, tp->Name, tp->Tdb_No, tp->Use, tp->GetAmType());
  177. tp->PrintAM(f, m);
  178. fprintf(f, "%s Columns (deg=%d):\n", m, tp->Degree);
  179. for (cp = tp->Columns; cp; cp = cp->GetNext())
  180. cp->Print(g, f, n);
  181. } /* endfor tp */
  182. } // end of Print
  183. void TDB::Print(PGLOBAL g, char *ps, uint z)
  184. {
  185. sprintf(ps, "R%d.%s", Tdb_No, Name);
  186. } // end of Print
  187. /* -------------------------- class TDBASE --------------------------- */
  188. /***********************************************************************/
  189. /* Implementation of the TDBASE class. This is the base class to all */
  190. /* classes for tables that can be joined together. */
  191. /***********************************************************************/
  192. TDBASE::TDBASE(PTABDEF tdp) : TDB(tdp)
  193. {
  194. To_Def = tdp;
  195. To_Link = NULL;
  196. To_Key_Col = NULL;
  197. To_Kindex = NULL;
  198. To_SetCols = NULL;
  199. MaxSize = -1;
  200. Knum = 0;
  201. Read_Only = (tdp) ? tdp->IsReadOnly() : false;
  202. m_data_charset= (tdp) ? tdp->data_charset() : NULL;
  203. } // end of TDBASE constructor
  204. TDBASE::TDBASE(PTDBASE tdbp) : TDB(tdbp)
  205. {
  206. To_Def = tdbp->To_Def;
  207. To_SetCols = tdbp->To_SetCols; // ???
  208. MaxSize = tdbp->MaxSize;
  209. Read_Only = tdbp->Read_Only;
  210. m_data_charset= tdbp->m_data_charset;
  211. } // end of TDBASE copy constructor
  212. /***********************************************************************/
  213. /* Return the pointer on the DB catalog this table belongs to. */
  214. /***********************************************************************/
  215. PCATLG TDBASE::GetCat(void)
  216. {
  217. return (To_Def) ? To_Def->GetCat() : NULL;
  218. } // end of GetCat
  219. /***********************************************************************/
  220. /* Return the datapath of the DB this table belongs to. */
  221. /***********************************************************************/
  222. PSZ TDBASE::GetPath(void)
  223. {
  224. return To_Def->GetPath();
  225. } // end of GetPath
  226. /***********************************************************************/
  227. /* Initialize TDBASE based column description block construction. */
  228. /* name is used to call columns by name. */
  229. /* num is used by TBL to construct columns by index number. */
  230. /* Note: name=Null and num=0 for constructing all columns (select *) */
  231. /***********************************************************************/
  232. PCOL TDBASE::ColDB(PGLOBAL g, PSZ name, int num)
  233. {
  234. int i;
  235. PCOLDEF cdp;
  236. PCOL cp, colp = NULL, cprec = NULL;
  237. if (trace)
  238. htrc("ColDB: am=%d colname=%s tabname=%s num=%d\n",
  239. GetAmType(), SVP(name), Name, num);
  240. for (cdp = To_Def->GetCols(), i = 1; cdp; cdp = cdp->GetNext(), i++)
  241. if ((!name && !num) ||
  242. (name && !stricmp(cdp->GetName(), name)) || num == i) {
  243. /*****************************************************************/
  244. /* Check for existence of desired column. */
  245. /* Also find where to insert the new block. */
  246. /*****************************************************************/
  247. for (cp = Columns; cp; cp = cp->GetNext())
  248. if (cp->GetIndex() < i)
  249. cprec = cp;
  250. else if (cp->GetIndex() == i)
  251. break;
  252. if (trace)
  253. htrc("cdp(%d).Name=%s cp=%p\n", i, cdp->GetName(), cp);
  254. /*****************************************************************/
  255. /* Now take care of Column Description Block. */
  256. /*****************************************************************/
  257. if (cp)
  258. colp = cp;
  259. else
  260. colp = MakeCol(g, cdp, cprec, i);
  261. if (trace)
  262. htrc("colp=%p\n", colp);
  263. if (name || num)
  264. break;
  265. else if (colp)
  266. cprec = colp;
  267. } // endif Name
  268. return (colp);
  269. } // end of ColDB
  270. /***********************************************************************/
  271. /* InsertSpecialColumn: Put a special column ahead of the column list.*/
  272. /***********************************************************************/
  273. PCOL TDBASE::InsertSpecialColumn(PGLOBAL g, PCOL colp)
  274. {
  275. if (!colp->IsSpecial())
  276. return NULL;
  277. colp->SetNext(Columns);
  278. Columns = colp;
  279. return colp;
  280. } // end of InsertSpecialColumn
  281. /***********************************************************************/
  282. /* Make a special COLBLK to insert in a table. */
  283. /***********************************************************************/
  284. PCOL TDBASE::InsertSpcBlk(PGLOBAL g, PCOLUMN cp)
  285. {
  286. char *name = (char*)cp->GetName();
  287. PCOL colp;
  288. if (!strcmp(name, "FILEID")) {
  289. // !strcmp(name, "SERVID")) {
  290. if (!To_Def || !(To_Def->GetPseudo() & 2)) {
  291. sprintf(g->Message, MSG(BAD_SPEC_COLUMN));
  292. return NULL;
  293. } // endif Pseudo
  294. // if (!strcmp(name, "FILEID"))
  295. colp = new(g) FIDBLK(cp);
  296. // else
  297. // colp = new(g) SIDBLK(cp);
  298. } else if (!strcmp(name, "TABID")) {
  299. colp = new(g) TIDBLK(cp);
  300. //} else if (!strcmp(name, "CONID")) {
  301. // colp = new(g) CIDBLK(cp);
  302. } else if (!strcmp(name, "ROWID")) {
  303. colp = new(g) RIDBLK(cp, false);
  304. } else if (!strcmp(name, "ROWNUM")) {
  305. colp = new(g) RIDBLK(cp, true);
  306. } else {
  307. sprintf(g->Message, MSG(BAD_SPECIAL_COL), name);
  308. return NULL;
  309. } // endif's name
  310. if (!(colp = InsertSpecialColumn(g, colp))) {
  311. sprintf(g->Message, MSG(BAD_SPECIAL_COL), name);
  312. return NULL;
  313. } // endif Insert
  314. return (colp);
  315. } // end of InsertSpcBlk
  316. /***********************************************************************/
  317. /* ResetTableOpt: Wrong for this table type. */
  318. /***********************************************************************/
  319. int TDBASE::ResetTableOpt(PGLOBAL g, bool dox)
  320. {
  321. strcpy(g->Message, "This table is not indexable");
  322. return RC_INFO;
  323. } // end of ResetTableOpt
  324. /***********************************************************************/
  325. /* SetKindex: set or reset the index pointer. */
  326. /***********************************************************************/
  327. void TDBASE::SetKindex(PKXBASE kxp)
  328. {
  329. if (To_Kindex)
  330. To_Kindex->Close(); // Discard old index
  331. To_Kindex = kxp;
  332. } // end of SetKindex
  333. /***********************************************************************/
  334. /* SetRecpos: Replace the table at the specified position. */
  335. /***********************************************************************/
  336. bool TDBASE::SetRecpos(PGLOBAL g, int recpos)
  337. {
  338. strcpy(g->Message, MSG(SETRECPOS_NIY));
  339. return true;
  340. } // end of SetRecpos
  341. /***********************************************************************/
  342. /* Methods */
  343. /***********************************************************************/
  344. void TDBASE::PrintAM(FILE *f, char *m)
  345. {
  346. fprintf(f, "%s AM(%d): mode=%d\n", m, GetAmType(), Mode);
  347. } // end of PrintAM
  348. /***********************************************************************/
  349. /* Marks DOS/MAP table columns used in internal joins. */
  350. /* tdb2 is the top of tree or first tdb in chained tdb's and tdbp */
  351. /* points to the currently marked tdb. */
  352. /* Two questions here: exact meaning of U_J_INT ? */
  353. /* Why is the eventual reference to To_Key_Col not marked U_J_EXT ? */
  354. /***********************************************************************/
  355. void TDBASE::MarkDB(PGLOBAL g, PTDB tdb2)
  356. {
  357. if (trace)
  358. htrc("DOS MarkDB: tdbp=%p tdb2=%p\n", this, tdb2);
  359. } // end of MarkDB
  360. /* ---------------------------TDBCAT class --------------------------- */
  361. /***********************************************************************/
  362. /* Implementation of the TDBCAT class. */
  363. /***********************************************************************/
  364. TDBCAT::TDBCAT(PTABDEF tdp) : TDBASE(tdp)
  365. {
  366. Qrp = NULL;
  367. Init = false;
  368. N = -1;
  369. } // end of TDBCAT constructor
  370. /***********************************************************************/
  371. /* Allocate CAT column description block. */
  372. /***********************************************************************/
  373. PCOL TDBCAT::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
  374. {
  375. PCATCOL colp;
  376. colp = (PCATCOL)new(g) CATCOL(cdp, this, n);
  377. if (cprec) {
  378. colp->SetNext(cprec->GetNext());
  379. cprec->SetNext(colp);
  380. } else {
  381. colp->SetNext(Columns);
  382. Columns = colp;
  383. } // endif cprec
  384. return colp;
  385. } // end of MakeCol
  386. /***********************************************************************/
  387. /* Initialize: Get the result query block. */
  388. /***********************************************************************/
  389. bool TDBCAT::Initialize(PGLOBAL g)
  390. {
  391. if (Init)
  392. return false;
  393. if (!(Qrp = GetResult(g)))
  394. return true;
  395. Init = true;
  396. return false;
  397. } // end of Initialize
  398. /***********************************************************************/
  399. /* CAT: Get the number of properties. */
  400. /***********************************************************************/
  401. int TDBCAT::GetMaxSize(PGLOBAL g)
  402. {
  403. if (MaxSize < 0) {
  404. if (Initialize(g))
  405. return -1;
  406. MaxSize = Qrp->Nblin;
  407. } // endif MaxSize
  408. return MaxSize;
  409. } // end of GetMaxSize
  410. /***********************************************************************/
  411. /* CAT Access Method opening routine. */
  412. /***********************************************************************/
  413. bool TDBCAT::OpenDB(PGLOBAL g)
  414. {
  415. if (Use == USE_OPEN) {
  416. /*******************************************************************/
  417. /* Table already open. */
  418. /*******************************************************************/
  419. N = -1;
  420. return false;
  421. } // endif use
  422. if (Mode != MODE_READ) {
  423. /*******************************************************************/
  424. /* ODBC Info tables cannot be modified. */
  425. /*******************************************************************/
  426. strcpy(g->Message, "CAT tables are read only");
  427. return true;
  428. } // endif Mode
  429. /*********************************************************************/
  430. /* Initialize the ODBC processing. */
  431. /*********************************************************************/
  432. if (Initialize(g))
  433. return true;
  434. return InitCol(g);
  435. } // end of OpenDB
  436. /***********************************************************************/
  437. /* Initialize columns. */
  438. /***********************************************************************/
  439. bool TDBCAT::InitCol(PGLOBAL g)
  440. {
  441. PCATCOL colp;
  442. PCOLRES crp;
  443. for (colp = (PCATCOL)Columns; colp; colp = (PCATCOL)colp->GetNext()) {
  444. for (crp = Qrp->Colresp; crp; crp = crp->Next)
  445. if ((colp->Flag && colp->Flag == crp->Fld) ||
  446. (!colp->Flag && !stricmp(colp->Name, crp->Name))) {
  447. colp->Crp = crp;
  448. break;
  449. } // endif Flag
  450. if (!colp->Crp /*&& !colp->GetValue()->IsConstant()*/) {
  451. sprintf(g->Message, "Invalid flag %d for column %s",
  452. colp->Flag, colp->Name);
  453. return true;
  454. } // endif Crp
  455. } // endfor colp
  456. return false;
  457. } // end of InitCol
  458. /***********************************************************************/
  459. /* Data Base read routine for CAT access method. */
  460. /***********************************************************************/
  461. int TDBCAT::ReadDB(PGLOBAL g)
  462. {
  463. return (++N < Qrp->Nblin) ? RC_OK : RC_EF;
  464. } // end of ReadDB
  465. /***********************************************************************/
  466. /* WriteDB: Data Base write routine for CAT access methods. */
  467. /***********************************************************************/
  468. int TDBCAT::WriteDB(PGLOBAL g)
  469. {
  470. strcpy(g->Message, "CAT tables are read only");
  471. return RC_FX;
  472. } // end of WriteDB
  473. /***********************************************************************/
  474. /* Data Base delete line routine for CAT access methods. */
  475. /***********************************************************************/
  476. int TDBCAT::DeleteDB(PGLOBAL g, int irc)
  477. {
  478. strcpy(g->Message, "Delete not enabled for CAT tables");
  479. return RC_FX;
  480. } // end of DeleteDB
  481. /***********************************************************************/
  482. /* Data Base close routine for WMI access method. */
  483. /***********************************************************************/
  484. void TDBCAT::CloseDB(PGLOBAL g)
  485. {
  486. // Nothing to do
  487. } // end of CloseDB
  488. // ------------------------ CATCOL functions ----------------------------
  489. /***********************************************************************/
  490. /* CATCOL public constructor. */
  491. /***********************************************************************/
  492. CATCOL::CATCOL(PCOLDEF cdp, PTDB tdbp, int n)
  493. : COLBLK(cdp, tdbp, n)
  494. {
  495. Tdbp = (PTDBCAT)tdbp;
  496. Crp = NULL;
  497. Flag = cdp->GetOffset();
  498. } // end of WMICOL constructor
  499. /***********************************************************************/
  500. /* Read the next Data Source elements. */
  501. /***********************************************************************/
  502. void CATCOL::ReadColumn(PGLOBAL g)
  503. {
  504. // Get the value of the Name or Description property
  505. Value->SetValue_pvblk(Crp->Kdata, Tdbp->N);
  506. } // end of ReadColumn