/************ TabOccur CPP Declares Source Code File (.CPP) ************/ /* Name: TABOCCUR.CPP Version 1.2 */ /* */ /* (C) Copyright to the author Olivier BERTRAND 2013 - 2021 */ /* */ /* OCCUR: Table that provides a view of a source table where the */ /* contain of several columns of the source table is placed in only */ /* one column, the OCCUR column, this resulting into several rows. */ /***********************************************************************/
/***********************************************************************/ /* Include relevant section of system dependant header files. */ /***********************************************************************/ #include"my_global.h" #include"table.h"// MySQL table definitions #ifdefined(_WIN32) #include <stdlib.h> #include <stdio.h> #ifdefined(__BORLANDC__) #define __MFC_COMPAT__ // To define min/max as macro #endif //#include <windows.h> #else #ifdefined(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
/***********************************************************************/ /* Prepare and count columns in the column list. */ /***********************************************************************/ int PrepareColist(char *colist)
{ char *p, *pn; int n = 0;
// Count the number of columns and change separator into null char for (pn = colist; ; pn += (strlen(pn) + 1)) // Separator can be ; if colist was specified in the option_list if ((p = strchr(pn, ',')) || (p = strchr(pn, ';'))) {
*p++ = '\0';
n++;
} else { if (*pn)
n++;
break;
} // endif p
return n;
} // end of PrepareColist
/************************************************************************/ /* OcrColumns: constructs the result blocks containing all the columns */ /* of the object table that will be retrieved by GetData commands. */ /************************************************************************/ bool OcrColumns(PGLOBAL g, PQRYRES qrp, constchar *col, constchar *ocr, constchar *rank)
{ char *pn, *colist; int i, k, m, n = 0, c = 0, j = qrp->Nblin; bool rk, b = false;
PCOLRES crp;
if (!col || !*col) {
strcpy(g->Message, "Missing colist"); returntrue;
} // endif col
// Prepare the column list
colist = PlugDup(g, col);
m = PrepareColist(colist);
if ((rk = (rank && *rank))) { if (m == 1) {
strcpy(g->Message, "Cannot handle one column colist and rank"); returntrue;
} // endif m
for (k = 0, pn = colist; k < m; k++, pn += (strlen(pn) + 1))
n = MY_MAX(n, (signed)strlen(pn));
} // endif k
// Default occur column name is the 1st colist column name if (!ocr || !*ocr)
ocr = colist;
/**********************************************************************/ /* Replace the columns of the colist by the rank and occur columns. */ /**********************************************************************/ for (i = 0; i < qrp->Nblin; i++) { for (k = 0, pn = colist; k < m; k++, pn += (strlen(pn) + 1)) if (!stricmp(pn, qrp->Colresp->Kdata->GetCharValue(i))) break;
if (k < m) { // This column belongs to colist if (rk) { // Place the rank column here for (crp = qrp->Colresp; crp; crp = crp->Next) switch (crp->Fld) { case FLD_NAME: crp->Kdata->SetValue((char*)rank, i); break; case FLD_TYPE: crp->Kdata->SetValue(TYPE_STRING, i); break; case FLD_PREC: crp->Kdata->SetValue(n, i); break; case FLD_SCALE: crp->Kdata->SetValue(0, i); break; case FLD_NULL: crp->Kdata->SetValue(0, i); break; case FLD_REM: crp->Kdata->Reset(i); break; default: ; // Ignored by CONNECT
} // endswich Fld
rk = false;
} elseif (!b) { // First remaining listed column, will be the occur column for (crp = qrp->Colresp; crp; crp = crp->Next) switch (crp->Fld) { case FLD_NAME: crp->Kdata->SetValue((char*)ocr, i); break; case FLD_REM: crp->Kdata->Reset(i); break; default: ; // Nothing to do
} // endswich Fld
b = true;
} elseif (j == qrp->Nblin)
j = i; // Column to remove
c++;
} elseif (j < i) { // Move this column in empty spot for (crp = qrp->Colresp; crp; crp = crp->Next)
crp->Kdata->Move(i, j);
j++;
} // endif k
} // endfor i
// Check whether all columns of the list where found if (c < m) {
strcpy(g->Message, "Some colist columns are not in the source table"); returntrue;
} // endif crp
/**********************************************************************/ /* Set the number of columns of the table. */ /**********************************************************************/
qrp->Nblin = j; returnfalse;
} // end of OcrColumns
/************************************************************************/ /* OcrSrcCols: constructs the result blocks containing all the columns */ /* of the object table that will be retrieved by GetData commands. */ /************************************************************************/ bool OcrSrcCols(PGLOBAL g, PQRYRES qrp, constchar *col, constchar *ocr, constchar *rank)
{ char *pn, *colist; int i, k, m, n = 0, c = 0; bool rk, b = false;
PCOLRES crp, rcrp, *pcrp;
if (!col || !*col) {
strcpy(g->Message, "Missing colist"); returntrue;
} // endif col
// Prepare the column list
colist = PlugDup(g, col);
m = PrepareColist(colist);
if ((rk = (rank && *rank))) for (k = 0, pn = colist; k < m; k++, pn += (strlen(pn) + 1))
n = MY_MAX(n, (signed)strlen(pn));
// Default occur column name is the 1st colist column name if (!ocr || !*ocr)
ocr = colist;
/**********************************************************************/ /* Replace the columns of the colist by the rank and occur columns. */ /**********************************************************************/ for (i = 0, pcrp = &qrp->Colresp; (crp = *pcrp); ) { for (k = 0, pn = colist; k < m; k++, pn += (strlen(pn) + 1)) if (!stricmp(pn, crp->Name)) break;
if (k < m) { // This column belongs to colist
c++;
// First remaining listed column, will be the occur column
crp->Name = (char*)ocr;
b = true;
} else {
*pcrp = crp->Next; // Remove this column continue;
} // endif b
// Check whether all columns of the list where found if (c < m) {
strcpy(g->Message, "Some colist columns are not in the source table"); returntrue;
} // endif crp
/**********************************************************************/ /* Set the number of columns of the table. */ /**********************************************************************/
qrp->Nblin = i; returnfalse;
} // end of OcrSrcCols
/* -------------- Implementation of the OCCUR classes ---------------- */
/***********************************************************************/ /* DefineAM: define specific AM block values from OCCUR table. */ /***********************************************************************/ bool OCCURDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
{
Rcol = GetStringCatInfo(g, "RankCol", "");
Colist = GetStringCatInfo(g, "Colist", "");
Xcol = GetStringCatInfo(g, "OccurCol", Colist); return PRXDEF::DefineAM(g, am, poff);
} // end of DefineAM
/***********************************************************************/ /* GetTable: makes a new TDB of the proper type. */ /***********************************************************************/
PTDB OCCURDEF::GetTable(PGLOBAL g, MODE)
{ if (Catfunc != FNC_COL) returnnew(g) TDBOCCUR(this); else returnnew(g) TDBTBC(this);
/***********************************************************************/ /* Implementation of the TDBOCCUR class. */ /***********************************************************************/
TDBOCCUR::TDBOCCUR(POCCURDEF tdp) : TDBPRX(tdp)
{ //Tdbp = NULL; // Source table (in TDBPRX)
Tabname = tdp->Tablep->GetName(); // Name of source table
Colist = tdp->Colist; // List of source columns
Xcolumn = tdp->Xcol; // Occur column name
Rcolumn = tdp->Rcol; // Rank column name
Xcolp = NULL; // To the OCCURCOL column
Col = NULL; // To source column blocks array
Mult = PrepareColist(Colist); // Multiplication factor
N = 0; // The current table index
M = 0; // The occurrence rank
RowFlag = 0; // 0: Ok, 1: Same, 2: Skip
} // end of TDBOCCUR constructor
/***********************************************************************/ /* Initializes the table. */ /***********************************************************************/ bool TDBOCCUR::InitTable(PGLOBAL g)
{ if (!Tdbp) // Get the table description block of this table if (!(Tdbp = GetSubTable(g, ((POCCURDEF)To_Def)->Tablep, TRUE))) returnTRUE;
if (!Tdbp->IsView()) if (MakeColumnList(g)) returnTRUE;
for (colp = Columns; colp; colp = colp->GetNext()) if (colp->GetAmType() == TYPE_AM_PRX) if (((PPRXCOL)colp)->Init(g, NULL)) returntrue;
Col = (PCOL*)PlugSubAlloc(g, NULL, Mult * sizeof(PCOL));
for (i = 0, pn = Colist; i < Mult; i++, pn += (strlen(pn) + 1)) { if (!(Col[i] = Tdbp->ColDB(g, pn, 0))) { // Column not found in table
snprintf(g->Message, sizeof(g->Message), MSG(COL_ISNOT_TABLE), pn, Tabname); returntrue;
} // endif Col
/***********************************************************************/ /* Allocate OCCUR column description block for a view. */ /***********************************************************************/ bool TDBOCCUR::ViewColumnList(PGLOBAL g)
{ char *pn; int i;
PCOL colp, cp;
PTDBMY tdbp;
if (!Tdbp->IsView()) returnfalse;
if (Tdbp->GetAmType() != TYPE_AM_MYSQL) {
strcpy(g->Message, "View is not MySQL"); returntrue;
} else
tdbp = (PTDBMY)Tdbp;
for (cp = Columns; cp; cp = cp->GetNext()) if (cp->GetAmType() == TYPE_AM_PRX) { if ((colp = tdbp->MakeFieldColumn(g, cp->GetName()))) {
((PPRXCOL)cp)->Colp = colp;
((PPRXCOL)cp)->To_Val = colp->GetValue();
} else returntrue;
} // endif Type
Col = (PCOL*)PlugSubAlloc(g, NULL, Mult * sizeof(PCOL));
for (i = 0, pn = Colist; i < Mult; i++, pn += (strlen(pn) + 1)) if (!(Col[i] = tdbp->MakeFieldColumn(g, pn))) { // Column not found in table
snprintf(g->Message, sizeof(g->Message), MSG(COL_ISNOT_TABLE), pn, Tabname); returntrue;
} // endif Col
returnfalse;
} // end of ViewColumnList
/***********************************************************************/ /* OCCUR GetMaxSize: returns the maximum number of rows in the table. */ /***********************************************************************/ int TDBOCCUR::GetMaxSize(PGLOBAL g)
{ if (MaxSize < 0) { if (!(Tdbp = GetSubTable(g, ((POCCURDEF)To_Def)->Tablep, TRUE))) return0;
MaxSize = Mult * Tdbp->GetMaxSize(g);
} // endif MaxSize
return MaxSize;
} // end of GetMaxSize
/***********************************************************************/ /* In this sample, ROWID will be the (virtual) row number, */ /* while ROWNUM will be the occurrence rank in the multiple column. */ /***********************************************************************/ int TDBOCCUR::RowNumber(PGLOBAL, bool b)
{ return (b) ? M : N;
} // end of RowNumber
/***********************************************************************/ /* OCCUR Access Method opening routine. */ /***********************************************************************/ bool TDBOCCUR::OpenDB(PGLOBAL g)
{ if (Use == USE_OPEN) { /*******************************************************************/ /* Table already open, just replace it at its beginning. */ /*******************************************************************/
N = M = 0;
RowFlag = 0;
if (Xcolp)
Xcolp->Xreset();
return Tdbp->OpenDB(g);
} // endif use
if (Mode != MODE_READ) { /*******************************************************************/ /* Currently OCCUR tables cannot be modified. */ /*******************************************************************/
strcpy(g->Message, "OCCUR tables are read only"); returnTRUE;
} // endif Mode
/*********************************************************************/ /* Do it here if not done yet. */ /*********************************************************************/ if (InitTable(g)) returnTRUE;
if (Xcolp) // Lock this column so it is evaluated by its table only
Xcolp->AddStatus(BUF_READ);
if (To_Key_Col || To_Kindex) { /*******************************************************************/ /* Direct access of OCCUR tables is not implemented yet. */ /*******************************************************************/
strcpy(g->Message, "No direct access to OCCUR tables"); returnTRUE;
} // endif To_Key_Col
/*********************************************************************/ /* Do open the source table. */ /*********************************************************************/ if (Tdbp->OpenDB(g)) returnTRUE;
Use = USE_OPEN; return ViewColumnList(g);
} // end of OpenDB
/***********************************************************************/ /* Data Base read routine for OCCUR access method. */ /***********************************************************************/ int TDBOCCUR::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;
if (Xcolp) {
RowFlag = 0;
Xcolp->ReadColumn(g);
M = Xcolp->GetI();
} // endif Xcolp
/***********************************************************************/ /* OCCURCOL public constructor. */ /***********************************************************************/
OCCURCOL::OCCURCOL(PCOLDEF cdp, PTDBOCCUR tdbp, int n)
: COLBLK(cdp, tdbp, n)
{ // Set additional OCCUR access method information for column.
I = 0;
} // end of OCCURCOL constructor
/***********************************************************************/ /* ReadColumn: what this routine does is to access the columns of */ /* list, extract their value and convert it to buffer type. */ /***********************************************************************/ void OCCURCOL::ReadColumn(PGLOBAL g)
{
PTDBOCCUR tdbp = (PTDBOCCUR)To_Tdb;
PCOL *col = tdbp->Col;
for (; I < tdbp->Mult; I++) {
col[I]->ReadColumn(g);
if (Nullable || !col[I]->GetValue()->IsZero()) break;
} // endfor I
if (I == tdbp->Mult) { // No more values, go to next source row
tdbp->RowFlag = 2;
I = 0; return;
} // endif I
// Set the OCCUR column value from the Ith source column value
Value->SetValue_pval(col[I++]->GetValue());
tdbp->RowFlag = 1;
} // end of ReadColumn
/***********************************************************************/ /* ReadColumn: what this routine does is to access the Mth columns of */ /* list, extract its name and set to it the rank column value. */ /***********************************************************************/ void RANKCOL::ReadColumn(PGLOBAL)
{
PTDBOCCUR tdbp = (PTDBOCCUR)To_Tdb;
PCOL *col = tdbp->Col;
// Set the RANK column value from the Mth source column name if (tdbp->M)
Value->SetValue_psz(col[tdbp->M - 1]->GetName()); else {
Value->Reset();
if (Nullable)
Value->SetNull(true);
} // endelse
} // end of ReadColumn
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet am 2026-10-08)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.