summaryrefslogtreecommitdiffstats
path: root/storage/connect/tabxcl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'storage/connect/tabxcl.cpp')
-rw-r--r--storage/connect/tabxcl.cpp298
1 files changed, 298 insertions, 0 deletions
diff --git a/storage/connect/tabxcl.cpp b/storage/connect/tabxcl.cpp
new file mode 100644
index 00000000..d354f556
--- /dev/null
+++ b/storage/connect/tabxcl.cpp
@@ -0,0 +1,298 @@
+/************* TabXcl CPP Declares Source Code File (.CPP) *************/
+/* Name: TABXCL.CPP Version 1.0 */
+/* */
+/* (C) Copyright to the author Olivier BERTRAND 2013-2017 */
+/* */
+/* XCOL: Table having one column containing several values */
+/* comma separated. When creating the table, the name of the X */
+/* column is given by the Name option. */
+/* This first version has one limitation: */
+/* - The X column has the same length than in the physical file. */
+/* This tables produces as many rows for a physical row than the */
+/* number of items in the X column (eventually 0). */
+/***********************************************************************/
+
+/***********************************************************************/
+/* Include relevant section of system dependant header files. */
+/***********************************************************************/
+#include "my_global.h"
+#include "table.h" // MySQL table definitions
+#if defined(_WIN32)
+#include <stdlib.h>
+#include <stdio.h>
+#if defined(__BORLANDC__)
+#define __MFC_COMPAT__ // To define min/max as macro
+#endif
+//#include <windows.h>
+#else
+#if defined(UNIX)
+#include <fnmatch.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "osutil.h"
+#else
+//#include <io.h>
+#endif
+//#include <fcntl.h>
+#endif
+
+/***********************************************************************/
+/* Include application header files: */
+/***********************************************************************/
+#include "global.h"
+#include "plgdbsem.h"
+#include "plgcnx.h" // For DB types
+#include "resource.h"
+#include "xtable.h"
+#include "tabext.h"
+#include "filamtxt.h"
+#include "tabdos.h"
+#include "tabcol.h"
+#include "tabxcl.h"
+#include "tabmysql.h"
+#include "ha_connect.h"
+
+/* -------------- Implementation of the XCOL classes ---------------- */
+
+/***********************************************************************/
+/* XCLDEF constructor. */
+/***********************************************************************/
+XCLDEF::XCLDEF(void)
+ {
+ Xcol = NULL;
+ Sep = ',';
+ Mult = 10;
+} // end of XCLDEF constructor
+
+/***********************************************************************/
+/* DefineAM: define specific AM block values from XCOL table. */
+/***********************************************************************/
+bool XCLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
+ {
+ char buf[8];
+
+ Xcol = GetStringCatInfo(g, "Colname", "");
+ GetCharCatInfo("Separator", ",", buf, sizeof(buf));
+ Sep = (strlen(buf) == 2 && buf[0] == '\\' && buf[1] == 't') ? '\t' : *buf;
+ Mult = GetIntCatInfo("Mult", 10);
+ return PRXDEF::DefineAM(g, am, poff);
+ } // end of DefineAM
+
+/***********************************************************************/
+/* GetTable: makes a new TDB of the proper type. */
+/***********************************************************************/
+PTDB XCLDEF::GetTable(PGLOBAL g, MODE)
+ {
+ if (Catfunc == FNC_COL)
+ return new(g) TDBTBC(this);
+ else
+ return new(g) TDBXCL(this);
+
+ } // end of GetTable
+
+/* ------------------------------------------------------------------- */
+
+/***********************************************************************/
+/* Implementation of the TDBXCL class. */
+/***********************************************************************/
+TDBXCL::TDBXCL(PXCLDEF tdp) : TDBPRX(tdp)
+ {
+ Xcolumn = tdp->Xcol; // CSV column name
+ Xcolp = NULL; // To the XCLCOL column
+ Mult = tdp->Mult; // Multiplication factor
+ N = 0; // The current table index
+ M = 0; // The occurrence rank
+ RowFlag = 0; // 0: Ok, 1: Same, 2: Skip
+ New = TRUE; // TRUE for new line
+ Sep = tdp->Sep; // The Xcol separator
+ } // end of TDBXCL constructor
+
+/***********************************************************************/
+/* Allocate XCL column description block. */
+/***********************************************************************/
+PCOL TDBXCL::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
+ {
+ PCOL colp;
+
+ if (!stricmp(cdp->GetName(), Xcolumn)) {
+ Xcolp = new(g) XCLCOL(cdp, this, cprec, n);
+ colp = Xcolp;
+ } else
+ colp = new(g) PRXCOL(cdp, this, cprec, n);
+
+ return colp;
+ } // end of MakeCol
+
+/***********************************************************************/
+/* XCL GetMaxSize: returns the maximum number of rows in the table. */
+/***********************************************************************/
+int TDBXCL::GetMaxSize(PGLOBAL g)
+ {
+ if (MaxSize < 0) {
+ if (InitTable(g))
+ return 0;
+
+ MaxSize = Mult * Tdbp->GetMaxSize(g);
+ } // endif MaxSize
+
+ return MaxSize;
+ } // end of GetMaxSize
+
+/***********************************************************************/
+/* For this table type, ROWID is the (virtual) row number, */
+/* while ROWNUM is be the occurrence rank in the multiple column. */
+/***********************************************************************/
+int TDBXCL::RowNumber(PGLOBAL, bool b)
+ {
+ return (b) ? M : N;
+ } // end of RowNumber
+
+/***********************************************************************/
+/* XCL Access Method opening routine. */
+/***********************************************************************/
+bool TDBXCL::OpenDB(PGLOBAL g)
+ {
+ if (Use == USE_OPEN) {
+ /*******************************************************************/
+ /* Table already open, just replace it at its beginning. */
+ /*******************************************************************/
+ M = N = 0;
+ RowFlag = 0;
+ New = TRUE;
+ return Tdbp->OpenDB(g);
+ } // endif use
+
+ if (Mode != MODE_READ) {
+ /*******************************************************************/
+ /* Currently XCOL tables cannot be modified. */
+ /*******************************************************************/
+ strcpy(g->Message, "XCOL tables are read only");
+ return TRUE;
+ } // endif Mode
+
+ if (InitTable(g))
+ return TRUE;
+
+ /*********************************************************************/
+ /* Check and initialize the subtable columns. */
+ /*********************************************************************/
+ for (PCOL cp = Columns; cp; cp = cp->GetNext())
+ if (!cp->IsSpecial())
+ if (((PPRXCOL)cp)->Init(g, NULL))
+ return TRUE;
+
+ /*********************************************************************/
+ /* Physically open the object table. */
+ /*********************************************************************/
+ if (Tdbp->OpenDB(g))
+ return TRUE;
+
+ Use = USE_OPEN;
+ return FALSE;
+ } // end of OpenDB
+
+/***********************************************************************/
+/* Data Base read routine for XCL access method. */
+/***********************************************************************/
+int TDBXCL::ReadDB(PGLOBAL g)
+ {
+ int rc = RC_OK;
+
+ /*********************************************************************/
+ /* Now start the multi reading process. */
+ /*********************************************************************/
+ do {
+ if (RowFlag != 1) {
+ if ((rc = Tdbp->ReadDB(g)) != RC_OK)
+ break;
+
+ New = TRUE;
+ M = 1;
+ } else {
+ New = FALSE;
+ M++;
+ } // endif RowFlag
+
+ if (Xcolp) {
+ RowFlag = 0;
+ Xcolp->ReadColumn(g);
+ } // endif Xcolp
+
+ N++;
+ } while (RowFlag == 2);
+
+ return rc;
+ } // end of ReadDB
+
+
+// ------------------------ XCLCOL functions ----------------------------
+
+/***********************************************************************/
+/* XCLCOL public constructor. */
+/***********************************************************************/
+XCLCOL::XCLCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i)
+ : PRXCOL(cdp, tdbp, cprec, i, "XCL")
+ {
+ // Set additional XXL access method information for column.
+ Cbuf = NULL; // Will be allocated later
+ Cp = NULL; // Pointer to current position in Cbuf
+ Sep = ((PTDBXCL)tdbp)->Sep;
+ AddStatus(BUF_READ); // Only evaluated from TDBXCL::ReadDB
+ } // end of XCLCOL constructor
+
+/***********************************************************************/
+/* XCLCOL initialization routine. */
+/* Allocate Cbuf that will contain the Colp value. */
+/***********************************************************************/
+bool XCLCOL::Init(PGLOBAL g, PTDB tp)
+ {
+ if (PRXCOL::Init(g, tp))
+ return true;
+
+ Cbuf = (char*)PlugSubAlloc(g, NULL, Colp->GetLength() + 1);
+ return false;
+ } // end of Init
+
+/***********************************************************************/
+/* What this routine does is to get the comma-separated string */
+/* from the source table column, extract the single values and */
+/* set the flag for the table ReadDB function. */
+/***********************************************************************/
+void XCLCOL::ReadColumn(PGLOBAL g)
+ {
+ if (((PTDBXCL)To_Tdb)->New) {
+ Colp->Reset(); // Moved here in case of failed filtering
+ Colp->Eval(g);
+ strncpy(Cbuf, To_Val->GetCharValue(), Colp->GetLength());
+ Cbuf[Colp->GetLength()] = 0;
+ Cp = Cbuf;
+ } // endif New
+
+ if (*Cp) {
+ PSZ p;
+
+ // Trim left
+ for (p = Cp; *p == ' '; p++)
+ ;
+
+ if ((Cp = strchr(Cp, Sep)))
+ // Separator is found
+ *Cp++ = '\0';
+
+ Value->SetValue_psz(p);
+ } else if (Nullable) {
+ Value->Reset();
+ Value->SetNull(true);
+ } else {
+ // Skip that row
+ ((PTDBXCL)To_Tdb)->RowFlag = 2;
+ Colp->Reset();
+ } // endif Cp
+
+ if (Cp && *Cp)
+ // More to come from the same row
+ ((PTDBXCL)To_Tdb)->RowFlag = 1;
+
+ } // end of ReadColumn