mirror of
				https://github.com/MariaDB/server.git
				synced 2025-11-04 12:56:14 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			414 lines
		
	
	
	
		
			15 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			414 lines
		
	
	
	
		
			15 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/************* Colblk C++ Functions Source Code File (.CPP) ************/
 | 
						|
/*  Name: COLBLK.CPP  Version 2.2                                      */
 | 
						|
/*                                                                     */
 | 
						|
/*  (C) Copyright to the author Olivier BERTRAND          1998-2017    */
 | 
						|
/*                                                                     */
 | 
						|
/*  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;
 | 
						|
    Precision = cdp->Precision;
 | 
						|
    Freq = cdp->Freq;
 | 
						|
    Buf_Type = cdp->Buf_Type;
 | 
						|
    ColUse |= cdp->Flags;       // Used by CONNECT
 | 
						|
    Nullable = !!(cdp->Flags & U_NULLS);
 | 
						|
    Unsigned = !!(cdp->Flags & U_UNSIGNED);
 | 
						|
  } else {
 | 
						|
    Name = NULL;
 | 
						|
    memset(&Format, 0, sizeof(FORMAT));
 | 
						|
    Opt = 0;
 | 
						|
    Long = 0;
 | 
						|
    Precision = 0;
 | 
						|
    Freq = 0;
 | 
						|
    Buf_Type = TYPE_ERROR;
 | 
						|
    Nullable = false;
 | 
						|
    Unsigned = false;
 | 
						|
  } // endif cdp
 | 
						|
 | 
						|
  To_Tdb = tdbp;
 | 
						|
  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;
 | 
						|
 | 
						|
  if (trace(2))
 | 
						|
    htrc(" copying COLBLK %s from %p to %p\n", Name, col1, this);
 | 
						|
 | 
						|
  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, FORMAT& fmt)
 | 
						|
  {
 | 
						|
  fmt = Format;
 | 
						|
 | 
						|
  if (trace(2))
 | 
						|
    htrc("COLBLK: %p format=%c(%d,%d)\n",
 | 
						|
         this, *fmt.Type, fmt.Length, fmt.Prec);
 | 
						|
 | 
						|
  return false;
 | 
						|
  } // end of SetFormat
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  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)
 | 
						|
  {
 | 
						|
  if (trace(2))
 | 
						|
    htrc("Col Eval: %s status=%.4X\n", Name, Status);
 | 
						|
 | 
						|
  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
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  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 GetScale() and Domain        */
 | 
						|
/*  in calling AllocateValue. Domain is used for TYPE_DATE only.       */
 | 
						|
/***********************************************************************/
 | 
						|
bool COLBLK::InitValue(PGLOBAL g)
 | 
						|
  {
 | 
						|
  if (Value)
 | 
						|
    return false;                       // Already done
 | 
						|
 | 
						|
  // Allocate a Value object
 | 
						|
  if (!(Value = AllocateValue(g, Buf_Type, Precision,
 | 
						|
                              GetScale(), Unsigned, GetDomain())))
 | 
						|
    return true;
 | 
						|
 | 
						|
  AddStatus(BUF_READY);
 | 
						|
  Value->SetNullable(Nullable);
 | 
						|
 | 
						|
  if (trace(2))
 | 
						|
    htrc(" colp=%p type=%d value=%p coluse=%.4X status=%.4X\n",
 | 
						|
         this, Buf_Type, Value, ColUse, Status);
 | 
						|
 | 
						|
  return false;
 | 
						|
  } // end of InitValue
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  SetBuffer: prepare a column block for write operation.             */
 | 
						|
/***********************************************************************/
 | 
						|
