2013-02-07 10:34:27 +01:00
|
|
|
/************ TabPivot C++ Program Source Code File (.CPP) *************/
|
|
|
|
/* PROGRAM NAME: TABPIVOT */
|
|
|
|
/* ------------- */
|
2017-02-16 18:01:48 +01:00
|
|
|
/* Version 1.7 */
|
2013-02-07 10:34:27 +01:00
|
|
|
/* */
|
|
|
|
/* COPYRIGHT: */
|
|
|
|
/* ---------- */
|
2017-02-16 18:01:48 +01:00
|
|
|
/* (C) Copyright to the author Olivier BERTRAND 2005-2017 */
|
2013-02-07 10:34:27 +01:00
|
|
|
/* */
|
|
|
|
/* WHAT THIS PROGRAM DOES: */
|
|
|
|
/* ----------------------- */
|
|
|
|
/* This program are the PIVOT classes DB execution routines. */
|
|
|
|
/***********************************************************************/
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* Include relevant sections of the operating system header file. */
|
|
|
|
/***********************************************************************/
|
|
|
|
#include "my_global.h"
|
2013-07-23 16:29:16 +02:00
|
|
|
#include "table.h" // MySQL table definitions
|
2015-05-27 16:23:38 +02:00
|
|
|
#if defined(__WIN__)
|
2013-02-07 10:34:27 +01:00
|
|
|
#if defined(__BORLANDC__)
|
|
|
|
#define __MFC_COMPAT__ // To define min/max as macro
|
|
|
|
#endif
|
|
|
|
//#include <windows.h>
|
|
|
|
#elif defined(UNIX)
|
|
|
|
#include <errno.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include "osutil.h"
|
|
|
|
#else
|
|
|
|
#include <io.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* Include application header files: */
|
|
|
|
/* global.h is header containing all global declarations. */
|
|
|
|
/* plgdbsem.h is header containing the DB application declarations. */
|
|
|
|
/***********************************************************************/
|
|
|
|
#define FRM_VER 6
|
|
|
|
#include "sql_const.h"
|
|
|
|
#include "field.h"
|
|
|
|
#include "global.h"
|
|
|
|
#include "plgdbsem.h"
|
|
|
|
#include "xtable.h"
|
2017-02-16 18:01:48 +01:00
|
|
|
#include "tabext.h"
|
2013-05-10 20:22:21 +02:00
|
|
|
#include "tabcol.h"
|
2013-02-07 10:34:27 +01:00
|
|
|
#include "colblk.h"
|
2013-05-19 19:25:06 +02:00
|
|
|
#include "tabmysql.h"
|
2013-02-07 10:34:27 +01:00
|
|
|
#include "csort.h"
|
2013-05-10 20:22:21 +02:00
|
|
|
#include "tabutil.h"
|
2013-02-07 10:34:27 +01:00
|
|
|
#include "tabpivot.h"
|
|
|
|
#include "valblk.h"
|
|
|
|
#include "ha_connect.h"
|
|
|
|
|
2013-05-28 17:22:38 +02:00
|
|
|
/***********************************************************************/
|
|
|
|
/* Make the Pivot table column list. */
|
|
|
|
/***********************************************************************/
|
|
|
|
PQRYRES PivotColumns(PGLOBAL g, const char *tab, const char *src,
|
|
|
|
const char *picol, const char *fncol,
|
2014-04-08 18:18:02 +02:00
|
|
|
const char *skcol, const char *host,
|
|
|
|
const char *db, const char *user,
|
|
|
|
const char *pwd, int port)
|
2013-05-28 17:22:38 +02:00
|
|
|
{
|
2014-04-08 18:18:02 +02:00
|
|
|
PIVAID pvd(tab, src, picol, fncol, skcol, host, db, user, pwd, port);
|
2013-05-28 21:06:15 +02:00
|
|
|
|
2013-05-28 17:22:38 +02:00
|
|
|
return pvd.MakePivotColumns(g);
|
|
|
|
} // end of PivotColumns
|
|
|
|
|
|
|
|
/* --------------- Implementation of the PIVAID classe --------------- */
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* PIVAID constructor. */
|
|
|
|
/***********************************************************************/
|
2014-04-08 18:18:02 +02:00
|
|
|
PIVAID::PIVAID(const char *tab, const char *src, const char *picol,
|
|
|
|
const char *fncol, const char *skcol, const char *host,
|
|
|
|
const char *db, const char *user, const char *pwd,
|
|
|
|
int port) : CSORT(false)
|
2013-05-28 17:22:38 +02:00
|
|
|
{
|
|
|
|
Host = (char*)host;
|
|
|
|
User = (char*)user;
|
|
|
|
Pwd = (char*)pwd;
|
|
|
|
Qryp = NULL;
|
|
|
|
Database = (char*)db;
|
|
|
|
Tabname = (char*)tab;
|
|
|
|
Tabsrc = (char*)src;
|
|
|
|
Picol = (char*)picol;
|
|
|
|
Fncol = (char*)fncol;
|
2014-04-08 18:18:02 +02:00
|
|
|
Skcol = (char*)skcol;
|
2013-05-28 17:22:38 +02:00
|
|
|
Rblkp = NULL;
|
|
|
|
Port = (port) ? port : GetDefaultPort();
|
|
|
|
} // end of PIVAID constructor
|
|
|
|
|
2014-04-08 18:18:02 +02:00
|
|
|
/***********************************************************************/
|
|
|
|
/* Skip columns that are in the skipped column list. */
|
|
|
|
/***********************************************************************/
|
|
|
|
bool PIVAID::SkipColumn(PCOLRES crp, char *skc)
|
|
|
|
{
|
|
|
|
if (skc)
|
|
|
|
for (char *p = skc; *p; p += (strlen(p) + 1))
|
|
|
|
if (!stricmp(crp->Name, p))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
} // end of SkipColumn
|
|
|
|
|
2013-05-28 17:22:38 +02:00
|
|
|
/***********************************************************************/
|
|
|
|
/* Make the Pivot table column list. */
|
|
|
|
/***********************************************************************/
|
|
|
|
PQRYRES PIVAID::MakePivotColumns(PGLOBAL g)
|
2017-05-23 19:35:50 +02:00
|
|
|
{
|
2014-04-08 18:18:02 +02:00
|
|
|
char *p, *query, *colname, *skc, buf[64];
|
2017-05-23 19:35:50 +02:00
|
|
|
int ndif, nblin, w = 0;
|
2014-04-04 01:28:34 +02:00
|
|
|
bool b = false;
|
2014-04-08 11:15:08 +02:00
|
|
|
PVAL valp;
|
|
|
|
PQRYRES qrp;
|
2013-05-28 17:22:38 +02:00
|
|
|
PCOLRES *pcrp, crp, fncrp = NULL;
|
|
|
|
|
2017-05-23 19:35:50 +02:00
|
|
|
try {
|
|
|
|
// Are there columns to skip?
|
|
|
|
if (Skcol) {
|
|
|
|
uint n = strlen(Skcol);
|
|
|
|
|
|
|
|
skc = (char*)PlugSubAlloc(g, NULL, n + 2);
|
|
|
|
strcpy(skc, Skcol);
|
|
|
|
skc[n + 1] = 0;
|
|
|
|
|
|
|
|
// Replace ; by nulls in skc
|
|
|
|
for (p = strchr(skc, ';'); p; p = strchr(p, ';'))
|
|
|
|
*p++ = 0;
|
|
|
|
|
|
|
|
} else
|
|
|
|
skc = NULL;
|
|
|
|
|
|
|
|
if (!Tabsrc && Tabname) {
|
|
|
|
// Locate the query
|
|
|
|
query = (char*)PlugSubAlloc(g, NULL, strlen(Tabname) + 26);
|
|
|
|
sprintf(query, "SELECT * FROM `%s` LIMIT 1", Tabname);
|
|
|
|
} else if (!Tabsrc) {
|
|
|
|
strcpy(g->Message, MSG(SRC_TABLE_UNDEF));
|
|
|
|
goto err;
|
|
|
|
} else
|
|
|
|
query = (char*)Tabsrc;
|
|
|
|
|
|
|
|
// Open a MySQL connection for this table
|
|
|
|
if (!Myc.Open(g, Host, Database, User, Pwd, Port)) {
|
|
|
|
b = true;
|
|
|
|
|
|
|
|
// Returned values must be in their original character set
|
|
|
|
if (Myc.ExecSQL(g, "SET character_set_results=NULL", &w) == RC_FX)
|
|
|
|
goto err;
|
|
|
|
else
|
|
|
|
Myc.FreeResult();
|
|
|
|
|
|
|
|
} else
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
// Send the source command to MySQL
|
|
|
|
if (Myc.ExecSQL(g, query, &w) == RC_FX)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
// We must have a storage query to get pivot column values
|
|
|
|
if (!(Qryp = Myc.GetResult(g, true)))
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
if (!Fncol) {
|
|
|
|
for (crp = Qryp->Colresp; crp; crp = crp->Next)
|
|
|
|
if ((!Picol || stricmp(Picol, crp->Name)) && !SkipColumn(crp, skc))
|
|
|
|
Fncol = crp->Name;
|
|
|
|
|
|
|
|
if (!Fncol) {
|
|
|
|
strcpy(g->Message, MSG(NO_DEF_FNCCOL));
|
|
|
|
goto err;
|
|
|
|
} // endif Fncol
|
|
|
|
|
|
|
|
} // endif Fncol
|
|
|
|
|
|
|
|
if (!Picol) {
|
|
|
|
// Find default Picol as the last one not equal to Fncol
|
|
|
|
for (crp = Qryp->Colresp; crp; crp = crp->Next)
|
|
|
|
if (stricmp(Fncol, crp->Name) && !SkipColumn(crp, skc))
|
|
|
|
Picol = crp->Name;
|
|
|
|
|
|
|
|
if (!Picol) {
|
|
|
|
strcpy(g->Message, MSG(NO_DEF_PIVOTCOL));
|
|
|
|
goto err;
|
|
|
|
} // endif Picol
|
|
|
|
|
|
|
|
} // endif picol
|
|
|
|
|
|
|
|
// Prepare the column list
|
|
|
|
for (pcrp = &Qryp->Colresp; crp = *pcrp; )
|
|
|
|
if (SkipColumn(crp, skc)) {
|
|
|
|
// Ignore this column
|
|
|
|
*pcrp = crp->Next;
|
|
|
|
} else if (!stricmp(Picol, crp->Name)) {
|
|
|
|
if (crp->Nulls) {
|
|
|
|
sprintf(g->Message, "Pivot column %s cannot be nullable", Picol);
|
|
|
|
goto err;
|
|
|
|
} // endif Nulls
|
|
|
|
|
|
|
|
Rblkp = crp->Kdata;
|
|
|
|
*pcrp = crp->Next;
|
|
|
|
} else if (!stricmp(Fncol, crp->Name)) {
|
|
|
|
fncrp = crp;
|
|
|
|
*pcrp = crp->Next;
|
|
|
|
} else
|
|
|
|
pcrp = &crp->Next;
|
|
|
|
|
|
|
|
if (!Rblkp) {
|
|
|
|
strcpy(g->Message, MSG(NO_DEF_PIVOTCOL));
|
|
|
|
goto err;
|
|
|
|
} else if (!fncrp) {
|
|
|
|
strcpy(g->Message, MSG(NO_DEF_FNCCOL));
|
|
|
|
goto err;
|
|
|
|
} // endif
|
|
|
|
|
|
|
|
if (Tabsrc) {
|
|
|
|
Myc.Close();
|
|
|
|
b = false;
|
|
|
|
|
|
|
|
// Before calling sort, initialize all
|
|
|
|
nblin = Qryp->Nblin;
|
|
|
|
|
|
|
|
Index.Size = nblin * sizeof(int);
|
|
|
|
Index.Sub = TRUE; // Should be small enough
|
|
|
|
|
|
|
|
if (!PlgDBalloc(g, NULL, Index))
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
Offset.Size = (nblin + 1) * sizeof(int);
|
|
|
|
Offset.Sub = TRUE; // Should be small enough
|
|
|
|
|
|
|
|
if (!PlgDBalloc(g, NULL, Offset))
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
ndif = Qsort(g, nblin);
|
|
|
|
|
|
|
|
if (ndif < 0) // error
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
// The query was limited, we must get pivot column values
|
|
|
|
// Returned values must be in their original character set
|
|
|
|
// if (Myc.ExecSQL(g, "SET character_set_results=NULL", &w) == RC_FX)
|
|
|
|
// goto err;
|
|
|
|
|
|
|
|
query = (char*)PlugSubAlloc(g, NULL, 0);
|
|
|
|
sprintf(query, "SELECT DISTINCT `%s` FROM `%s`", Picol, Tabname);
|
|
|
|
PlugSubAlloc(g, NULL, strlen(query) + 1);
|
|
|
|
Myc.FreeResult();
|
|
|
|
|
|
|
|
// Send the source command to MySQL
|
|
|
|
if (Myc.ExecSQL(g, query, &w) == RC_FX)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
// We must have a storage query to get pivot column values
|
|
|
|
if (!(qrp = Myc.GetResult(g, true)))
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
Myc.Close();
|
|
|
|
b = false;
|
|
|
|
|
|
|
|
// Get the column list
|
|
|
|
crp = qrp->Colresp;
|
|
|
|
Rblkp = crp->Kdata;
|
|
|
|
ndif = qrp->Nblin;
|
|
|
|
} // endif Tabsrc
|
|
|
|
|
|
|
|
// Allocate the Value used to retieve column names
|
|
|
|
if (!(valp = AllocateValue(g, Rblkp->GetType(),
|
|
|
|
Rblkp->GetVlen(),
|
|
|
|
Rblkp->GetPrec())))
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
// Now make the functional columns
|
|
|
|
for (int i = 0; i < ndif; i++) {
|
|
|
|
if (i) {
|
|
|
|
crp = (PCOLRES)PlugSubAlloc(g, NULL, sizeof(COLRES));
|
|
|
|
memcpy(crp, fncrp, sizeof(COLRES));
|
|
|
|
} else
|
|
|
|
crp = fncrp;
|
|
|
|
|
|
|
|
// Get the value that will be the generated column name
|
|
|
|
if (Tabsrc)
|
|
|
|
valp->SetValue_pvblk(Rblkp, Pex[Pof[i]]);
|
|
|
|
else
|
|
|
|
valp->SetValue_pvblk(Rblkp, i);
|
|
|
|
|
|
|
|
colname = valp->GetCharString(buf);
|
|
|
|
crp->Name = PlugDup(g, colname);
|
|
|
|
crp->Flag = 1;
|
|
|
|
|
|
|
|
// Add this column
|
|
|
|
*pcrp = crp;
|
|
|
|
crp->Next = NULL;
|
|
|
|
pcrp = &crp->Next;
|
|
|
|
} // endfor i
|
|
|
|
|
|
|
|
// We added ndif columns and removed 2 (picol and fncol)
|
|
|
|
Qryp->Nbcol += (ndif - 2);
|
|
|
|
return Qryp;
|
|
|
|
} catch (int n) {
|
|
|
|
if (trace)
|
|
|
|
htrc("Exception %d: %s\n", n, g->Message);
|
|
|
|
} catch (const char *msg) {
|
|
|
|
strcpy(g->Message, msg);
|
|
|
|
} // end catch
|
2014-04-04 01:28:34 +02:00
|
|
|
|
|
|
|
err:
|
|
|
|
if (b)
|
|
|
|
Myc.Close();
|
|
|
|
|
|
|
|
return NULL;
|
2017-05-23 19:35:50 +02:00
|
|
|
} // end of MakePivotColumns
|
2013-05-28 17:22:38 +02:00
|
|
|
|
2013-05-28 21:06:15 +02:00
|
|
|
/***********************************************************************/
|
|
|
|
/* PIVAID: Compare routine for sorting pivot column values. */
|
|
|
|
/***********************************************************************/
|
|
|
|
int PIVAID::Qcompare(int *i1, int *i2)
|
|
|
|
{
|
|
|
|
// TODO: the actual comparison between pivot column result values.
|
|
|
|
return Rblkp->CompVal(*i1, *i2);
|
|
|
|
} // end of Qcompare
|
|
|
|
|
2013-05-10 20:22:21 +02:00
|
|
|
/* --------------- Implementation of the PIVOT classes --------------- */
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* PIVOTDEF constructor. */
|
|
|
|
/***********************************************************************/
|
|
|
|
PIVOTDEF::PIVOTDEF(void)
|
|
|
|
{
|
|
|
|
Host = User = Pwd = DB = NULL;
|
|
|
|
Tabname = Tabsrc = Picol = Fncol = Function = NULL;
|
|
|
|
GBdone = Accept = false;
|
|
|
|
Port = 0;
|
|
|
|
} // end of PIVOTDEF constructor
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* DefineAM: define specific AM block values from PIVOT table. */
|
|
|
|
/***********************************************************************/
|
|
|
|
bool PIVOTDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
|
|
|
|
{
|
|
|
|
char *p1, *p2;
|
|
|
|
PHC hc = ((MYCAT*)Cat)->GetHandler();
|
|
|
|
|
2013-05-19 19:25:06 +02:00
|
|
|
if (PRXDEF::DefineAM(g, am, poff))
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
Tabname = (char*)Tablep->GetName();
|
2016-01-09 20:52:17 +01:00
|
|
|
DB = (char*)Tablep->GetSchema();
|
2013-05-19 19:25:06 +02:00
|
|
|
Tabsrc = (char*)Tablep->GetSrc();
|
2013-05-10 20:22:21 +02:00
|
|
|
|
2014-04-14 14:26:48 +02:00
|
|
|
Host = GetStringCatInfo(g, "Host", "localhost");
|
|
|
|
User = GetStringCatInfo(g, "User", "*");
|
|
|
|
Pwd = GetStringCatInfo(g, "Password", NULL);
|
|
|
|
Picol = GetStringCatInfo(g, "PivotCol", NULL);
|
|
|
|
Fncol = GetStringCatInfo(g, "FncCol", NULL);
|
2013-05-10 20:22:21 +02:00
|
|
|
|
|
|
|
// If fncol is like avg(colname), separate Fncol and Function
|
|
|
|
if (Fncol && (p1 = strchr(Fncol, '(')) && (p2 = strchr(p1, ')')) &&
|
|
|
|
(*Fncol != '"') && (!*(p2+1))) {
|
|
|
|
*p1++ = '\0'; *p2 = '\0';
|
|
|
|
Function = Fncol;
|
|
|
|
Fncol = p1;
|
|
|
|
} else
|
2014-04-14 14:26:48 +02:00
|
|
|
Function = GetStringCatInfo(g, "Function", "SUM");
|
2013-05-10 20:22:21 +02:00
|
|
|
|
2014-04-14 14:26:48 +02:00
|
|
|
GBdone = GetBoolCatInfo("Groupby", false);
|
|
|
|
Accept = GetBoolCatInfo("Accept", false);
|
|
|
|
Port = GetIntCatInfo("Port", 3306);
|
2013-05-19 19:25:06 +02:00
|
|
|
Desc = (Tabsrc) ? Tabsrc : Tabname;
|
2013-05-10 20:22:21 +02:00
|
|
|
return FALSE;
|
|
|
|
} // end of DefineAM
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* GetTable: makes a new TDB of the proper type. */
|
|
|
|
/***********************************************************************/
|
2015-05-09 17:30:20 +02:00
|
|
|
PTDB PIVOTDEF::GetTable(PGLOBAL g, MODE)
|
2013-05-10 20:22:21 +02:00
|
|
|
{
|
|
|
|
return new(g) TDBPIVOT(this);
|
|
|
|
} // end of GetTable
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* Implementation of the TDBPIVOT class. */
|
|
|
|
/***********************************************************************/
|
|
|
|
TDBPIVOT::TDBPIVOT(PPIVOTDEF tdp) : TDBPRX(tdp)
|
|
|
|
{
|
|
|
|
Host = tdp->Host;
|
|
|
|
Database = tdp->DB;
|
|
|
|
User = tdp->User;
|
|
|
|
Pwd = tdp->Pwd;
|
|
|
|
Port = tdp->Port;
|
|
|
|
Tabname = tdp->Tabname; // Name of source table
|
|
|
|
Tabsrc = tdp->Tabsrc; // SQL description of source table
|
|
|
|
Picol = tdp->Picol; // Pivot column name
|
|
|
|
Fncol = tdp->Fncol; // Function column name
|
|
|
|
Function = tdp->Function; // Aggregate function name
|
|
|
|
Xcolp = NULL; // To the FNCCOL column
|
|
|
|
//Xresp = NULL; // To the pivot result column
|
|
|
|
//Rblkp = NULL; // The value block of the pivot column
|
|
|
|
Fcolp = NULL; // To the function column
|
|
|
|
Dcolp = NULL; // To the dump column
|
|
|
|
GBdone = tdp->GBdone;
|
|
|
|
Accept = tdp->Accept;
|
|
|
|
Mult = -1; // Estimated table size
|
|
|
|
N = 0; // The current table index
|
|
|
|
M = 0; // The occurence rank
|
|
|
|
FileStatus = 0; // Logical End-of-File
|
|
|
|
RowFlag = 0; // 0: Ok, 1: Same, 2: Skip
|
|
|
|
} // end of TDBPIVOT constructor
|
|
|
|
|
2013-05-19 19:25:06 +02:00
|
|
|
/***********************************************************************/
|
|
|
|
/* Allocate source column description block. */
|
|
|
|
/***********************************************************************/
|
|
|
|
PCOL TDBPIVOT::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
|
|
|
|
{
|
|
|
|
PCOL colp;
|
|
|
|
|
|
|
|
if (cdp->GetOffset()) {
|
|
|
|
colp = new(g) FNCCOL(cdp, this, cprec, n);
|
|
|
|
|
|
|
|
if (cdp->GetOffset() > 1)
|
|
|
|
Dcolp = colp;
|
|
|
|
|
|
|
|
} else
|
|
|
|
colp = new(g) SRCCOL(cdp, this, cprec, n);
|
|
|
|
|
|
|
|
return colp;
|
|
|
|
} // end of MakeCol
|
|
|
|
|
2013-05-22 13:35:21 +02:00
|
|
|
/***********************************************************************/
|
|
|
|
/* Find default fonction and pivot columns. */
|
|
|
|
/***********************************************************************/
|
|
|
|
bool TDBPIVOT::FindDefaultColumns(PGLOBAL g)
|
|
|
|
{
|
|
|
|
PCOLDEF cdp;
|
|
|
|
PTABDEF defp = Tdbp->GetDef();
|
|
|
|
|
|
|
|
if (!Fncol) {
|
|
|
|
for (cdp = defp->GetCols(); cdp; cdp = cdp->GetNext())
|
|
|
|
if (!Picol || stricmp(Picol, cdp->GetName()))
|
|
|
|
Fncol = cdp->GetName();
|
|
|
|
|
|
|
|
if (!Fncol) {
|
|
|
|
strcpy(g->Message, MSG(NO_DEF_FNCCOL));
|
|
|
|
return true;
|
|
|
|
} // endif Fncol
|
|
|
|
|
|
|
|
} // endif Fncol
|
|
|
|
|
|
|
|
if (!Picol) {
|
|
|
|
// Find default Picol as the last one not equal to Fncol
|
|
|
|
for (cdp = defp->GetCols(); cdp; cdp = cdp->GetNext())
|
|
|
|
if (stricmp(Fncol, cdp->GetName()))
|
|
|
|
Picol = cdp->GetName();
|
|
|
|
|
|
|
|
if (!Picol) {
|
|
|
|
strcpy(g->Message, MSG(NO_DEF_PIVOTCOL));
|
|
|
|
return true;
|
|
|
|
} // endif Picol
|
|
|
|
|
|
|
|
} // endif Picol
|
|
|
|
|
|
|
|
return false;
|
|
|
|
} // end of FindDefaultColumns
|
|
|
|
|
2013-05-10 20:22:21 +02:00
|
|
|
/***********************************************************************/
|
|
|
|
/* Prepare the source table Query. */
|
|
|
|
/***********************************************************************/
|
|
|
|
bool TDBPIVOT::GetSourceTable(PGLOBAL g)
|
|
|
|
{
|
|
|
|
if (Tdbp)
|
|
|
|
return false; // Already done
|
|
|
|
|
2013-05-19 19:25:06 +02:00
|
|
|
if (!Tabsrc && Tabname) {
|
|
|
|
// Get the table description block of this table
|
|
|
|
if (!(Tdbp = GetSubTable(g, ((PPIVOTDEF)To_Def)->Tablep, true)))
|
2013-05-10 20:22:21 +02:00
|
|
|
return true;
|
|
|
|
|
2013-05-22 13:35:21 +02:00
|
|
|
if (!GBdone) {
|
|
|
|
char *colist;
|
2013-05-19 19:25:06 +02:00
|
|
|
PCOLDEF cdp;
|
2013-05-10 20:22:21 +02:00
|
|
|
|
2013-05-22 13:35:21 +02:00
|
|
|
if (FindDefaultColumns(g))
|
|
|
|
return true;
|
2013-05-10 20:22:21 +02:00
|
|
|
|
2013-05-22 13:35:21 +02:00
|
|
|
// Locate the suballocated colist (size is not known yet)
|
|
|
|
*(colist = (char*)PlugSubAlloc(g, NULL, 0)) = 0;
|
2013-05-10 20:22:21 +02:00
|
|
|
|
2013-05-22 13:35:21 +02:00
|
|
|
// Make the column list
|
|
|
|
for (cdp = To_Def->GetCols(); cdp; cdp = cdp->GetNext())
|
|
|
|
if (!cdp->GetOffset())
|
|
|
|
strcat(strcat(colist, cdp->GetName()), ", ");
|
2013-05-10 20:22:21 +02:00
|
|
|
|
2013-05-22 13:35:21 +02:00
|
|
|
// Add the Pivot column at the end of the list
|
|
|
|
strcat(colist, Picol);
|
2013-05-10 20:22:21 +02:00
|
|
|
|
2013-05-22 13:35:21 +02:00
|
|
|
// Now we know how much was suballocated
|
2014-02-27 18:00:01 +01:00
|
|
|
PlugSubAlloc(g, NULL, strlen(colist) + 1);
|
2013-05-19 19:25:06 +02:00
|
|
|
|
2013-05-22 13:35:21 +02:00
|
|
|
// Locate the source string (size is not known yet)
|
|
|
|
Tabsrc = (char*)PlugSubAlloc(g, NULL, 0);
|
2013-05-19 19:25:06 +02:00
|
|
|
|
2013-05-22 13:35:21 +02:00
|
|
|
// Start making the definition
|
|
|
|
strcat(strcat(strcpy(Tabsrc, "SELECT "), colist), ", ");
|
2013-05-10 20:22:21 +02:00
|
|
|
|
2013-05-22 13:35:21 +02:00
|
|
|
// Make it suitable for Pivot by doing the group by
|
|
|
|
strcat(strcat(Tabsrc, Function), "(");
|
|
|
|
strcat(strcat(strcat(Tabsrc, Fncol), ") "), Fncol);
|
|
|
|
strcat(strcat(Tabsrc, " FROM "), Tabname);
|
|
|
|
strcat(strcat(Tabsrc, " GROUP BY "), colist);
|
2013-05-10 20:22:21 +02:00
|
|
|
|
2013-05-22 13:35:21 +02:00
|
|
|
if (Tdbp->IsView()) // Until MariaDB bug is fixed
|
|
|
|
strcat(strcat(Tabsrc, " ORDER BY "), colist);
|
2013-05-19 19:25:06 +02:00
|
|
|
|
2013-05-22 13:35:21 +02:00
|
|
|
// Now we know how much was suballocated
|
2014-02-27 18:00:01 +01:00
|
|
|
PlugSubAlloc(g, NULL, strlen(Tabsrc) + 1);
|
2013-05-22 13:35:21 +02:00
|
|
|
} // endif !GBdone
|
2013-05-10 20:22:21 +02:00
|
|
|
|
|
|
|
} else if (!Tabsrc) {
|
|
|
|
strcpy(g->Message, MSG(SRC_TABLE_UNDEF));
|
|
|
|
return true;
|
|
|
|
} // endif
|
|
|
|
|
|
|
|
if (Tabsrc) {
|
2013-05-19 19:25:06 +02:00
|
|
|
// Get the new table description block of this source table
|
|
|
|
PTABLE tablep = new(g) XTAB("whatever", Tabsrc);
|
|
|
|
|
2016-01-09 20:52:17 +01:00
|
|
|
tablep->SetSchema(Database);
|
2013-05-10 20:22:21 +02:00
|
|
|
|
2013-05-19 19:25:06 +02:00
|
|
|
if (!(Tdbp = GetSubTable(g, tablep, true)))
|
2013-05-10 20:22:21 +02:00
|
|
|
return true;
|
|
|
|
|
2013-05-19 19:25:06 +02:00
|
|
|
} // endif Tabsrc
|
|
|
|
|
|
|
|
return false;
|
|
|
|
} // end of GetSourceTable
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* Make the required pivot columns. */
|
|
|
|
/***********************************************************************/
|
|
|
|
bool TDBPIVOT::MakePivotColumns(PGLOBAL g)
|
|
|
|
{
|
|
|
|
if (!Tdbp->IsView()) {
|
2013-05-22 13:35:21 +02:00
|
|
|
// This was not done yet if GBdone is true
|
|
|
|
if (FindDefaultColumns(g))
|
|
|
|
return true;
|
|
|
|
|
2013-05-19 19:25:06 +02:00
|
|
|
// Now it is time to allocate the pivot and function columns
|
|
|
|
if (!(Fcolp = Tdbp->ColDB(g, Fncol, 0))) {
|
|
|
|
// Function column not found in table
|
|
|
|
sprintf(g->Message, MSG(COL_ISNOT_TABLE), Fncol, Tabname);
|
|
|
|
return true;
|
|
|
|
} else if (Fcolp->InitValue(g))
|
2013-05-10 20:22:21 +02:00
|
|
|
return true;
|
|
|
|
|
2013-05-19 19:25:06 +02:00
|
|
|
if (!(Xcolp = Tdbp->ColDB(g, Picol, 0))) {
|
|
|
|
// Pivot column not found in table
|
|
|
|
sprintf(g->Message, MSG(COL_ISNOT_TABLE), Picol, Tabname);
|
|
|
|
return true;
|
|
|
|
} else if (Xcolp->InitValue(g))
|
|
|
|
return true;
|
|
|
|
|
2013-05-19 19:53:38 +02:00
|
|
|
// Check and initialize the subtable columns
|
|
|
|
for (PCOL cp = Columns; cp; cp = cp->GetNext())
|
|
|
|
if (cp->GetAmType() == TYPE_AM_SRC) {
|
2015-01-28 00:19:39 +01:00
|
|
|
if (((PSRCCOL)cp)->Init(g, NULL))
|
2013-05-19 19:53:38 +02:00
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
} else if (cp->GetAmType() == TYPE_AM_FNC)
|
|
|
|
if (((PFNCCOL)cp)->InitColumn(g))
|
|
|
|
return TRUE;
|
|
|
|
|
2013-05-19 19:25:06 +02:00
|
|
|
} // endif isview
|
|
|
|
|
|
|
|
return false;
|
|
|
|
} // end of MakePivotColumns
|
2013-05-10 20:22:21 +02:00
|
|
|
|
2013-05-19 19:25:06 +02:00
|
|
|
/***********************************************************************/
|
|
|
|
/* Make the required pivot columns for an object view. */
|
|
|
|
/***********************************************************************/
|
|
|
|
bool TDBPIVOT::MakeViewColumns(PGLOBAL g)
|
|
|
|
{
|
|
|
|
if (Tdbp->IsView()) {
|
|
|
|
// Tdbp is a view ColDB cannot be used
|
|
|
|
PCOL colp, cp;
|
|
|
|
PTDBMY tdbp;
|
|
|
|
|
|
|
|
if (Tdbp->GetAmType() != TYPE_AM_MYSQL) {
|
|
|
|
strcpy(g->Message, "View is not MySQL");
|
|
|
|
return true;
|
|
|
|
} else
|
|
|
|
tdbp = (PTDBMY)Tdbp;
|
|
|
|
|
2013-05-22 13:35:21 +02:00
|
|
|
if (!Fncol && !(Fncol = tdbp->FindFieldColumn(Picol))) {
|
|
|
|
strcpy(g->Message, MSG(NO_DEF_FNCCOL));
|
2013-05-19 19:25:06 +02:00
|
|
|
return true;
|
2013-05-10 20:22:21 +02:00
|
|
|
} // endif Fncol
|
|
|
|
|
2013-05-22 13:35:21 +02:00
|
|
|
if (!Picol && !(Picol = tdbp->FindFieldColumn(Fncol))) {
|
|
|
|
strcpy(g->Message, MSG(NO_DEF_PIVOTCOL));
|
|
|
|
return true;
|
2013-05-10 20:22:21 +02:00
|
|
|
} // endif Picol
|
|
|
|
|
2013-05-19 19:25:06 +02:00
|
|
|
// Now it is time to allocate the pivot and function columns
|
|
|
|
if (!(Fcolp = tdbp->MakeFieldColumn(g, Fncol)))
|
|
|
|
return true;
|
2013-05-10 20:22:21 +02:00
|
|
|
|
2013-05-19 19:25:06 +02:00
|
|
|
if (!(Xcolp = tdbp->MakeFieldColumn(g, Picol)))
|
|
|
|
return true;
|
2013-02-07 10:34:27 +01:00
|
|
|
|
2013-05-19 19:53:38 +02:00
|
|
|
// Check and initialize the subtable columns
|
2013-05-19 19:25:06 +02:00
|
|
|
for (cp = Columns; cp; cp = cp->GetNext())
|
|
|
|
if (cp->GetAmType() == TYPE_AM_SRC) {
|
|
|
|
if ((colp = tdbp->MakeFieldColumn(g, cp->GetName()))) {
|
|
|
|
((PSRCCOL)cp)->Colp = colp;
|
|
|
|
((PSRCCOL)cp)->To_Val = colp->GetValue();
|
|
|
|
cp->AddStatus(BUF_READ); // All is done here
|
|
|
|
} else
|
|
|
|
return true;
|
2013-02-07 10:34:27 +01:00
|
|
|
|
2013-05-19 19:53:38 +02:00
|
|
|
} else if (cp->GetAmType() == TYPE_AM_FNC)
|
|
|
|
if (((PFNCCOL)cp)->InitColumn(g))
|
|
|
|
return TRUE;
|
2013-02-07 10:34:27 +01:00
|
|
|
|
2013-05-19 19:25:06 +02:00
|
|
|
} // endif isview
|
2013-02-07 10:34:27 +01:00
|
|
|
|
2013-05-19 19:25:06 +02:00
|
|
|
return false;
|
|
|
|
} // end of MakeViewColumns
|
2013-02-07 10:34:27 +01:00
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* PIVOT GetMaxSize: returns the maximum number of rows in the table. */
|
|
|
|
/***********************************************************************/
|
2015-05-09 17:30:20 +02:00
|
|
|
int TDBPIVOT::GetMaxSize(PGLOBAL g __attribute__((unused)))
|
2013-02-07 10:34:27 +01:00
|
|
|
{
|
|
|
|
#if 0
|
|
|
|
if (MaxSize < 0)
|
|
|
|
MaxSize = MakePivotColumns(g);
|
|
|
|
|
|
|
|
return MaxSize;
|
|
|
|
#endif // 0
|
2013-05-19 19:25:06 +02:00
|
|
|
return 10;
|
2013-02-07 10:34:27 +01:00
|
|
|
} // end of GetMaxSize
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* In this sample, ROWID will be the (virtual) row number, */
|
|
|
|
/* while ROWNUM will be the occurence rank in the multiple column. */
|
|
|
|
/***********************************************************************/
|
2015-05-09 17:30:20 +02:00
|
|
|
int TDBPIVOT::RowNumber(PGLOBAL, bool b)
|
2013-02-07 10:34:27 +01:00
|
|
|
{
|
|
|
|
return (b) ? M : N;
|
|
|
|
} // end of RowNumber
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* PIVOT Access Method opening routine. */
|
|
|
|
/***********************************************************************/
|
|
|
|
bool TDBPIVOT::OpenDB(PGLOBAL g)
|
|
|
|
{
|
|
|
|
if (Use == USE_OPEN) {
|
|
|
|
/*******************************************************************/
|
|
|
|
/* Table already open, just replace it at its beginning. */
|
|
|
|
/*******************************************************************/
|
|
|
|
N = M = 0;
|
|
|
|
RowFlag = 0;
|
|
|
|
FileStatus = 0;
|
|
|
|
return FALSE;
|
|
|
|
} // endif use
|
|
|
|
|
|
|
|
if (Mode != MODE_READ) {
|
|
|
|
/*******************************************************************/
|
|
|
|
/* Currently PIVOT tables cannot be modified. */
|
|
|
|
/*******************************************************************/
|
|
|
|
sprintf(g->Message, MSG(TABLE_READ_ONLY), "PIVOT");
|
|
|
|
return TRUE;
|
|
|
|
} // endif Mode
|
|
|
|
|
|
|
|
if (To_Key_Col || To_Kindex) {
|
|
|
|
/*******************************************************************/
|
|
|
|
/* Direct access of PIVOT tables is not implemented yet. */
|
|
|
|
/*******************************************************************/
|
|
|
|
strcpy(g->Message, MSG(NO_PIV_DIR_ACC));
|
|
|
|
return TRUE;
|
|
|
|
} // endif To_Key_Col
|
|
|
|
|
2013-05-10 20:22:21 +02:00
|
|
|
/*********************************************************************/
|
|
|
|
/* Do it here if not done yet (should not be the case). */
|
|
|
|
/*********************************************************************/
|
|
|
|
if (GetSourceTable(g))
|
|
|
|
return TRUE;
|
2013-05-19 19:25:06 +02:00
|
|
|
|
|
|
|
// For tables, columns must be allocated before opening
|
|
|
|
if (MakePivotColumns(g))
|
|
|
|
return TRUE;
|
2013-05-10 20:22:21 +02:00
|
|
|
|
|
|
|
/*********************************************************************/
|
|
|
|
/* Physically open the object table. */
|
|
|
|
/*********************************************************************/
|
|
|
|
if (Tdbp->OpenDB(g))
|
|
|
|
return TRUE;
|
|
|
|
|
2013-11-11 13:00:39 +01:00
|
|
|
Use = USE_OPEN; // Do it now in case we are recursively called
|
|
|
|
|
2013-05-19 19:25:06 +02:00
|
|
|
/*********************************************************************/
|
|
|
|
/* Make all required pivot columns for object views. */
|
|
|
|
/*********************************************************************/
|
|
|
|
return MakeViewColumns(g);
|
2013-02-07 10:34:27 +01:00
|
|
|
} // end of OpenDB
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* Data Base read routine for PIVOT access method. */
|
|
|
|
/***********************************************************************/
|
|
|
|
int TDBPIVOT::ReadDB(PGLOBAL g)
|
|
|
|
{
|
|
|
|
int rc = RC_OK;
|
|
|
|
bool newrow = FALSE;
|
|
|
|
PCOL colp;
|
|
|
|
|
|
|
|
if (FileStatus == 2)
|
|
|
|
return RC_EF;
|
|
|
|
|
|
|
|
if (FileStatus)
|
|
|
|
for (colp = Columns; colp; colp = colp->GetNext())
|
|
|
|
if (colp->GetAmType() == TYPE_AM_SRC)
|
|
|
|
((PSRCCOL)colp)->SetColumn();
|
|
|
|
|
|
|
|
// New row, reset all function column values
|
|
|
|
for (colp = Columns; colp; colp = colp->GetNext())
|
|
|
|
if (colp->GetAmType() == TYPE_AM_FNC)
|
|
|
|
colp->GetValue()->Reset();
|
|
|
|
|
|
|
|
/*********************************************************************/
|
|
|
|
/* Now start the multi reading process. */
|
|
|
|
/*********************************************************************/
|
|
|
|
do {
|
|
|
|
if (RowFlag != 1) {
|
2013-05-10 20:22:21 +02:00
|
|
|
if ((rc = Tdbp->ReadDB(g)) != RC_OK) {
|
2013-02-07 10:34:27 +01:00
|
|
|
if (FileStatus && rc == RC_EF) {
|
|
|
|
// A prepared row remains to be sent
|
|
|
|
FileStatus = 2;
|
|
|
|
rc = RC_OK;
|
|
|
|
} // endif FileStatus
|
|
|
|
|
|
|
|
break;
|
|
|
|
} // endif rc
|
|
|
|
|
2013-05-10 20:22:21 +02:00
|
|
|
for (colp = Tdbp->GetColumns(); colp; colp = colp->GetNext())
|
2013-02-07 10:34:27 +01:00
|
|
|
colp->ReadColumn(g);
|
|
|
|
|
|
|
|
for (colp = Columns; colp; colp = colp->GetNext())
|
|
|
|
if (colp->GetAmType() == TYPE_AM_SRC)
|
|
|
|
if (FileStatus) {
|
2013-05-10 20:22:21 +02:00
|
|
|
if (((PSRCCOL)colp)->CompareLast()) {
|
2013-02-07 10:34:27 +01:00
|
|
|
newrow = (RowFlag) ? TRUE : FALSE;
|
2013-05-10 20:22:21 +02:00
|
|
|
break;
|
|
|
|
} // endif CompareLast
|
2013-02-07 10:34:27 +01:00
|
|
|
|
|
|
|
} else
|
|
|
|
((PSRCCOL)colp)->SetColumn();
|
|
|
|
|
|
|
|
FileStatus = 1;
|
|
|
|
} // endif RowFlag
|
|
|
|
|
|
|
|
if (newrow) {
|
|
|
|
RowFlag = 1;
|
|
|
|
break;
|
|
|
|
} else
|
|
|
|
RowFlag = 2;
|
|
|
|
|
|
|
|
// Look for the column having this header
|
|
|
|
for (colp = Columns; colp; colp = colp->GetNext())
|
|
|
|
if (colp->GetAmType() == TYPE_AM_FNC) {
|
2013-05-10 20:22:21 +02:00
|
|
|
if (((PFNCCOL)colp)->CompareColumn())
|
2013-02-07 10:34:27 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
} // endif AmType
|
|
|
|
|
2013-05-10 20:22:21 +02:00
|
|
|
if (!colp && !(colp = Dcolp)) {
|
|
|
|
if (!Accept) {
|
|
|
|
strcpy(g->Message, MSG(NO_MATCH_COL));
|
|
|
|
return RC_FX;
|
|
|
|
} else
|
|
|
|
continue;
|
|
|
|
|
2013-02-07 10:34:27 +01:00
|
|
|
} // endif colp
|
|
|
|
|
|
|
|
// Set the value of the matching column from the fonction value
|
|
|
|
colp->GetValue()->SetValue_pval(Fcolp->GetValue());
|
|
|
|
} while (RowFlag == 2);
|
|
|
|
|
|
|
|
N++;
|
|
|
|
return rc;
|
|
|
|
} // end of ReadDB
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* WriteDB: Data Base write routine for PIVOT access methods. */
|
|
|
|
/***********************************************************************/
|
|
|
|
int TDBPIVOT::WriteDB(PGLOBAL g)
|
|
|
|
{
|
|
|
|
sprintf(g->Message, MSG(TABLE_READ_ONLY), "PIVOT");
|
|
|
|
return RC_FX;
|
|
|
|
} // end of WriteDB
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* Data Base delete line routine for PIVOT access methods. */
|
|
|
|
/***********************************************************************/
|
2015-05-09 17:30:20 +02:00
|
|
|
int TDBPIVOT::DeleteDB(PGLOBAL g, int)
|
2013-02-07 10:34:27 +01:00
|
|
|
{
|
|
|
|
sprintf(g->Message, MSG(NO_TABLE_DEL), "PIVOT");
|
|
|
|
return RC_FX;
|
|
|
|
} // end of DeleteDB
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* Data Base close routine for PIVOT access method. */
|
|
|
|
/***********************************************************************/
|
|
|
|
void TDBPIVOT::CloseDB(PGLOBAL g)
|
|
|
|
{
|
2013-05-12 18:14:03 +02:00
|
|
|
if (Tdbp)
|
|
|
|
Tdbp->CloseDB(g);
|
|
|
|
|
2013-02-07 10:34:27 +01:00
|
|
|
} // end of CloseDB
|
|
|
|
|
|
|
|
// ------------------------ FNCCOL functions ----------------------------
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* FNCCOL public constructor. */
|
|
|
|
/***********************************************************************/
|
2013-05-10 20:22:21 +02:00
|
|
|
FNCCOL::FNCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i)
|
|
|
|
: COLBLK(cdp, tdbp, i)
|
2013-02-07 10:34:27 +01:00
|
|
|
{
|
2013-05-10 20:22:21 +02:00
|
|
|
if (cprec) {
|
|
|
|
Next = cprec->GetNext();
|
|
|
|
cprec->SetNext(this);
|
|
|
|
} else {
|
|
|
|
Next = tdbp->GetColumns();
|
|
|
|
tdbp->SetColumns(this);
|
|
|
|
} // endif cprec
|
|
|
|
|
2013-02-07 10:34:27 +01:00
|
|
|
Value = NULL; // We'll get a new one later
|
2013-05-10 20:22:21 +02:00
|
|
|
Hval = NULL; // The unconverted header value
|
|
|
|
Xcolp = NULL;
|
2013-02-07 10:34:27 +01:00
|
|
|
} // end of FNCCOL constructor
|
|
|
|
|
|
|
|
/***********************************************************************/
|
2013-05-10 20:22:21 +02:00
|
|
|
/* FNCCOL initialization function. */
|
2013-02-07 10:34:27 +01:00
|
|
|
/***********************************************************************/
|
2013-05-10 20:22:21 +02:00
|
|
|
bool FNCCOL::InitColumn(PGLOBAL g)
|
2013-02-07 10:34:27 +01:00
|
|
|
{
|
|
|
|
// Must have its own value block
|
|
|
|
if (InitValue(g))
|
|
|
|
return TRUE;
|
|
|
|
|
2013-05-10 20:22:21 +02:00
|
|
|
// Make a value from the column name
|
|
|
|
Hval = AllocateValue(g, Name, TYPE_STRING);
|
|
|
|
Hval->SetPrec(1); // Case insensitive
|
2013-02-07 10:34:27 +01:00
|
|
|
|
2013-05-10 20:22:21 +02:00
|
|
|
Xcolp = ((PTDBPIVOT)To_Tdb)->Xcolp;
|
2013-02-07 10:34:27 +01:00
|
|
|
AddStatus(BUF_READ); // All is done here
|
|
|
|
return FALSE;
|
|
|
|
} // end of InitColumn
|
|
|
|
|
|
|
|
/***********************************************************************/
|
2013-05-10 20:22:21 +02:00
|
|
|
/* CompareColumn: Compare column value with source column value. */
|
2013-02-07 10:34:27 +01:00
|
|
|
/***********************************************************************/
|
2013-05-10 20:22:21 +02:00
|
|
|
bool FNCCOL::CompareColumn(void)
|
2013-02-07 10:34:27 +01:00
|
|
|
{
|
2013-05-10 20:22:21 +02:00
|
|
|
// Compare the unconverted values
|
|
|
|
return Hval->IsEqual(Xcolp->GetValue(), false);
|
|
|
|
} // end of CompareColumn
|
|
|
|
|
|
|
|
// ------------------------ SRCCOL functions ----------------------------
|
2013-02-07 10:34:27 +01:00
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* SRCCOL public constructor. */
|
|
|
|
/***********************************************************************/
|
2013-05-10 20:22:21 +02:00
|
|
|
SRCCOL::SRCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int n)
|
|
|
|
: PRXCOL(cdp, tdbp, cprec, n)
|
2013-02-07 10:34:27 +01:00
|
|
|
{
|
|
|
|
} // end of SRCCOL constructor
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* Initialize the column as pointing to the source column. */
|
|
|
|
/***********************************************************************/
|
2017-02-16 18:01:48 +01:00
|
|
|
bool SRCCOL::Init(PGLOBAL g, PTDB tp)
|
2013-02-07 10:34:27 +01:00
|
|
|
{
|
2015-01-28 00:19:39 +01:00
|
|
|
if (PRXCOL::Init(g, tp))
|
2013-05-10 20:22:21 +02:00
|
|
|
return true;
|
2013-02-07 10:34:27 +01:00
|
|
|
|
|
|
|
AddStatus(BUF_READ); // All is done here
|
2013-05-10 20:22:21 +02:00
|
|
|
return false;
|
2013-02-07 10:34:27 +01:00
|
|
|
} // end of SRCCOL constructor
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* SetColumn: have the column value set from the source column. */
|
|
|
|
/***********************************************************************/
|
|
|
|
void SRCCOL::SetColumn(void)
|
|
|
|
{
|
2013-05-10 20:22:21 +02:00
|
|
|
Value->SetValue_pval(To_Val);
|
2013-02-07 10:34:27 +01:00
|
|
|
} // end of SetColumn
|
|
|
|
|
|
|
|
/***********************************************************************/
|
|
|
|
/* SetColumn: Compare column value with source column value. */
|
|
|
|
/***********************************************************************/
|
2013-05-10 20:22:21 +02:00
|
|
|
bool SRCCOL::CompareLast(void)
|
2013-02-07 10:34:27 +01:00
|
|
|
{
|
|
|
|
// Compare the unconverted values
|
2013-05-10 20:22:21 +02:00
|
|
|
return !Value->IsEqual(To_Val, true);
|
2013-02-07 10:34:27 +01:00
|
|
|
} // end of CompareColumn
|
|
|
|
|
|
|
|
/* --------------------- End of TabPivot/TabQrs ---------------------- */
|