/************* Colblk C++ Functions Source Code File (.CPP) ************/ /* Name: COLBLK.CPP Version 2.0 */ /* */ /* (C) Copyright to the author Olivier BERTRAND 1998-2013 */ /* */ /* This file contains the COLBLK class functions. */ /***********************************************************************/ /***********************************************************************/ /* Include relevant MariaDB header file. */ /***********************************************************************/ #include "my_global.h" /***********************************************************************/ /* Include required application header files */ /* global.h is header containing all global Plug declarations. */ /* plgdbsem.h is header containing the DB applic. declarations. */ /***********************************************************************/ #include "global.h" #include "plgdbsem.h" #include "tabcol.h" #include "colblk.h" #include "xindex.h" #include "xtable.h" /***********************************************************************/ /* COLBLK protected constructor. */ /***********************************************************************/ COLBLK::COLBLK(PCOLDEF cdp, PTDB tdbp, int i) { Next = NULL; Index = i; //Number = 0; ColUse = 0; if ((Cdp = cdp)) { Name = cdp->Name; Format = cdp->F; Opt = cdp->Opt; Long = cdp->Long; Buf_Type = cdp->Buf_Type; ColUse |= cdp->Flags; // Used by CONNECT } else { Name = NULL; memset(&Format, 0, sizeof(FORMAT)); Opt = 0; Long = 0; Buf_Type = TYPE_ERROR; } // endif cdp To_Tdb = tdbp; Nullable = false; Status = BUF_NO; //Value = NULL; done in XOBJECT constructor To_Kcol = NULL; } // end of COLBLK constructor /***********************************************************************/ /* COLBLK constructor used for copying columns. */ /* tdbp is the pointer to the new table descriptor. */ /***********************************************************************/ COLBLK::COLBLK(PCOL col1, PTDB tdbp) { PCOL colp; // Copy the old column block to the new one *this = *col1; Next = NULL; //To_Orig = col1; To_Tdb = tdbp; #ifdef DEBTRACE htrc(" copying COLBLK %s from %p to %p\n", Name, col1, this); #endif if (tdbp) // Attach the new column to the table block if (!tdbp->GetColumns()) tdbp->SetColumns(this); else { for (colp = tdbp->GetColumns(); colp->Next; colp = colp->Next) ; colp->Next = this; } // endelse } // end of COLBLK copy constructor /***********************************************************************/ /* Reset the column descriptor to non evaluated yet. */ /***********************************************************************/ void COLBLK::Reset(void) { Status &= ~BUF_READ; } // end of Reset /***********************************************************************/ /* Compare: compares itself to an (expression) object and returns */ /* true if it is equivalent. */ /***********************************************************************/ bool COLBLK::Compare(PXOB xp) { return (this == xp); } // end of Compare /***********************************************************************/ /* SetFormat: function used to set SELECT output format. */ /***********************************************************************/ bool COLBLK::SetFormat(PGLOBAL g, FORMAT& fmt) { fmt = Format; #ifdef DEBTRACE htrc("COLBLK: %p format=%c(%d,%d)\n", this, *fmt.Type, fmt.Length, fmt.Prec); #endif return false; } // end of SetFormat /***********************************************************************/ /* CheckColumn: a column descriptor is found, say it by returning 1. */ /***********************************************************************/ int COLBLK::CheckColumn(PGLOBAL g, PSQL sqlp, PXOB &p, int &ag) { return 1; } // end of CheckColumn /***********************************************************************/ /* Eval: get the column value from the last read record or from a */ /* matching Index column if there is one. */ /***********************************************************************/ bool COLBLK::Eval(PGLOBAL g) { #ifdef DEBTRACE htrc("Col Eval: %s status=%.4X\n", Name, Status); #endif if (!GetStatus(BUF_READ)) { // if (To_Tdb->IsNull()) // Value->Reset(); if (To_Kcol) To_Kcol->FillValue(Value); else ReadColumn(g); AddStatus(BUF_READ); } // endif return false; } // end of Eval /***********************************************************************/ /* CheckSort: */ /* Used to check that a table is involved in the sort list items. */ /***********************************************************************/ bool COLBLK::CheckSort(PTDB tdbp) { return (tdbp == To_Tdb); } // end of CheckSort /***********************************************************************/ /* MarkCol: see PlugMarkCol for column references to mark. */ /***********************************************************************/ void COLBLK::MarkCol(ushort bits) { ColUse |= bits; #ifdef DEBTRACE htrc(" column R%d.%s marked as %04X\n", To_Tdb->GetTdb_No(), Name, ColUse); #endif } // end of MarkCol /***********************************************************************/ /* InitValue: prepare a column block for read operation. */ /* Now we use Format.Length for the len parameter to avoid strings */ /* to be truncated when converting from string to coded string. */ /* Added in version 1.5 is the arguments GetPrecision() and Domain */ /* in calling AllocateValue. Domain is used for TYPE_TOKEN only, */ /* but why was GetPrecision() not specified ? To be checked. */ /***********************************************************************/ bool COLBLK::InitValue(PGLOBAL g) { if (Value) return false; // Already done // Allocate a Value object if (!(Value = AllocateValue(g, Buf_Type, Format.Length, GetPrecision(), GetDomain(), (To_Tdb) ? To_Tdb->GetCat() : NULL))) return true; Status = BUF_READY; Value->SetNullable(Nullable); #ifdef DEBTRACE htrc(" colp=%p type=%d value=%p coluse=%.4X status=%.4X\n", this, Buf_Type, Value, ColUse, Status); #endif return false; } // end of InitValue /***********************************************************************/ /* SetBuffer: prepare a column block for write operation. */ /***********************************************************************/ bool COLBLK::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check) { sprintf(g->Message, MSG(UNDEFINED_AM), "SetBuffer"); return true; } // end of SetBuffer /***********************************************************************/ /* GetLength: returns an evaluation of the column string length. */ /***********************************************************************/ int COLBLK::GetLengthEx(void) { return Long; } // end of GetLengthEx /***********************************************************************/ /* ReadColumn: what this routine does is to access the last line */ /* read from the corresponding table, extract from it the field */ /* corresponding to this column and convert it to buffer type. */ /***********************************************************************/ void COLBLK::ReadColumn(PGLOBAL g) { sprintf(g->Message, MSG(UNDEFINED_AM), "ReadColumn"); longjmp(g->jumper[g->jump_level], TYPE_COLBLK); } // end of ReadColumn /***********************************************************************/ /* WriteColumn: what this routine does is to access the last line */ /* read from the corresponding table, and rewrite the field */ /* corresponding to this column from the column buffer and type. */ /***********************************************************************/ void COLBLK::WriteColumn(PGLOBAL g) { sprintf(g->Message, MSG(UNDEFINED_AM), "WriteColumn"); longjmp(g->jumper[g->jump_level], TYPE_COLBLK); } // end of WriteColumn /***********************************************************************/ /* Make file output of a column descriptor block. */ /***********************************************************************/ void COLBLK::Print(PGLOBAL g, FILE *f, uint n) { char m[64]; int i; PCOL colp; memset(m, ' ', n); // Make margin string m[n] = '\0'; for (colp = To_Tdb->GetColumns(), i = 1; colp; colp = colp->Next, i++) if (colp == this) break; fprintf(f, "%sR%dC%d type=%d F=%.2s(%d,%d)", m, To_Tdb->GetTdb_No(), i, GetAmType(), Format.Type, Format.Length, Format.Prec); fprintf(f, " coluse=%04X status=%04X buftyp=%d value=%p name=%s\n", ColUse, Status, Buf_Type, Value, Name); } // end of Print /***********************************************************************/ /* Make string output of a column descriptor block. */ /***********************************************************************/ void COLBLK::Print(PGLOBAL g, char *ps, uint z) { sprintf(ps, "R%d.%s", To_Tdb->GetTdb_No(), Name); } // end of Print /***********************************************************************/ /* SPCBLK constructor. */ /***********************************************************************/ SPCBLK::SPCBLK(PCOLUMN cp) : COLBLK((PCOLDEF)NULL, cp->GetTo_Table()->GetTo_Tdb(), 0) { Name = (char*)cp->GetName(); Long = 0; Buf_Type = TYPE_ERROR; } // end of SPCBLK constructor /***********************************************************************/ /* WriteColumn: what this routine does is to access the last line */ /* read from the corresponding table, and rewrite the field */ /* corresponding to this column from the column buffer and type. */ /***********************************************************************/ void SPCBLK::WriteColumn(PGLOBAL g) { sprintf(g->Message, MSG(SPCOL_READONLY), Name); longjmp(g->jumper[g->jump_level], TYPE_COLBLK); } // end of WriteColumn /***********************************************************************/ /* RIDBLK constructor for the ROWID special column. */ /***********************************************************************/ RIDBLK::RIDBLK(PCOLUMN cp, bool rnm) : SPCBLK(cp) { Long = 10; Buf_Type = TYPE_INT; Rnm = rnm; *Format.Type = 'N'; Format.Length = 10; } // end of RIDBLK constructor /***********************************************************************/ /* ReadColumn: what this routine does is to return the ordinal */ /* number of the current row in the table (if Rnm is true) or in the */ /* current file (if Rnm is false) the same except for multiple tables.*/ /***********************************************************************/ void RIDBLK::ReadColumn(PGLOBAL g) { Value->SetValue(To_Tdb->RowNumber(g, Rnm)); } // end of ReadColumn /***********************************************************************/ /* FIDBLK constructor for the FILEID special column. */ /***********************************************************************/ FIDBLK::FIDBLK(PCOLUMN cp) : SPCBLK(cp) { //Is_Key = 2; for when the MUL table indexed reading will be implemented. Long = _MAX_PATH; Buf_Type = TYPE_STRING; *Format.Type = 'C'; Format.Length = Long; #if defined(WIN32) Format.Prec = 1; // Case insensitive #endif // WIN32 Constant = (!((PTDBASE)To_Tdb)->GetDef()->GetMultiple() && To_Tdb->GetAmType() != TYPE_AM_PLG && To_Tdb->GetAmType() != TYPE_AM_PLM); Fn = NULL; } // end of FIDBLK constructor /***********************************************************************/ /* ReadColumn: what this routine does is to return the current */ /* file ID of the table (can change for Multiple tables). */ /***********************************************************************/ void FIDBLK::ReadColumn(PGLOBAL g) { if (Fn != ((PTDBASE)To_Tdb)->GetFile(g)) { char filename[_MAX_PATH]; Fn = ((PTDBASE)To_Tdb)->GetFile(g); PlugSetPath(filename, Fn, ((PTDBASE)To_Tdb)->GetPath()); Value->SetValue_psz(filename); } // endif Fn } // end of ReadColumn /***********************************************************************/ /* TIDBLK constructor for the TABID special column. */ /***********************************************************************/ TIDBLK::TIDBLK(PCOLUMN cp) : SPCBLK(cp) { //Is_Key = 2; for when the MUL table indexed reading will be implemented. Long = 64; Buf_Type = TYPE_STRING; *Format.Type = 'C'; Format.Length = Long; Format.Prec = 1; // Case insensitive Constant = (To_Tdb->GetAmType() != TYPE_AM_PLG && To_Tdb->GetAmType() != TYPE_AM_PLM); Tname = NULL; } // end of TIDBLK constructor /***********************************************************************/ /* ReadColumn: what this routine does is to return the table ID. */ /***********************************************************************/ void TIDBLK::ReadColumn(PGLOBAL g) { if (Tname == NULL) { Tname = (char*)To_Tdb->GetName(); Value->SetValue_psz(Tname); } // endif Tname } // end of ReadColumn