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.

286 lines
9.6 KiB

  1. /************* TabXcl CPP Declares Source Code File (.CPP) *************/
  2. /* Name: TABXCL.CPP Version 1.0 */
  3. /* */
  4. /* (C) Copyright to the author Olivier BERTRAND 2013 */
  5. /* */
  6. /* XCOL: Table having one column containing several values */
  7. /* comma separated. When creating the table, the name of the X */
  8. /* column is given by the Name option. */
  9. /* This first version has one limitation: */
  10. /* - The X column has the same length than in the physical file. */
  11. /* This tables produces as many rows for a physical row than the */
  12. /* number of items in the X column (eventually 0). */
  13. /***********************************************************************/
  14. /***********************************************************************/
  15. /* Include relevant section of system dependant header files. */
  16. /***********************************************************************/
  17. #include "my_global.h"
  18. #include "table.h" // MySQL table definitions
  19. #if defined(WIN32)
  20. #include <stdlib.h>
  21. #include <stdio.h>
  22. #if defined(__BORLANDC__)
  23. #define __MFC_COMPAT__ // To define min/max as macro
  24. #endif
  25. //#include <windows.h>
  26. #else
  27. #if defined(UNIX)
  28. #include <fnmatch.h>
  29. #include <errno.h>
  30. #include <stdlib.h>
  31. #include <stdio.h>
  32. #include <string.h>
  33. #include "osutil.h"
  34. #else
  35. //#include <io.h>
  36. #endif
  37. //#include <fcntl.h>
  38. #endif
  39. /***********************************************************************/
  40. /* Include application header files: */
  41. /***********************************************************************/
  42. #include "global.h"
  43. #include "plgdbsem.h"
  44. #include "plgcnx.h" // For DB types
  45. #include "resource.h"
  46. #include "reldef.h"
  47. #include "filamtxt.h"
  48. #include "tabdos.h"
  49. #include "tabcol.h"
  50. #include "tabxcl.h"
  51. #include "xtable.h"
  52. #if defined(MYSQL_SUPPORT)
  53. #include "tabmysql.h"
  54. #endif // MYSQL_SUPPORT
  55. #include "ha_connect.h"
  56. #include "mycat.h"
  57. extern "C" int trace;
  58. /* -------------- Implementation of the XCOL classes ---------------- */
  59. /***********************************************************************/
  60. /* XCLDEF constructor. */
  61. /***********************************************************************/
  62. XCLDEF::XCLDEF(void)
  63. {
  64. Xcol = NULL;
  65. Sep = ',';
  66. Mult = 10;
  67. } // end of XCLDEF constructor
  68. /***********************************************************************/
  69. /* DefineAM: define specific AM block values from XCOL table. */
  70. /***********************************************************************/
  71. bool XCLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
  72. {
  73. char buf[8];
  74. Xcol = Cat->GetStringCatInfo(g, "Colname", "");
  75. Cat->GetCharCatInfo("Separator", ",", buf, sizeof(buf));
  76. Sep = (strlen(buf) == 2 && buf[0] == '\\' && buf[1] == 't') ? '\t' : *buf;
  77. Mult = Cat->GetIntCatInfo("Mult", 10);
  78. return PRXDEF::DefineAM(g, am, poff);
  79. } // end of DefineAM
  80. /***********************************************************************/
  81. /* GetTable: makes a new TDB of the proper type. */
  82. /***********************************************************************/
  83. PTDB XCLDEF::GetTable(PGLOBAL g, MODE mode)
  84. {
  85. if (Catfunc == FNC_COL)
  86. return new(g) TDBTBC(this);
  87. else
  88. return new(g) TDBXCL(this);
  89. } // end of GetTable
  90. /* ------------------------------------------------------------------- */
  91. /***********************************************************************/
  92. /* Implementation of the TDBXCL class. */
  93. /***********************************************************************/
  94. TDBXCL::TDBXCL(PXCLDEF tdp) : TDBPRX(tdp)
  95. {
  96. Xcolumn = tdp->Xcol; // CSV column name
  97. Xcolp = NULL; // To the XCLCOL column
  98. Mult = tdp->Mult; // Multiplication factor
  99. N = 0; // The current table index
  100. M = 0; // The occurence rank
  101. RowFlag = 0; // 0: Ok, 1: Same, 2: Skip
  102. New = TRUE; // TRUE for new line
  103. Sep = tdp->Sep; // The Xcol separator
  104. } // end of TDBXCL constructor
  105. /***********************************************************************/
  106. /* Allocate XCL column description block. */
  107. /***********************************************************************/
  108. PCOL TDBXCL::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
  109. {
  110. PCOL colp;
  111. if (!stricmp(cdp->GetName(), Xcolumn)) {
  112. Xcolp = new(g) XCLCOL(g, cdp, this, cprec, n);
  113. colp = Xcolp;
  114. } else
  115. colp = new(g) PRXCOL(cdp, this, cprec, n);
  116. return colp;
  117. } // end of MakeCol
  118. /***********************************************************************/
  119. /* XCL GetMaxSize: returns the maximum number of rows in the table. */
  120. /***********************************************************************/
  121. int TDBXCL::GetMaxSize(PGLOBAL g)
  122. {
  123. if (MaxSize < 0) {
  124. if (InitTable(g))
  125. return 0;
  126. MaxSize = Mult * Tdbp->GetMaxSize(g);
  127. } // endif MaxSize
  128. return MaxSize;
  129. } // end of GetMaxSize
  130. /***********************************************************************/
  131. /* For this table type, ROWID is the (virtual) row number, */
  132. /* while ROWNUM is be the occurence rank in the multiple column. */
  133. /***********************************************************************/
  134. int TDBXCL::RowNumber(PGLOBAL g, bool b)
  135. {
  136. return (b) ? M : N;
  137. } // end of RowNumber
  138. /***********************************************************************/
  139. /* XCL Access Method opening routine. */
  140. /***********************************************************************/
  141. bool TDBXCL::OpenDB(PGLOBAL g)
  142. {
  143. if (Use == USE_OPEN) {
  144. /*******************************************************************/
  145. /* Table already open, just replace it at its beginning. */
  146. /*******************************************************************/
  147. M = N = 0;
  148. RowFlag = 0;
  149. New = TRUE;
  150. return Tdbp->OpenDB(g);
  151. } // endif use
  152. if (Mode != MODE_READ) {
  153. /*******************************************************************/
  154. /* Currently XCOL tables cannot be modified. */
  155. /*******************************************************************/
  156. strcpy(g->Message, "XCOL tables are read only");
  157. return TRUE;
  158. } // endif Mode
  159. if (InitTable(g))
  160. return TRUE;
  161. /*********************************************************************/
  162. /* Check and initialize the subtable columns. */
  163. /*********************************************************************/
  164. for (PCOL cp = Columns; cp; cp = cp->GetNext())
  165. if (((PXCLCOL)cp)->Init(g))
  166. return TRUE;
  167. /*********************************************************************/
  168. /* Physically open the object table. */
  169. /*********************************************************************/
  170. if (Tdbp->OpenDB(g))
  171. return TRUE;
  172. Use = USE_OPEN;
  173. return FALSE;
  174. } // end of OpenDB
  175. /***********************************************************************/
  176. /* Data Base read routine for XCL access method. */
  177. /***********************************************************************/
  178. int TDBXCL::ReadDB(PGLOBAL g)
  179. {
  180. int rc = RC_OK;
  181. /*********************************************************************/
  182. /* Now start the multi reading process. */
  183. /*********************************************************************/
  184. do {
  185. if (RowFlag != 1) {
  186. if ((rc = Tdbp->ReadDB(g)) != RC_OK)
  187. break;
  188. New = TRUE;
  189. M = 1;
  190. } else {
  191. New = FALSE;
  192. M++;
  193. } // endif RowFlag
  194. if (Xcolp) {
  195. RowFlag = 0;
  196. Xcolp->ReadColumn(g);
  197. } // endif Xcolp
  198. N++;
  199. } while (RowFlag == 2);
  200. return rc;
  201. } // end of ReadDB
  202. // ------------------------ XCLCOL functions ----------------------------
  203. /***********************************************************************/
  204. /* XCLCOL public constructor. */
  205. /***********************************************************************/
  206. XCLCOL::XCLCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i)
  207. : PRXCOL(cdp, tdbp, cprec, i, "XCL")
  208. {
  209. // Set additional XXL access method information for column.
  210. Cbuf = (char*)PlugSubAlloc(g, NULL, Long + 1);
  211. Cp = NULL; // Pointer to current position in Cbuf
  212. Sep = ((PTDBXCL)tdbp)->Sep;
  213. AddStatus(BUF_READ); // Only evaluated from TDBXCL::ReadDB
  214. } // end of XCLCOL constructor
  215. /***********************************************************************/
  216. /* What this routine does is to get the comma-separated string */
  217. /* from the source table column, extract the single values and */
  218. /* set the flag for the table ReadDB function. */
  219. /***********************************************************************/
  220. void XCLCOL::ReadColumn(PGLOBAL g)
  221. {
  222. if (((PTDBXCL)To_Tdb)->New) {
  223. Colp->Eval(g);
  224. strcpy(Cbuf, To_Val->GetCharValue());
  225. Cp = Cbuf;
  226. } // endif New
  227. if (*Cp) {
  228. PSZ p;
  229. // Trim left
  230. for (p = Cp; *p == ' '; p++) ;
  231. if ((Cp = strchr(Cp, Sep)))
  232. // Separator is found
  233. *Cp++ = '\0';
  234. Value->SetValue_psz(p);
  235. } else if (Nullable) {
  236. Value->Reset();
  237. Value->SetNull(true);
  238. } else {
  239. // Skip that row
  240. ((PTDBXCL)To_Tdb)->RowFlag = 2;
  241. Colp->Reset();
  242. } // endif Cp
  243. if (Cp && *Cp)
  244. // More to come from the same row
  245. ((PTDBXCL)To_Tdb)->RowFlag = 1;
  246. } // end of ReadColumn