bool COLBLK::SetBuffer(PGLOBAL g, PVAL, bool, bool)
 | 
						|
  {
 | 
						|
  snprintf(g->Message, sizeof(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)
 | 
						|
{
 | 
						|
  snprintf(g->Message, sizeof(g->Message), MSG(UNDEFINED_AM), "ReadColumn");
 | 
						|
	throw (int)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)
 | 
						|
{
 | 
						|
  snprintf(g->Message, sizeof(g->Message), MSG(UNDEFINED_AM), "WriteColumn");
 | 
						|
	throw (int)TYPE_COLBLK;
 | 
						|
} // end of WriteColumn
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  Make file output of a column descriptor block.                     */
 | 
						|
/***********************************************************************/
 | 
						|
void COLBLK::Printf(PGLOBAL, 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 Printf
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  Make string output of a column descriptor block.                   */
 | 
						|
/***********************************************************************/
 | 
						|
void COLBLK::Prints(PGLOBAL, char *ps, uint)
 | 
						|
  {
 | 
						|
  sprintf(ps, "R%d.%s", To_Tdb->GetTdb_No(), Name);
 | 
						|
  } // end of Prints
 | 
						|
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  SPCBLK constructor.                                                */
 | 
						|
/***********************************************************************/
 | 
						|
SPCBLK::SPCBLK(PCOLUMN cp)
 | 
						|
       : COLBLK((PCOLDEF)NULL, cp->GetTo_Table()->GetTo_Tdb(), 0)
 | 
						|
  {
 | 
						|
  Name = (char*)cp->GetName();
 | 
						|
  Precision = 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)
 | 
						|
{
 | 
						|
  snprintf(g->Message, sizeof(g->Message), MSG(SPCOL_READONLY), Name);
 | 
						|
	throw (int)TYPE_COLBLK;
 | 
						|
} // end of WriteColumn
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  RIDBLK constructor for the ROWID special column.                   */
 | 
						|
/***********************************************************************/
 | 
						|
RIDBLK::RIDBLK(PCOLUMN cp, bool rnm) : SPCBLK(cp)
 | 
						|
  {
 | 
						|
  Precision = 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, OPVAL op) : SPCBLK(cp), Op(op)
 | 
						|
  {
 | 
						|
//Is_Key = 2; for when the MUL table indexed reading will be implemented.
 | 
						|
  Precision = Long = _MAX_PATH;
 | 
						|
  Buf_Type = TYPE_STRING;
 | 
						|
  *Format.Type = 'C';
 | 
						|
  Format.Length = Long;
 | 
						|
#if defined(_WIN32)
 | 
						|
  Format.Prec = 1;          // Case insensitive
 | 
						|
#endif   // _WIN32
 | 
						|
  Constant = (!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 != To_Tdb->GetFile(g)) {
 | 
						|
    char filename[_MAX_PATH];
 | 
						|
 | 
						|
    Fn = To_Tdb->GetFile(g);
 | 
						|
    PlugSetPath(filename, Fn, To_Tdb->GetPath());
 | 
						|
 | 
						|
    if (Op != OP_XX) {
 | 
						|
      char buff[_MAX_PATH];
 | 
						|
 | 
						|
      Value->SetValue_psz(ExtractFromPath(g, buff, filename, Op));
 | 
						|
    } else
 | 
						|
      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.
 | 
						|
  Precision = Long = 64;
 | 
						|
  Buf_Type = TYPE_STRING;
 | 
						|
  *Format.Type = 'C';
 | 
						|
  Format.Length = Long;
 | 
						|
  Format.Prec = 1;          // Case insensitive
 | 
						|
  Constant = (To_Tdb->GetAmType() != TYPE_AM_TBL);
 | 
						|
  Tname = NULL;
 | 
						|
  } // end of TIDBLK constructor
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  ReadColumn: what this routine does is to return the table ID.      */
 | 
						|
/***********************************************************************/
 | 
						|
void TIDBLK::ReadColumn(PGLOBAL)
 | 
						|
  {
 | 
						|
  if (Tname == NULL) {
 | 
						|
    Tname = (char*)To_Tdb->GetName();
 | 
						|
    Value->SetValue_psz(Tname);
 | 
						|
    } // endif Tname
 | 
						|
 | 
						|
  } // end of ReadColumn
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  PRTBLK constructor for the PARTID special column.                  */
 | 
						|
/***********************************************************************/
 | 
						|
PRTBLK::PRTBLK(PCOLUMN cp) : SPCBLK(cp)
 | 
						|
  {
 | 
						|
//Is_Key = 2; for when the MUL table indexed reading will be implemented.
 | 
						|
  Precision = Long = 64;
 | 
						|
  Buf_Type = TYPE_STRING;
 | 
						|
  *Format.Type = 'C';
 | 
						|
  Format.Length = Long;
 | 
						|
  Format.Prec = 1;          // Case insensitive
 | 
						|
  Constant = true;          // TODO: check whether this is true indeed
 | 
						|
  Pname = NULL;
 | 
						|
  } // end of PRTBLK constructor
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  ReadColumn: what this routine does is to return the partition ID.  */
 | 
						|
/***********************************************************************/
 | 
						|
void PRTBLK::ReadColumn(PGLOBAL g)
 | 
						|
  {
 | 
						|
  if (Pname == NULL) {
 | 
						|
    const char *p;
 | 
						|
 | 
						|
    Pname = To_Tdb->GetDef()->GetStringCatInfo(g, "partname", "?");
 | 
						|
    p = strrchr(Pname, '#');
 | 
						|
    Value->SetValue_psz((p) ? p + 1 : Pname);
 | 
						|
    } // endif Pname
 | 
						|
 | 
						|
  } // end of ReadColumn
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  SIDBLK constructor for the SERVID special column.                  */
 | 
						|
/***********************************************************************/
 | 
						|
SIDBLK::SIDBLK(PCOLUMN cp) : SPCBLK(cp)
 | 
						|
  {
 | 
						|
//Is_Key = 2; for when the MUL table indexed reading will be implemented.
 | 
						|
  Precision = Long = 64;
 | 
						|
  Buf_Type = TYPE_STRING;
 | 
						|
  *Format.Type = 'C';
 | 
						|
  Format.Length = Long;
 | 
						|
  Format.Prec = 1;          // Case insensitive
 | 
						|
  Constant = (To_Tdb->GetAmType() != TYPE_AM_TBL);
 | 
						|
  Sname = NULL;
 | 
						|
  } // end of TIDBLK constructor
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  ReadColumn: what this routine does is to return the server ID.     */
 | 
						|
/***********************************************************************/
 | 
						|
void SIDBLK::ReadColumn(PGLOBAL)
 | 
						|
  {
 | 
						|
//if (Sname == NULL) {
 | 
						|
    Sname = To_Tdb->GetServer();
 | 
						|
    Value->SetValue_psz(Sname);
 | 
						|
//  } // endif Sname
 | 
						|
 | 
						|
  } // end of ReadColumn
 |