mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 12:02:42 +01:00
298 lines
10 KiB
C++
298 lines
10 KiB
C++
/************* 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 occurence 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 occurence 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
|