1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

Adding the CONNECT storage engine sources.

This commit is contained in:
Alexander Barkov
2013-01-18 19:21:44 +04:00
parent 055b62f404
commit d7143a4160
103 changed files with 61313 additions and 0 deletions

View File

@@ -0,0 +1,65 @@
# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
if( WITH_WARNINGS )
add_definitions(-Wall -Wfatal-errors -Wextra)
message(STATUS "GCC: All warnings enabled")
else()
add_definitions(--no-warnings)
message(STATUS "GCC: All warnings disabled")
endif()
add_definitions( -DUNIX -DLINUX -DUBUNTU -DMARIADB -DFORCE_INIT_OF_VARS -DMYSQL_DYNAMIC_PLUGIN )
add_definitions( -DHUGE_SUPPORT -DXML_SUPPORT -DMYSQL_SUPPORT -DZIP_SUPPORT -DODBC_SUPPORT )
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpermissive -fexceptions -fPIC ")
INCLUDE_DIRECTORIES(/usr/include/libxml2)
INCLUDE_DIRECTORIES(/usr/include/i386-linux-gnu)
INCLUDE_DIRECTORIES()
get_property(inc_dirs DIRECTORY PROPERTY INCLUDE_DIRECTORIES)
message("inc_dirs = ${inc_dirs}")
SET(CONNECT_PLUGIN_STATIC "connect")
SET(CONNECT_PLUGIN_DYNAMIC "connect")
SET(CONNECT_SOURCES
ha_connect.cc connect.cc user_connect.cc mycat.cc
fmdlex.c inihandl.c osutil.c plugutil.c rcmsg.c
csort.cpp maputil.cpp plgdbutl.cpp
colblk.cpp reldef.cpp tabcol.cpp table.cpp
filamap.cpp filamdbf.cpp filamfix.cpp filamtxt.cpp filamvct.cpp
tabdos.cpp tabfix.cpp tabfmt.cpp tabmul.cpp tabsys.cpp tabvct.cpp
valblk.cpp value.cpp xindex.cpp xobject.cpp
tabodbc.cpp odbconn.cpp
filamzip.cpp tabtbl.cpp myconn.cpp myutil.cpp tabmysql.cpp
tabxml.cpp plgxml.cpp libdoc.cpp)
SET(XML_LIBRARY "-L/usr/lib/i386-linux-gnu -lxml2")
#SET(MYSQL_LIBRARY "-L/usr/local/mysql/lib -lmysqlclient")
#SET(MYSQL_LIBRARY "-L/ ../../libmysql/libmysqlclient.a")
# For static linking
SET(MYSQL_LIBRARY mysqlclient)
# For dynaric linking
#SET(MYSQL_LIBRARY libmysql)
SET(ODBC_LIBRARY "-L/usr/lib -lodbc")
MYSQL_ADD_PLUGIN(connect ${CONNECT_SOURCES}
STORAGE_ENGINE MODULE_ONLY
MODULE_OUTPUT_NAME "ha_connect"
LINK_LIBRARIES ${ZLIB_LIBRARY} ${XML_LIBRARY} ${MYSQL_LIBRARY} ${ODBC_LIBRARY})

57
storage/connect/block.h Normal file
View File

@@ -0,0 +1,57 @@
/**************** Block H Declares Source Code File (.H) ***************/
/* Name: BLOCK.H Version 2.0 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 1998 */
/* */
/* This file contains the BLOCK pure virtual class definition. */
/*---------------------------------------------------------------------*/
/* Note: one of the main purpose of this base class is to take care */
/* of the very specific way Plug handles memory allocation. */
/* Instead of allocating small chunks of storage via new or malloc */
/* Plug works in its private memory pool in which it does the sub- */
/* allocation using the function PlugSubAlloc. These are never freed */
/* separately but when a transaction is terminated, the entire pool */
/* is set to empty, resulting in a very fast and efficient allocate */
/* process, no garbage collection problem, and an automatic recovery */
/* procedure (via LongJump) when the memory is exhausted. */
/* For this to work new must be given two parameters, first the */
/* global pointer of the Plug application, and an optional pointer to */
/* the memory pool to use, defaulting to NULL meaning using the Plug */
/* standard default memory pool, example: */
/* tabp = new(g) XTAB("EMPLOYEE"); */
/* allocates a XTAB class object in the standard Plug memory pool. */
/***********************************************************************/
#if !defined(BLOCK_DEFINED)
#define BLOCK_DEFINED
#if defined(WIN32) && !defined(NOEX)
#define DllExport __declspec( dllexport )
#else // !WIN32
#define DllExport
#endif // !WIN32
/***********************************************************************/
/* Definition of class BLOCK with its method function new. */
/***********************************************************************/
typedef class BLOCK *PBLOCK;
class DllExport BLOCK {
public:
void * operator new(size_t size, PGLOBAL g, void *p = NULL) {
#ifdef DEBTRACE
if (debug != NULL)
htrc("New BLOCK: size=%d g=%p p=%p\n", size, g, p);
#endif
return (PlugSubAlloc(g, p, size));
} // end of new
virtual void Print(PGLOBAL, FILE *, uint) {} // Produce file desc
virtual void Print(PGLOBAL, char *, uint) {} // Produce string desc
#if !defined(__BORLANDC__)
// Avoid warning C4291 by defining a matching dummy delete operator
void operator delete(void *, PGLOBAL, void *) {}
#endif
}; // end of class BLOCK
#endif // !BLOCK_DEFINED

150
storage/connect/catalog.h Normal file
View File

@@ -0,0 +1,150 @@
/*************** Catalog H Declares Source Code File (.H) **************/
/* Name: CATALOG.H Version 3.2 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 2000-2012 */
/* */
/* This file contains the CATALOG PlugDB classes definitions. */
/***********************************************************************/
#ifndef __CATALOG__H
#define __CATALOG__H
#include "block.h"
/***********************************************************************/
/* Defines the length of a buffer to contain entire table section. */
/***********************************************************************/
#define PLG_MAX_PATH 144 /* Must be the same across systems */
#define PLG_BUFF_LEN 100 /* Number of lines in binary file buffer */
#if !defined(WIN32)
/**************************************************************************/
/* Defines specific to Windows and ODBC. */
/**************************************************************************/
#define SQL_CHAR 1
#define SQL_NUMERIC 2
#define SQL_DECIMAL 3
#define SQL_INTEGER 4
#define SQL_SMALLINT 5
#define SQL_FLOAT 6
#define SQL_REAL 7
#define SQL_DOUBLE 8
#define SQL_TIMESTAMP 11
#define SQL_VARCHAR 12
#define SQL_NULLABLE_UNKNOWN 2
#define SQL_ALL_EXCEPT_LIKE 2
#define SQL_SEARCHABLE 3
#define SQL_ALL_TYPES 0
#define SQL_TABLE_STAT 0
#define SQL_BEST_ROWID 1
#define SQL_PC_NOT_PSEUDO 1
#define SQL_PC_PSEUDO 2
#define SQL_SCOPE_CURROW 0
#endif // !WIN32
//typedef class INDEXDEF *PIXDEF;
/***********************************************************************/
/* Defines the structure used to enumerate tables or views. */
/***********************************************************************/
typedef struct _curtab {
PRELDEF CurTdb;
char *Curp;
char *Tabpat;
bool Ispat;
bool NoView;
int Nt;
char *Type[16];
} CURTAB, *PCURTAB;
/***********************************************************************/
/* Defines the structure used to get column catalog info. */
/***********************************************************************/
typedef struct _colinfo {
char *Name;
int Type;
int Offset;
int Length;
int Key;
int Prec;
int Opt;
char *Remark;
char *Datefmt;
char *Fieldfmt;
ushort Flags; // Used by MariaDB CONNECT handlers
} COLINFO, *PCOLINFO;
/***********************************************************************/
/* CATALOG: base class for catalog classes. */
/***********************************************************************/
class DllExport CATALOG {
friend class RELDEF;
friend class TABDEF;
friend class DIRDEF;
friend class OEMDEF;
public:
CATALOG(void); // Constructor
// Implementation
void *GetDescp(void) {return Descp;}
PRELDEF GetTo_Desc(void) {return To_Desc;}
//PSZ GetDescFile(void) {return DescFile;}
int GetCblen(void) {return Cblen;}
bool GetDefHuge(void) {return DefHuge;}
void SetDefHuge(bool b) {DefHuge = b;}
bool GetSepIndex(void) {return SepIndex;}
void SetSepIndex(bool b) {SepIndex = b;}
char *GetCbuf(void) {return Cbuf;}
char *GetDataPath(void) {return (char*)DataPath;}
// Methods
virtual void Reset(void) {}
virtual void SetDataPath(PGLOBAL g, const char *path) {}
virtual bool GetBoolCatInfo(LPCSTR name, PSZ what, bool bdef) {return bdef;}
virtual bool SetIntCatInfo(LPCSTR name, PSZ what, int ival) {return false;}
virtual int GetIntCatInfo(LPCSTR name, PSZ what, int idef) {return idef;}
virtual int GetSizeCatInfo(LPCSTR name, PSZ what, PSZ sdef) {return 0;}
virtual int GetCharCatInfo(LPCSTR name, PSZ what, PSZ sdef, char *buf, int size)
{strncpy(buf, sdef, size); return size;}
virtual char *GetStringCatInfo(PGLOBAL g, PSZ name, PSZ what, PSZ sdef)
{return sdef;}
virtual int GetColCatInfo(PGLOBAL g, PTABDEF defp) {return -1;}
virtual bool GetIndexInfo(PGLOBAL g, PTABDEF defp) {return true;}
virtual bool CheckName(PGLOBAL g, char *name) {return true;}
virtual bool ClearName(PGLOBAL g, PSZ name) {return true;}
virtual PRELDEF MakeOneTableDesc(PGLOBAL g, LPCSTR name, LPCSTR am) {return NULL;}
virtual PRELDEF GetTableDescEx(PGLOBAL g, PTABLE tablep) {return NULL;}
virtual PRELDEF GetTableDesc(PGLOBAL g, LPCSTR name, LPCSTR am,
PRELDEF *prp = NULL) {return NULL;}
virtual PRELDEF GetFirstTable(PGLOBAL g) {return NULL;}
virtual PRELDEF GetNextTable(PGLOBAL g) {return NULL;}
virtual bool TestCond(PGLOBAL g, const char *name, const char *type) {return true;}
virtual bool DropTable(PGLOBAL g, PSZ name, bool erase) {return true;}
virtual PTDB GetTable(PGLOBAL g, PTABLE tablep, MODE mode = MODE_READ) {return NULL;}
virtual void TableNames(PGLOBAL g, char *buffer, int maxbuf, int info[]) {}
virtual void ColumnNames(PGLOBAL g, char *tabname, char *buffer,
int maxbuf, int info[]) {}
virtual void ColumnDefs(PGLOBAL g, char *tabname, char *buffer,
int maxbuf, int info[]) {}
virtual void *DecodeValues(PGLOBAL g, char *tabname, char *colname,
char *buffer, int maxbuf, int info[]) {return NULL;}
virtual int ColumnType(PGLOBAL g, char *tabname, char *colname) {return 0;}
virtual void ClearDB(PGLOBAL g) {}
protected:
virtual bool ClearSection(PGLOBAL g, const char *key, const char *section) {return true;}
virtual PRELDEF MakeTableDesc(PGLOBAL g, LPCSTR name, LPCSTR am) {return NULL;}
// Members
PRELDEF To_Desc; /* To chain of relation desc. */
void *Descp; /* To DB description area */
//AREADEF DescArea; /* Table desc. area size */
char *Cbuf; /* Buffer used for col section */
int Cblen; /* Length of suballoc. buffer */
CURTAB Ctb; /* Used to enumerate tables */
bool DefHuge; /* true: tables default to huge */
bool SepIndex; /* true: separate index files */
//char DescFile[_MAX_PATH]; /* DB description filename */
LPCSTR DataPath; /* Is the Path of DB data dir */
}; // end of class CATALOG
#endif // __CATALOG__H

View File

@@ -0,0 +1,42 @@
/************** PlgDBSem H Declares Source Code File (.H) **************/
/* Name: CHKLVL.H Version 1.1 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 2009 */
/* */
/* This file contains the definition of the checking level constants. */
/***********************************************************************/
#if !defined(_CHKLVL_DEFINED_)
#define _CHKLVL_DEFINED_
/***********************************************************************/
/* Following definitions are used to indicate the level of checking. */
/***********************************************************************/
enum CHKLVL {CHK_NO = 0x00, /* No checking */
CHK_TYPE = 0x01, /* Check types for Insert/Update */
CHK_UPDATE = 0x02, /* Two pass checking of Update */
CHK_DELETE = 0x04, /* Indexed checking of Delete */
CHK_JOIN = 0x08, /* Check types joining tables */
CHK_OPT = 0x10, /* Automatic optimize on changes */
CHK_MANY = 0x20, /* Check many-to-many joins */
CHK_ALL = 0x3F, /* All of the above */
CHK_STD = 0x1E, /* Standard level of checking */
CHK_MAXRES = 0x40, /* Prevent Maxres recalculation */
CHK_ONLY = 0x100}; /* Just check, no action (NIY) */
/***********************************************************************/
/* Following definitions are used to indicate the execution mode. */
/***********************************************************************/
enum XMOD {XMOD_EXECUTE = 0, /* DOS execution mode */
XMOD_PREPARE = 1, /* Prepare mode */
XMOD_TEST = 2, /* Test mode */
XMOD_CONVERT = 3}; /* HQL conversion mode */
/***********************************************************************/
/* Following definitions indicate the use of a temporay file. */
/***********************************************************************/
enum USETEMP {TMP_AUTO = 0, /* Best choice */
TMP_NO = 1, /* Never */
TMP_YES = 2, /* Always */
TMP_FORCE = 3}; /* Forced for MAP tables */
#endif // _CHKLVL_DEFINED_

379
storage/connect/colblk.cpp Normal file
View File

@@ -0,0 +1,379 @@
/************* Colblk C++ Functions Source Code File (.CPP) ************/
/* Name: COLBLK.CPP Version 1.9 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 1998-2012 */
/* */
/* 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;
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;
#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

180
storage/connect/colblk.h Normal file
View File

@@ -0,0 +1,180 @@
/*************** Colblk H Declares Source Code File (.H) ***************/
/* Name: COLBLK.H Version 1.5 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 2005-2012 */
/* */
/* This file contains the COLBLK and derived classes declares. */
/***********************************************************************/
#ifndef __COLBLK__H
#define __COLBLK__H
/***********************************************************************/
/* Include required application header files */
/***********************************************************************/
#include "xobject.h"
#include "reldef.h"
/***********************************************************************/
/* Class COLBLK: Base class for table column descriptors. */
/***********************************************************************/
class DllExport COLBLK : public XOBJECT {
friend class TDBPIVOT;
protected:
// Default constructors used by derived classes
COLBLK(PCOLDEF cdp = NULL, PTDB tdbp = NULL, int i = 0);
COLBLK(PCOL colp, PTDB tdbp = NULL); // Used in copy process
COLBLK(int n) {} // Used when changing a column class in TDBXML
public:
// Implementation
virtual int GetType(void) {return TYPE_COLBLK;}
virtual int GetResultType(void) {return Buf_Type;}
virtual int GetPrecision(void) {return Format.Prec;}
virtual int GetLength(void) {return Long;}
virtual int GetLengthEx(void);
virtual int GetAmType() {return TYPE_AM_ERROR;}
virtual void SetOk(void) {Status |= BUF_EMPTY;}
virtual PTDB GetTo_Tdb(void) {return To_Tdb;}
PCOL GetNext(void) {return Next;}
PSZ GetName(void) {return Name;}
int GetIndex(void) {return Index;}
int GetOpt(void) {return Opt;}
ushort GetColUse(void) {return ColUse;}
ushort GetColUse(ushort u) {return (ColUse & u);}
ushort GetStatus(void) {return Status;}
ushort GetStatus(ushort u) {return (Status & u);}
void SetColUse(ushort u) {ColUse = u;}
void SetStatus(ushort u) {Status = u;}
void AddColUse(ushort u) {ColUse |= u;}
void AddStatus(ushort u) {Status |= u;}
void SetNext(PCOL cp) {Next = cp;}
void SetKcol(PXCOL kcp) {To_Kcol = kcp;}
PCOLDEF GetCdp(void) {return Cdp;}
PSZ GetDomain(void) {return (Cdp) ? Cdp->Decode : NULL;}
PSZ GetDesc(void) {return (Cdp) ? Cdp->Desc : NULL;}
PSZ GetFmt(void) {return (Cdp) ? Cdp->Fmt : NULL;}
// Methods
virtual void Reset(void);
virtual bool Compare(PXOB xp);
virtual bool SetFormat(PGLOBAL, FORMAT&);
virtual int CheckColumn(PGLOBAL g, PSQL sqlp, PXOB &xp, int &ag);
virtual bool IsSpecial(void) {return false;}
virtual int CheckSpcCol(PTDB tdbp, int n) {return 2;}
virtual bool CheckSort(PTDB tdbp);
virtual void MarkCol(ushort bits);
virtual bool Eval(PGLOBAL g);
virtual bool SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check);
virtual void SetTo_Val(PVAL valp) {}
virtual void ReadColumn(PGLOBAL g);
virtual void WriteColumn(PGLOBAL g);
virtual void Print(PGLOBAL g, FILE *, uint);
virtual void Print(PGLOBAL g, char *, uint);
virtual bool VarSize(void) {return false;}
virtual bool IsColInside(PCOL colp) {return this == colp;}
bool InitValue(PGLOBAL g);
protected:
// Members
PCOL Next; // Next column in table
PSZ Name; // Column name
PCOLDEF Cdp; // To column definition block
PTDB To_Tdb; // Points to Table Descriptor Block
PXCOL To_Kcol; // Points to Xindex matching column
int Index; // Column number in table
int Opt; // Cluster/sort information
int Buf_Type; // Data type
int Long; // Internal length in table
FORMAT Format; // Output format
ushort ColUse; // Column usage
ushort Status; // Column read status
}; // end of class COLBLK
/***********************************************************************/
/* Class SPCBLK: Base class for special column descriptors. */
/***********************************************************************/
class SPCBLK : public COLBLK {
public:
// Constructor
SPCBLK(PCOLUMN cp);
// Implementation
virtual int GetAmType(void) = 0;
virtual bool GetRnm(void) {return false;}
// Methods
virtual bool IsSpecial(void) {return true;}
virtual void ReadColumn(PGLOBAL g) = 0;
virtual void WriteColumn(PGLOBAL g);
protected:
// Default constructor not to be used
SPCBLK(void) : COLBLK(1) {}
}; // end of class SPCBLK
/***********************************************************************/
/* Class RIDBLK: ROWID special column descriptor. */
/***********************************************************************/
class RIDBLK : public SPCBLK {
public:
// Constructor
RIDBLK(PCOLUMN cp, bool rnm);
// Implementation
virtual int GetAmType(void) {return TYPE_AM_ROWID;}
virtual bool GetRnm(void) {return Rnm;}
// Methods
virtual void ReadColumn(PGLOBAL g);
protected:
bool Rnm; // False for RowID, True for RowNum
}; // end of class RIDBLK
/***********************************************************************/
/* Class FIDBLK: FILEID special column descriptor. */
/***********************************************************************/
class FIDBLK : public SPCBLK {
public:
// Constructor
FIDBLK(PCOLUMN cp);
// Implementation
virtual int GetAmType(void) {return TYPE_AM_FILID;}
// Methods
virtual void Reset(void) {} // This is a pseudo constant column
virtual int CheckSpcCol(PTDB tdbp, int n)
{return (n == 2 && tdbp == To_Tdb) ? 1 : 2;}
virtual void ReadColumn(PGLOBAL g);
protected:
PSZ Fn; // The current To_File of the table
}; // end of class FIDBLK
/***********************************************************************/
/* Class TIDBLK: TABID special column descriptor. */
/***********************************************************************/
class TIDBLK : public SPCBLK {
public:
// Constructor
TIDBLK(PCOLUMN cp);
// Implementation
virtual int GetAmType(void) {return TYPE_AM_TABID;}
// Methods
virtual void Reset(void) {} // This is a pseudo constant column
virtual int CheckSpcCol(PTDB tdbp, int n)
{return (n == 3 && tdbp == To_Tdb) ? 1 : 2;}
virtual void ReadColumn(PGLOBAL g);
protected:
// Default constructor not to be used
TIDBLK(void) {}
// Members
PSZ Tname; // The current table name
}; // end of class TIDBLK
#endif // __COLBLK__H

866
storage/connect/connect.cc Normal file
View File

@@ -0,0 +1,866 @@
/* Copyright (C) Olivier Bertrand 2004 - 2012
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/***********************************************************************/
/* Author Olivier BERTRAND bertrandop@gmail.com 2004-2012 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
/* This program are the CONNECT general purpose semantic routines. */
/***********************************************************************/
#ifdef __GNUC__
#pragma implementation // gcc: Class implementation
#endif
/***********************************************************************/
/* Include application header files */
/* */
/* global.h is header containing all global declarations. */
/* plgdbsem.h is header containing the DB applic. declarations. */
/***********************************************************************/
#define MYSQL_SERVER 1
#define DONT_DEFINE_VOID
#include "handler.h"
#undef OFFSET
typedef class ha_connect *PHC;
#include "global.h"
#include "plgdbsem.h"
#include "xobject.h"
#include "connect.h"
#include "tabcol.h"
#include "catalog.h"
#include "ha_connect.h"
#include "mycat.h"
#define my_strupr(p) my_caseup_str(default_charset_info, (p));
#define my_strlwr(p) my_casedn_str(default_charset_info, (p));
#define my_stricmp(a, b) my_strcasecmp(default_charset_info, (a), (b))
/***********************************************************************/
/* DB static variables. */
/***********************************************************************/
extern int xtrace;
#if defined(WIN32)
typedef unsigned __int64 ulonglong;
#else
typedef unsigned long long ulonglong;
#endif
/***********************************************************************/
/* Routines called internally by semantic routines. */
/***********************************************************************/
void CntEndDB(PGLOBAL);
RCODE EvalColumns(PGLOBAL g, PTDB tdbp);
/***********************************************************************/
/* MySQL routines called externally by semantic routines. */
/***********************************************************************/
int rename_file_ext(const char *from, const char *to,const char *ext);
/***********************************************************************/
/* CntExit: CONNECT termination routine. */
/***********************************************************************/
PGLOBAL CntExit(PGLOBAL g)
{
if (g) {
PDBUSER dup= PlgGetUser(g);
CntEndDB(g);
PlugExit(g);
if (dup->Catalog) {
delete dup->Catalog;
dup->Catalog= NULL;
} // endif
free(dup);
g= NULL;
} // endif g
return g;
} // end of CntExit
/***********************************************************************/
/* CntEndDB: DB termination semantic routine. */
/***********************************************************************/
void CntEndDB(PGLOBAL g)
{
PDBUSER dbuserp= PlgGetUser(g);
if (dbuserp) {
if (dbuserp->Catalog) {
delete dbuserp->Catalog;
dbuserp->Catalog= NULL;
} // endif Catalog
*dbuserp->Name= '\0';
// *dbuserp->Work= '\0';
} // endif dbuserp
} // end of CntEndDB
/***********************************************************************/
/* CntCheckDB: Initialize a DB application session. */
/* Note: because MySQL does not call a storage handler when a user */
/* executes a use db command, a check must be done before an SQL */
/* command is executed to check whether we are still working on the */
/* current database, and if not to load the newly used database. */
/***********************************************************************/
bool CntCheckDB(PGLOBAL g, PHC handler, const char *pathname)
{
bool rc= false;
PDBUSER dbuserp= PlgGetUser(g);
if (xtrace) {
printf("CntCheckDB: dbuserp=%p\n", dbuserp);
} // endif xtrace
if (!dbuserp || !handler)
return true;
if (xtrace)
printf("cat=%p oldhandler=%p newhandler=%p\n", dbuserp->Catalog,
(dbuserp->Catalog) ? ((MYCAT*)dbuserp->Catalog)->GetHandler() : NULL,
handler);
if (dbuserp->Catalog) {
// ((MYCAT *)dbuserp->Catalog)->SetHandler(handler); done later
((MYCAT *)dbuserp->Catalog)->SetDataPath(g, pathname);
return false; // Nothing else to do
} // endif Catalog
// Copy new database name in dbuser block
strncpy(dbuserp->Name, "???", sizeof(dbuserp->Name) - 1);
dbuserp->Vtdbno= 0; // Init of TDB numbers
/*********************************************************************/
/* Now allocate and initialize the Database Catalog. */
/*********************************************************************/
dbuserp->Step= MSG(READY);
if (!(dbuserp->Catalog= new MYCAT(handler)))
return true;
((MYCAT *)dbuserp->Catalog)->SetDataPath(g, pathname);
dbuserp->UseTemp= TMP_YES; // Must use temporary file
/*********************************************************************/
/* All is correct. */
/*********************************************************************/
sprintf(g->Message, MSG(DATABASE_LOADED), "???");
if (xtrace)
printf("msg=%s\n", g->Message);
return rc;
} // end of CntCheckDB
/***********************************************************************/
/* CntInfo: Get table info. */
/* Returns valid: true if this is a table info. */
/***********************************************************************/
bool CntInfo(PGLOBAL g, PTDB tp, PXF info)
{
bool b;
PTDBDOS tdbp= (PTDBDOS)tp;
if (tdbp) {
b= tdbp->GetFtype() != RECFM_NAF;
info->data_file_length= (b) ? (ulonglong)tdbp->GetFileLength(g) : 0;
info->records= (unsigned)tdbp->GetMaxSize(g);
// info->mean_rec_length= tdbp->GetLrecl();
info->mean_rec_length= 0;
info->data_file_name= (b) ? tdbp->GetFile(g) : NULL;
return true;
} else {
info->data_file_length= 0;
info->records= 0;
info->mean_rec_length= 0;
info->data_file_name= NULL;
return false;
} // endif tdbp
} // end of CntInfo
/***********************************************************************/
/* GetTDB: Get the table description block of a CONNECT table. */
/***********************************************************************/
PTDB CntGetTDB(PGLOBAL g, LPCSTR name, MODE mode, PHC h)
{
int rc;
PTDB tdbp;
PTABLE tabp;
PDBUSER dup= PlgGetUser(g);
PCATLG cat= (dup) ? dup->Catalog : NULL; // Safe over longjmp
if (xtrace)
printf("CntGetTDB: name=%s mode=%d cat=%p\n", name, mode, cat);
if (!cat)
return NULL;
// Save stack and allocation environment and prepare error return
if (g->jump_level == MAX_JUMP) {
strcpy(g->Message, MSG(TOO_MANY_JUMPS));
return NULL;
} // endif jump_level
if ((rc= setjmp(g->jumper[++g->jump_level])) != 0) {
tdbp= NULL;
goto err;
} // endif rc
// Get table object from the catalog
tabp= new(g) XTAB(name);
if (xtrace)
printf("CntGetTDB: tabp=%p\n", tabp);
// Perhaps this should be made thread safe
((MYCAT*)cat)->SetHandler(h);
if (!(tdbp= cat->GetTable(g, tabp, mode)))
printf("CntGetTDB: %s\n", g->Message);
err:
if (xtrace)
printf("Returning tdbp=%p mode=%d\n", tdbp, mode);
g->jump_level--;
return tdbp;
} // end of CntGetTDB
/***********************************************************************/
/* OPENTAB: Open a Table. */
/***********************************************************************/
bool CntOpenTable(PGLOBAL g, PTDB tdbp, MODE mode, char *c1, char *c2,
bool del, PHC h)
{
char *p;
int i, n;
PCOL colp;
PCOLUMN cp;
PDBUSER dup= PlgGetUser(g);
if (xtrace)
printf("CntOpenTable: tdbp=%p mode=%d\n", tdbp, mode);
if (!tdbp) {
strcpy(g->Message, "Null tdbp");
printf("CntOpenTable: %s\n", g->Message);
return true;
} // endif tdbp
if (!c1)
// Allocate all column blocks for that table
tdbp->ColDB(g, NULL, 0);
else for (p= c1; *p; p+= n) {
// Allocate only used column blocks
if (xtrace)
printf("Allocating column %s\n", p);
if (*p == '*') {
// This is a special column
cp= new(g) COLUMN(p + 1);
cp->SetTo_Table(tdbp->GetTable());
colp= ((PTDBASE)tdbp)->InsertSpcBlk(g, cp);
} else
colp= tdbp->ColDB(g, p, 0);
if (!colp) {
sprintf(g->Message, "Column %s not found in %s", p, tdbp->GetName());
return true;
} // endif colp
n= strlen(p) + 1;
} // endfor p
for (i= 0, colp= tdbp->GetColumns(); colp; i++, colp= colp->GetNext()) {
if (colp->InitValue(g))
return true;
if (mode == MODE_INSERT)
if (colp->SetBuffer(g, colp->GetValue(), true, true))
return true;
colp->AddColUse(U_P); // For PLG tables
} // endfor colp
// Now do open the physical table
tdbp->SetMode(mode);
if (del && ((PTDBASE)tdbp)->GetFtype() != RECFM_NAF) {
// To avoid erasing the table when doing a partial delete
// make a fake Next
PDOSDEF ddp= new(g) DOSDEF;
PTDB tp= new(g) TDBDOS(ddp, NULL);
tdbp->SetNext(tp);
dup->Check &= ~CHK_DELETE;
} // endif del
if (xtrace)
printf("About to open the table: tdbp=%p\n", tdbp);
if (mode != MODE_ANY) {
if (tdbp->OpenDB(g)) {
printf("%s\n", g->Message);
return true;
} else
tdbp->SetNext(NULL);
} // endif mode
/*********************************************************************/
/* In Update mode, the updated column blocks must be distinct from */
/* the read column blocks. So make a copy of the TDB and allocate */
/* its column blocks in mode write (required by XML tables). */
/*********************************************************************/
if (mode == MODE_UPDATE) {
PTDBASE utp;
if (!(utp= (PTDBASE)tdbp->Duplicate(g))) {
sprintf(g->Message, MSG(INV_UPDT_TABLE), tdbp->GetName());
return true;
} // endif tp
if (!c2)
// Allocate all column blocks for that table
utp->ColDB(g, NULL, 0);
else for (p= c2; *p; p+= n) {
// Allocate only used column blocks
utp->ColDB(g, p, 0);
n= strlen(p) + 1;
} // endfor p
for (i= 0, colp= utp->GetColumns(); colp; i++, colp= colp->GetNext()) {
if (colp->InitValue(g))
return true;
if (colp->SetBuffer(g, colp->GetValue(), true, true))
return true;
} // endfor colp
// Attach the updated columns list to the main table
((PTDBASE)tdbp)->SetSetCols(utp->GetColumns());
} else if (tdbp && mode == MODE_INSERT)
((PTDBASE)tdbp)->SetSetCols(tdbp->GetColumns());
if (xtrace)
printf("Opening table %s in mode %d tdbp=%p\n",
tdbp->GetName(), mode, tdbp);
return false;
} // end of CntOpenTable
/***********************************************************************/
/* Rewind a table by reopening it. */
/***********************************************************************/
bool CntRewindTable(PGLOBAL g, PTDB tdbp)
{
if (!tdbp)
return true;
tdbp->OpenDB(g);
return false;
} // end of CntRewindTable
/***********************************************************************/
/* Evaluate all columns after a record is read. */
/***********************************************************************/
RCODE EvalColumns(PGLOBAL g, PTDB tdbp)
{
RCODE rc= RC_OK;
PCOL colp;
// Save stack and allocation environment and prepare error return
if (g->jump_level == MAX_JUMP) {
if (xtrace) {
strcpy(g->Message, MSG(TOO_MANY_JUMPS));
printf("EvalColumns: %s\n", g->Message);
} // endif
return RC_FX;
} // endif jump_level
if (setjmp(g->jumper[++g->jump_level]) != 0) {
if (xtrace)
printf("Error reading columns: %s\n", g->Message);
rc= RC_FX;
goto err;
} // endif rc
for (colp= tdbp->GetColumns(); rc == RC_OK && colp;
colp= colp->GetNext()) {
colp->Reset();
// Virtual columns are computed by MariaDB
if (!colp->GetColUse(U_VIRTUAL))
if (colp->Eval(g))
rc= RC_FX;
} // endfor colp
err:
g->jump_level--;
return rc;
} // end of EvalColumns
/***********************************************************************/
/* ReadNext: Read next record sequentially. */
/***********************************************************************/
RCODE CntReadNext(PGLOBAL g, PTDB tdbp)
{
RCODE rc;
if (!tdbp)
return RC_FX;
else if (((PTDBASE)tdbp)->GetKindex()) {
// Reading sequencially an indexed table. This happens after the
// handler function records_in_range was called and MySQL decides
// to quit using the index (!!!) Drop the index.
for (PCOL colp= tdbp->GetColumns(); colp; colp= colp->GetNext())
colp->SetKcol(NULL);
((PTDBASE)tdbp)->SetKindex(NULL);
} // endif index
while ((rc= (RCODE)tdbp->ReadDB(g)) == RC_NF) ;
return (rc != RC_OK) ? rc : EvalColumns(g, tdbp);
} // end of CntReadNext
/***********************************************************************/
/* WriteRow: Insert a new row into a table. */
/***********************************************************************/
RCODE CntWriteRow(PGLOBAL g, PTDB tdbp)
{
RCODE rc;
PCOL colp;
PTDBASE tp= (PTDBASE)tdbp;
if (!tdbp)
return RC_FX;
// Save stack and allocation environment and prepare error return
if (g->jump_level == MAX_JUMP) {
strcpy(g->Message, MSG(TOO_MANY_JUMPS));
return RC_FX;
} // endif jump_level
if (setjmp(g->jumper[++g->jump_level]) != 0) {
printf("%s\n", g->Message);
rc= RC_FX;
goto err;
} // endif rc
// Store column values in table write buffer(s)
for (colp= tp->GetSetCols(); colp; colp= colp->GetNext())
if (!colp->GetColUse(U_VIRTUAL))
colp->WriteColumn(g);
// if (tdbp->GetMode() == MODE_INSERT)
// tbxp->SetModified(true);
// Return result code from write operation
rc= (RCODE)tdbp->WriteDB(g);
err:
g->jump_level--;
return rc;
} // end of CntWriteRow
/***********************************************************************/
/* UpdateRow: Update a row into a table. */
/***********************************************************************/
RCODE CntUpdateRow(PGLOBAL g, PTDB tdbp)
{
if (!tdbp || tdbp->GetMode() != MODE_UPDATE)
return RC_FX;
// Return result code from write operation
return CntWriteRow(g, tdbp);
} // end of CntUpdateRow
/***********************************************************************/
/* DeleteRow: Delete a row from a table. */
/***********************************************************************/
RCODE CntDeleteRow(PGLOBAL g, PTDB tdbp, bool all)
{
RCODE rc;
if (!tdbp || tdbp->GetMode() != MODE_DELETE)
return RC_FX;
// else
// ((PTDBDOX)tdbp)->SetModified(true);
if (((PTDBASE)tdbp)->GetDef()->Indexable() && all)
((PTDBDOS)tdbp)->Cardinal= 0;
// Return result code from delete operation
// Note: if all, this call will be done when closing the table
rc= (RCODE)tdbp->DeleteDB(g, (all) ? RC_FX : RC_OK);
return rc;
} // end of CntDeleteRow
/***********************************************************************/
/* CLOSETAB: Close a table. */
/***********************************************************************/
int CntCloseTable(PGLOBAL g, PTDB tdbp)
{
int rc= RC_OK;
TDBDOX *tbxp= NULL;
if (!tdbp)
return rc; // Already done
if (xtrace)
printf("CntCloseTable: tdbp=%p mode=%d\n", tdbp, tdbp->GetMode());
/*********************************************************************/
/* This will close the table file(s) and also finalize write */
/* operations such as Insert, Update, or Delete. */
/*********************************************************************/
if (tdbp->GetMode() == MODE_DELETE)
rc= tdbp->DeleteDB(g, RC_EF); // Specific A.M. delete routine
// Prepare error return
if (g->jump_level == MAX_JUMP) {
strcpy(g->Message, MSG(TOO_MANY_JUMPS));
rc= RC_FX;
goto err;
} // endif
if ((rc = setjmp(g->jumper[++g->jump_level])) != 0) {
g->jump_level--;
goto err;
} // endif
tdbp->CloseDB(g);
g->jump_level--;
if (xtrace > 1)
printf("Table %s closed\n", tdbp->GetName());
//if (!((PTDBDOX)tdbp)->GetModified())
// return 0;
if (tdbp->GetMode() == MODE_READ || tdbp->GetMode() == MODE_ANY)
return 0;
if (xtrace > 1)
printf("About to reset opt\n");
// Make all the eventual indexes
tbxp= (TDBDOX*)tdbp;
tbxp->SetKindex(NULL);
tbxp->To_Key_Col= NULL;
rc= tbxp->ResetTableOpt(g, ((PTDBASE)tdbp)->GetDef()->Indexable());
err:
if (xtrace > 1)
printf("Done rc=%d\n", rc);
return (rc == RC_OK || rc == RC_INFO) ? 0 : rc;
} // end of CntCloseTable
/***********************************************************************/
/* Load and initialize the use of an index. */
/* This is the condition(s) for doing indexing. */
/* Note: FIX table are not reset here to Nrec= 1. */
/***********************************************************************/
int CntIndexInit(PGLOBAL g, PTDB ptdb, int id)
{
int k;
PCOL colp;
PVAL valp;
PKXBASE xp;
PXLOAD pxp;
PIXDEF xdp;
XKPDEF *kdp;
PTDBDOX tdbp;
PCOLDEF cdp;
DOXDEF *dfp;
if (!ptdb)
return -1;
else if (!((PTDBASE)ptdb)->GetDef()->Indexable()) {
sprintf(g->Message, "Table %s is not indexable", ptdb->GetName());
return 0;
} else
tdbp= (PTDBDOX)ptdb;
dfp= (DOXDEF*)tdbp->To_Def;
//if (!(k= colp->GetKey()))
// if (colp->GetOpt() >= 2) {
// strcpy(g->Message, "Not a valid indexed column");
// return -1;
// } else
// This is a pseudo indexed sorted block optimized column
// return 0;
if (tdbp->To_Kindex)
if (((XXBASE*)tdbp->To_Kindex)->GetID() == id) {
tdbp->To_Kindex->Reset(); // Same index
return (tdbp->To_Kindex->IsMul()) ? 2 : 1;
} else {
tdbp->To_Kindex->Close();
tdbp->To_Kindex= NULL;
} // endif colp
for (xdp= dfp->To_Indx; xdp; xdp= xdp->GetNext())
if (xdp->GetID() == id)
break;
if (!xdp) {
sprintf(g->Message, "Wrong index ID %d", id);
return 0;
} // endif xdp
// Allocate the key columns definition block
tdbp->Knum= xdp->GetNparts();
tdbp->To_Key_Col= (PCOL*)PlugSubAlloc(g, NULL, tdbp->Knum * sizeof(PCOL));
// Get the key column description list
for (k= 0, kdp= (XKPDEF*)xdp->GetToKeyParts(); kdp; kdp= (XKPDEF*)kdp->Next)
if (!(colp= tdbp->ColDB(g, kdp->Name, 0)) || colp->InitValue(g)) {
sprintf(g->Message, "Wrong column %s", kdp->Name);
return 0;
} else
tdbp->To_Key_Col[k++]= colp;
#if defined(_DEBUG)
if (k != tdbp->Knum) {
sprintf(g->Message, "Key part number mismatch for %s",
xdp->GetName());
return 0;
} // endif k
#endif // _DEBUG
// Allocate the pseudo constants that will contain the key values
tdbp->To_Link= (PXOB*)PlugSubAlloc(g, NULL, tdbp->Knum * sizeof(PXOB));
for (k= 0, kdp= (XKPDEF*)xdp->GetToKeyParts();
kdp; k++, kdp= (XKPDEF*)kdp->Next) {
cdp= tdbp->Key(k)->GetCdp();
valp= AllocateValue(g, cdp->GetType(), cdp->GetLength());
tdbp->To_Link[k]= new(g) CONSTANT(valp);
//if (kdp->Klen && tdbp->To_Link[k]->GetResultType() == TYPE_STRING)
// ((XCOLBLK*)tdbp->To_Link[k])->SetLength(kdp->Klen);
//((PCOL)tdbp->To_Link[k])->InitValue(g);
} // endfor k
// Make the index on xdp
if (!xdp->IsAuto()) {
if (dfp->Huge)
pxp= new(g) XHUGE;
else
pxp= new(g) XFILE;
if (tdbp->Knum == 1) // Single index
xp= new(g) XINDXS(tdbp, xdp, pxp, tdbp->To_Key_Col, tdbp->To_Link);
else // Multi-Column index
xp= new(g) XINDEX(tdbp, xdp, pxp, tdbp->To_Key_Col, tdbp->To_Link);
} else // Column contains same values as ROWID
xp= new(g) XXROW(tdbp);
if (xp->Init(g))
return 0;
tdbp->To_Kindex= xp;
return (xp->IsMul()) ? 2 : 1;
} // end of CntIndexInit
/***********************************************************************/
/* IndexRead: fetch a record having the index value. */
/***********************************************************************/
RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op,
const void *key, int len)
{
char *kp= (char*)key;
int n;
short lg;
RCODE rc;
PVAL valp;
PCOL colp;
XXBASE *xbp;
PTDBDOX tdbp;
if (!ptdb)
return RC_FX;
if (!((PTDBASE)ptdb)->GetDef()->Indexable()) {
sprintf(g->Message, "Table %s is not indexable", ptdb->GetName());
return RC_FX;
} else
tdbp= (PTDBDOX)ptdb;
// Set reference values and index operator
if (!tdbp->To_Link || !tdbp->To_Kindex) {
sprintf(g->Message, "Index not initialized for table %s", tdbp->Name);
return RC_FX;
} else
xbp= (XXBASE*)tdbp->To_Kindex;
if (key) {
for (n= 0; n < tdbp->Knum; n++) {
colp= (PCOL)tdbp->To_Key_Col[n];
if (colp->GetColUse(U_NULLS))
kp++; // Skip null byte
valp= tdbp->To_Link[n]->GetValue();
if (!valp->IsTypeNum()) {
if (colp->GetColUse(U_VAR)) {
lg= *(short*)kp;
kp+= sizeof(short);
valp->SetValue_char(kp, (int)lg);
} else
valp->SetValue_char(kp, valp->GetClen());
} else
valp->SetBinValue((void*)kp);
kp+= valp->GetClen();
if (len == kp - (char*)key) {
n++;
break;
} else if (len < kp - (char*)key) {
strcpy(g->Message, "Key buffer is too small");
return RC_FX;
} // endif len
} // endfor n
xbp->SetNval(n);
} // endif key
xbp->SetOp(op);
xbp->SetNth(0);
if ((rc= (RCODE)tdbp->ReadDB(g)) == RC_OK)
rc= EvalColumns(g, tdbp);
return rc;
} // end of CntIndexRead
/***********************************************************************/
/* Return the number of rows matching given values. */
/***********************************************************************/
int CntIndexRange(PGLOBAL g, PTDB ptdb, const uchar* *key, uint *len,
bool *incl, key_part_map *kmap)
{
const uchar *p, *kp;
int i, n, k[2];
short lg;
bool b;
PVAL valp;
PCOL colp;
PTDBDOX tdbp;
XXBASE *xbp;
if (!ptdb)
return -1;
else if (!((PTDBASE)ptdb)->GetDef()->Indexable()) {
sprintf(g->Message, "Table %s is not indexable", ptdb->GetName());
DBUG_PRINT("Range", (g->Message));
return -1;
} else
tdbp= (PTDBDOX)ptdb;
if (!tdbp->To_Link || !tdbp->To_Kindex) {
sprintf(g->Message, "Index not initialized for table %s", tdbp->Name);
DBUG_PRINT("Range", (g->Message));
return -1;
} else
xbp= (XXBASE*)tdbp->To_Kindex;
for (b= false, i= 0; i < 2; i++) {
p= kp= key[i];
if (kp) {
for (n= 0; n < tdbp->Knum; n++) {
if (kmap[i] & (key_part_map)(1 << n)) {
if (b == true)
// Cannot do indexing with missing intermediate key
return -1;
colp= (PCOL)tdbp->To_Key_Col[n];
if (colp->GetColUse(U_NULLS))
p++; // Skip null byte ???
valp= tdbp->To_Link[n]->GetValue();
if (!valp->IsTypeNum()) {
if (colp->GetColUse(U_VAR)) {
lg= *(short*)p;
p+= sizeof(short);
valp->SetValue_char((char*)p, (int)lg);
} else
valp->SetValue_char((char*)p, valp->GetClen());
} else
valp->SetBinValue((void*)p);
if (xtrace) {
char bf[32];
printf("i=%d n=%d key=%s\n", i, n, valp->GetCharString(bf));
} // endif xtrace
p+= valp->GetClen();
if (len[i] == p - kp) {
n++;
break;
} else if (len[i] < (unsigned)(p - kp)) {
strcpy(g->Message, "Key buffer is too small");
return -1;
} // endif len
} else
b= true;
} // endfor n
xbp->SetNval(n);
if (xtrace)
printf("xbp=%p Nval=%d i=%d incl=%d\n", xbp, n, i, incl[i]);
k[i]= xbp->Range(g, i + 1, incl[i]);
} else
k[i]= (i) ? xbp->GetNum_K() : 0;
} // endfor i
if (xtrace)
printf("k1=%d k0=%d\n", k[1], k[0]);
return k[1] - k[0];
} // end of CntIndexRange

77
storage/connect/connect.h Normal file
View File

@@ -0,0 +1,77 @@
/* Copyright (C) Olivier Bertrand 2004 - 2011
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/**************** Cnt H Declares Source Code File (.H) *****************/
/* Name: CONNECT.H Version 2.4 */
/* This file contains the some based classes declares. */
/***********************************************************************/
//#include "xtable.h" // Base class declares
#include "filamtxt.h"
#include "tabdos.h"
//typedef struct _tabdesc *PTABD; // For friend setting
typedef struct _xinfo *PXF;
typedef struct _create_xinfo *PCXF;
typedef class TDBDOX *PTDBDOX;
/***********************************************************************/
/* Definition of classes XCOLCRT, XIXDEF, XKPDEF, DOXDEF, TDBDOX */
/* These classes purpose is chiefly to access protected items! */
/***********************************************************************/
class XCOLCRT: public COLCRT {
friend class ha_connect;
friend bool CntCreateTable(PGLOBAL, char *, PCXF);
public:
XCOLCRT(PSZ name) : COLCRT(name) {Nulls= -1;} // Constructor
bool HasNulls(void) {return (Nulls != 0);}
private:
int Nulls;
}; // end of class XCOLCRT
class DOXDEF: public DOSDEF {
//friend class TDBDOX;
//friend int MakeIndex(PGLOBAL, PTDB, PIXDEF);
friend int CntIndexInit(PGLOBAL, PTDB, int);
}; // end of class DOXDEF
/***********************************************************************/
/* This is the DOS/UNIX Access Method base class declaration. */
/***********************************************************************/
class TDBDOX: public TDBDOS {
friend int MakeIndex(PGLOBAL, PTDB, PIXDEF);
friend int CntCloseTable(PGLOBAL, PTDB);
friend int CntIndexInit(PGLOBAL, PTDB, int);
friend RCODE CntIndexRead(PGLOBAL, PTDB, OPVAL, const void*, int);
friend RCODE CntDeleteRow(PGLOBAL, PTDB, bool);
friend int CntIndexRange(PGLOBAL, PTDB, const uchar**, uint*,
bool*, key_part_map*);
friend class ha_connect;
}; // end of class TDBDOX
class XKPDEF: public KPARTDEF {
friend class TDBDOX;
friend class ha_connect;
//friend int CntMakeIndex(PGLOBAL, const char *, PIXDEF);
friend int CntIndexInit(PGLOBAL, PTDB, int);
public:
XKPDEF(const char *name, int n) : KPARTDEF((PSZ)name, n) {HasNulls= false;}
void SetNulls(bool b) {HasNulls= b;}
protected:
bool HasNulls; /* Can have null values */
}; // end of class XKPDEF
RCODE CheckRecord(PGLOBAL g, PTDB tdbp, char *oldbuf, char *newbuf);

962
storage/connect/csort.cpp Normal file
View File

@@ -0,0 +1,962 @@
/*************** CSort C Program Source Code File (.CPP) ***************/
/* PROGRAM NAME: CSORT */
/* ------------- */
/* Version 2.2 */
/* */
/* COPYRIGHT: */
/* ---------- */
/* (C) Copyright to the author Olivier Bertrand 1995-2012 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
/* This program is the C++ sorting routines that use qsort/insert */
/* algorithm and produces an offset/break table while sorting. */
/* */
/* WHAT YOU NEED TO COMPILE THIS PROGRAM: */
/* -------------------------------------- */
/* */
/* REQUIRED FILES: */
/* --------------- */
/* csort.cpp - Source code */
/* */
/* REQUIRED LIBRARIES: */
/* ------------------- */
/* OS2DEF.LIB - OS2 libray definition subset. */
/* */
/* REQUIRED PROGRAMS: */
/* ------------------ */
/* Microsoft C++ Compiler */
/* or GNU Compiler/Linker */
/* or BORLAND 4.5 C++ compiler */
/* */
/* NOTE */
/* ---- */
/* These functions are not 64-bits ready. */
/* */
/***********************************************************************/
/***********************************************************************/
/* Include relevant MariaDB header file. */
/***********************************************************************/
#include "my_global.h"
/***********************************************************************/
/* Include application header files */
/***********************************************************************/
#include <stdlib.h> /* C standard library */
#include <string.h> /* String manipulation declares */
#include <stdio.h> /* Required for sprintf declare */
#if defined(_DEBUG)
#include <assert.h> /* Assertion routine declares */
#endif
/***********************************************************************/
/* Include CSort class header file */
/***********************************************************************/
#include "global.h"
#include "plgdbsem.h" /* For MBLOCK type definition */
#include "csort.h" /* CSort class definition */
#if !defined(BIGSORT)
#define BIGSORT 200000
#endif // !BIGSORT
/***********************************************************************/
/* DB static external variables. */
/***********************************************************************/
extern MBLOCK Nmblk; /* Used to initialize MBLOCK's */
/***********************************************************************/
/* Initialize the CSORT static members. */
/***********************************************************************/
int CSORT::Limit = 0;
double CSORT::Lg2 = log(2.0);
size_t CSORT::Cpn[1000] = {0}; /* Precalculated cmpnum values */
/***********************************************************************/
/* CSORT constructor. */
/***********************************************************************/
CSORT::CSORT(bool cns, int th, int mth)
: Pex((int*&)Index.Memp), Pof((int*&)Offset.Memp)
{
G = NULL;
Dup =NULL;
Cons = cns;
Thresh = th;
Mthresh = mth;
Nitem = 0;
Index = Nmblk;
Offset = Nmblk;
Swix = NULL;
Savmax = 0;
Savcur = 0;
Savstep = NULL;
} // end of CSORT constructor
/***********************************************************************/
/* CSORT intialization. */
/***********************************************************************/
int CSORT::Qsort(PGLOBAL g, int nb)
{
int rc;
#if defined(_DEBUG)
assert(Index.Size >= nb * sizeof(int));
#endif
if (nb > BIGSORT) {
G = g;
Dup = (PDBUSER)g->Activityp->Aptr;
if (Dup->Proginfo) {
Savstep = Dup->Step;
Savmax = Dup->ProgMax;
Savcur = Dup->ProgCur;
// Evaluate the number of comparisons that we will do
Dup->ProgMax = Cmpnum(nb);
Dup->ProgCur = 0;
Dup->Step = (char*)PlugSubAlloc(g, NULL, 32);
sprintf((char*)Dup->Step, MSG(SORTING_VAL), nb);
} else
Dup = NULL;
} else
Dup = NULL;
Nitem = nb;
for (int n = 0; n < Nitem; n++)
Pex[n] = n;
rc = (Cons) ? Qsortc() : Qsortx();
if (Dup) {
// Restore any change in progress info settings
// printf("Progcur=%u\n", Dup->ProgCur);
Dup->Step = Savstep;
Dup->ProgMax = Savmax;
Dup->ProgCur = Savcur;
} // endif Subcor
return rc;
} // end of QSort
#if defined(DEBTRACE)
/***********************************************************************/
/* Debug routine to be used by sort for specific data (dummy as now) */
/***********************************************************************/
void CSORT::DebugSort(int ph, int n, int *base, int *mid, int *tmp)
{
htrc("phase=%d n=%d base=%p mid=%p tmp=%p\n",
ph, n, base, mid, tmp);
} // end of DebugSort
#endif
/***********************************************************************/
/* Qsortx: Version adapted from qsortx.c by O.Bertrand */
/* This version is specialy adapted for Index sorting, meaning that */
/* the data is not moved, but the Index only is sorted. */
/* Index array elements are any 4-byte word (a pointer or a int int */
/* array index), they are not interpreted except by the user provided */
/* comparison routine which must works accordingly. */
/* In addition, this program takes care of data in which there is a */
/* high rate of repetitions. */
/* CAUTION: the sort algorithm used here is not conservative. Equal */
/* values will be internally stored in unpredictable order. */
/* The THRESHold below is the insertion sort threshold, and also the */
/* threshold for continuing que quicksort partitioning. */
/* The MTHREShold is where we stop finding a better median. */
/* These two quantities should be adjusted dynamically depending upon */
/* the repetition rate of the data. */
/* Algorithm used: */
/* First, set up some global parameters for Qstx to share. Then, */
/* quicksort with Qstx(), and then a cleanup insertion sort ourselves. */
/* Sound simple? It's not... */
/***********************************************************************/
int CSORT::Qsortx(void)
{
register int c;
register int lo, hi, min;
register int i, j, rc = 0;
// To do: rc should be checked for being used uninitialized
int *top;
#ifdef DEBTRACE
int ncp;
num_comp = 0;
#endif
/*********************************************************************/
/* Prepare the Offset array that will be updated during sorts. */
/*********************************************************************/
if (Pof)
for (Pof[Nitem] = Nitem, j = 0; j < Nitem; j++)
Pof[j] = 0;
else
j = Nitem + 1;
/*********************************************************************/
/* Sort on one or zero element is obvious. */
/*********************************************************************/
if (Nitem <= 1)
return Nitem;
/*********************************************************************/
/* Thresh seems to be good as (10 * n / rep). But for testing we */
/* set it directly as one parameter of the Xset function call. */
/* Note: this should be final as the rep parameter is no more used. */
/*********************************************************************/
top = Pex + Nitem;
#ifdef DEBTRACE
htrc("Qsortx: nitem=%d thresh=%d mthresh=%d\n",
Nitem, Thresh, Mthresh);
#endif
/*********************************************************************/
/* If applicable, do a rough preliminary quick sort. */
/*********************************************************************/
if (Nitem >= Thresh)
Qstx(Pex, top);
#ifdef DEBTRACE
htrc(" after quick sort num_comp=%d\n", num_comp);
ncp = num_comp;
num_comp = 0;
#ifdef DEBUG2
DebugSort((Pof) ? 1 : 4, Nitem, Pex, NULL, NULL);
#endif
#endif
if (Thresh > 2) {
if (Pof)
/*****************************************************************/
/* The preliminary search for the smallest element has been */
/* removed so with no sentinel in place, we must check for x */
/* going below the Pof pointer. For each remaining element */
/* group from [1] to [n-1], set hi to the index of the element */
/* AFTER which this one goes. Then, do the standard insertion */
/* sort shift on an integer at a time basis for each equal */
/* element group in the frob. */
/*****************************************************************/
for (min = hi = 0; min < Nitem; min = hi) {
if (Pof[hi]) {
hi += Pof[hi];
continue;
} // endif Pof
Pof[min] = 1;
#ifdef DEBUG2
htrc("insert from min=%d\n", min);
#endif
for (lo = hi; !Pof[++hi]; lo = hi) {
while (lo >= min && (rc = Qcompare(Pex + lo, Pex + hi)) > 0)
if (Pof[lo] > 0)
lo -= Pof[lo];
else
return -2;
if (++lo != hi) {
c = Pex[hi];
for (i = j = hi; i > 0; i = j)
if (Pof[i - 1] <= 0)
return -3;
else if ((j -= Pof[i - 1]) >= lo) {
Pex[i] = Pex[j];
Pof[j + 1] = Pof[i] = Pof[j];
} else
break;
Pex[i] = c;
} // endif lo
if (rc)
Pof[lo] = 1;
else {
i = lo - Pof[lo - 1];
Pof[lo] = ++Pof[i];
} // endelse
#ifdef DEBUG2
htrc("rc=%d lo=%d hi=%d trx=%d\n", rc, lo, hi, Pof[lo]);
#endif
} // endfor hi
} // endfor min
else
/*****************************************************************/
/* Call conservative insertion sort not using/setting offset. */
/*****************************************************************/
Istc(Pex, Pex + min(Nitem, Thresh), top);
} // endif Thresh
#ifdef DEBTRACE
htrc(" after insert sort num_comp=%d\n", num_comp);
num_comp += ncp;
#endif
if (Pof)
/*******************************************************************/
/* Reduce the Offset array. */
/*******************************************************************/
for (i = j = 0; i <= Nitem; j++, i += c) {
#ifdef DEBUG2
htrc(" trxp(%d)=%d trxp(%d)=%d c=%d\n",
i, Pof[i], j, Pof[j], c);
#endif
if ((c = Pof[i]))
Pof[j] = i;
else
return -4;
} // endfor i
return (j - 1);
} // end of Qsortx
/***********************************************************************/
/* Qstx: Do a quicksort on index elements (just one int int). */
/* First, find the median element, and put that one in the first place */
/* as the discriminator. (This "median" is just the median of the */
/* first, last and middle elements). (Using this median instead of */
/* the first element is a big win). Then, the usual partitioning/ */
/* swapping, followed by moving the discriminator into the right place.*/
/* Element equal to the discriminator are placed against it, so the */
/* mid (discriminator) block grows when equal elements exist. This is */
/* a huge win in case of repartitions with few different elements. */
/* The mid block being at its final position, its first and last */
/* elements are marked in the offset list (used to make break list). */
/* Then, figure out the sizes of the two partitions, do the smaller */
/* one recursively and the larger one via a repeat of this code. */
/* Stopping when there are less than THRESH elements in a partition */
/* and cleaning up with an insertion sort (in our caller) is a huge */
/* win(?). All data swaps are done in-line, which is space-losing but */
/* time-saving. (And there are only three places where this is done). */
/***********************************************************************/
void CSORT::Qstx(int *base, int *max)
{
register int *i, *j, *jj, *mid, *him, c;
int *tmp;
int lo, hi, rc;
size_t zlo, zhi, cnm;
zlo = zhi = cnm = 0; // Avoid warning message
lo = max - base; // Number of elements as longs
if (Dup)
cnm = Cmpnum(lo);
do {
/*******************************************************************/
/* At the top here, lo is the number of integers of elements in */
/* the current partition. (Which should be max - base). */
/* Find the median of the first, last, and middle element and make */
/* that the middle element. Set j to largest of first and middle. */
/* If max is larger than that guy, then it's that guy, else */
/* compare max with loser of first and take larger. Things are */
/* set up to prefer the middle, then the first in case of ties. */
/* In addition, hi and rc are set to comparison results. So if hi */
/* is null, the two high values are equal and if rc is null, the */
/* two low values are equal. This was used to set which test will */
/* be made by LE and which one by LT (does not apply anymore). */
/*******************************************************************/
him = mid = i = base + (lo >> 1);
hi = rc = 0;
#ifdef DEBTRACE
tmp = max - 1;
htrc("--> block base=%d size=%d\n", base - Pex, lo);
DebugSort(2, 0, base, mid, tmp);
#endif
if (lo >= Mthresh) {
rc = Qcompare((jj = base), i);
j = (rc > 0) ? jj : i;
hi = Qcompare(j, (tmp = max - 1));
if (hi > 0 && rc) {
j = (j == jj) ? i : jj; // switch to first loser
if ((rc = Qcompare(j, tmp)) < 0)
j = tmp;
} // endif
if (j != i) {
c = *i;
*i = *j;
*j = c;
} // endif j
} else if (lo == 2) {
/*****************************************************************/
/* Small group. Do special quicker processing. */
/*****************************************************************/
if ((rc = Qcompare(base, (him = base + 1))) > 0)
c = *base, *base = *him, *him = c;
if (Pof)
Pof[base - Pex] = Pof[him - Pex] = (rc) ? 1 : 2;
break;
} // endif lo
#ifdef DEBTRACE
DebugSort(3, hi, NULL, mid, &rc);
#endif
/*******************************************************************/
/* Semi-standard quicksort partitioning/swapping. Added here is */
/* a test on equality. All values equal to the mid element are */
/* placed under or over it. Mid block can be also moved when it */
/* is necessary because the other partition is full. At the end */
/* of the for loop the mid block is definitely positionned. */
/*******************************************************************/
for (i = base, j = max - 1; ;) {
CONT:
while (i < mid)
if ((rc = Qcompare(i, mid)) < 0)
i++;
else if (!rc) {
c = *i;
*i = *(--mid);
*mid = c;
} else
break;
while (j > him)
if ((rc = Qcompare(him, j)) < 0)
j--;
else if (!rc) {
c = *j;
*j = *(++him);
*him = c;
} else if (i == mid) { // Triple move:
c = *j; // j goes under mid block
*j = *(++him); // val over mid block -> j
*him = *mid++; // and mid block goes one
*i++ = c; // position higher.
} else { // i <-> j
c = *i;
*i++ = *j;
*j-- = c;
goto CONT;
} // endif's
if (i == mid)
break;
else { // Triple move:
c = *i; // i goes over mid block
*i = *(--mid); // val under mid block -> i
*mid = *him--; // and mid block goes one
*j-- = c; // position lower.
} // endelse
} // endfor i
/*******************************************************************/
/* The mid block being placed at its final position we can now set */
/* the offset array values indicating break point and block size. */
/*******************************************************************/
j = mid;
i = him + 1;
if (Pof)
Pof[him - Pex] = Pof[mid - Pex] = i - j;
/*******************************************************************/
/* Look at sizes of the two partitions, do the smaller one first */
/* by recursion, then do the larger one by making sure lo is its */
/* size, base and max are update correctly, and branching back. */
/* But only repeat (recursively or by branching) if the partition */
/* is of at least size THRESH. */
/*******************************************************************/
lo = j - base;
hi = max - i;
if (Dup) { // Update progress information
zlo = Cmpnum(lo);
zhi = Cmpnum(hi);
Dup->ProgCur += cnm - (zlo + zhi);
} // endif Dup
#ifdef DEBTRACE
htrc(" done lo=%d sep=%d hi=%d\n", lo, i - j, hi);
#endif
if (lo <= hi) {
if (lo >= Thresh)
Qstx(base, j);
else if (lo == 1 && Pof)
Pof[base - Pex] = 1;
base = i;
lo = hi;
cnm = zhi;
} else {
if (hi >= Thresh)
Qstx(i, max);
else if (hi == 1 && Pof)
Pof[i - Pex] = 1;
max = j;
cnm = zlo;
} // endif
if (lo == 1 && Pof)
Pof[base - Pex] = 1;
} while (lo >= Thresh); // enddo
} // end of Qstx
/***********************************************************************/
/* Qsortc.c: Version adapted from qsort.c by O.Bertrand */
/* This version is specialy adapted for Index sorting, meaning that */
/* the data is not moved, but the Index only is sorted. */
/* Index array elements are any 4-byte word (a pointer or a int int */
/* array index), they are not interpreted except by the user provided */
/* comparison routine which must works accordingly. */
/* In addition, this program takes care of data in which there is a */
/* high rate of repetitions. */
/* NOTE: the sort algorithm used here is conservative. Equal and */
/* greater than values are internally stored in additional work area. */
/* The THRESHold below is the insertion sort threshold, and also the */
/* threshold for continuing que quicksort partitioning. */
/* The MTHREShold is where we stop finding a better median. */
/* These two quantities should be adjusted dynamically depending upon */
/* the repetition rate of the data. */
/* Algorithm used: */
/* First, set up some global parameters for Qstc to share. Then, */
/* quicksort with Qstc(), and then a cleanup insertion sort ourselves.*/
/* Sound simple? It's not... */
/***********************************************************************/
int CSORT::Qsortc(void)
{
register int c;
register int lo, hi, min;
register int i, j, k, m, rc = 0;
// To do: rc should be checked for being used uninitialized
int *max;
#ifdef DEBTRACE
int ncp;
num_comp = 0;
#endif
/*********************************************************************/
/* Prepare the Offset array that will be updated during sorts. */
/*********************************************************************/
if (Pof)
for (Pof[Nitem] = Nitem, j = 0; j < Nitem; j++)
Pof[j] = 0;
else
j = Nitem + 1;
/*********************************************************************/
/* Sort on one or zero element is obvious. */
/*********************************************************************/
if (Nitem <= 1)
return Nitem;
/*********************************************************************/
/* Thresh seems to be good as (10 * n / rep). But for testing we */
/* set it directly as one parameter of the Xset function call. */
/* Note: this should be final as the rep parameter is no more used. */
/*********************************************************************/
max = Pex + Nitem;
#ifdef DEBTRACE
htrc("Qsortc: nitem=%d thresh=%d mthresh=%d\n",
Nitem, Thresh, Mthresh);
#endif
/*********************************************************************/
/* If applicable, do a rough preliminary conservative quick sort. */
/*********************************************************************/
if (Nitem >= Thresh) {
if (!(Swix = (int *)malloc(Nitem * sizeof(int))))
return -1;
Qstc(Pex, max);
free(Swix);
Swix = NULL;
} // endif n
#ifdef DEBTRACE
htrc(" after quick sort num_comp=%d\n", num_comp);
ncp = num_comp;
num_comp = 0;
#ifdef DEBUG2
DebugSort((Pof) ? 1 : 4, Nitem, Pex, NULL, NULL);
#endif
#endif
if (Thresh > 2) {
if (Pof)
/*****************************************************************/
/* The preliminary search for the smallest element has been */
/* removed so with no sentinel in place, we must check for x */
/* going below the Pof pointer. For each remaining element */
/* group from [1] to [n-1], set hi to the index of the element */
/* AFTER which this one goes. Then, do the standard insertion */
/* sort shift on an integer at a time basis for each equal */
/* element group in the frob. */
/*****************************************************************/
for (min = hi = 0; min < Nitem; min = hi) {
if (Pof[hi]) {
hi += Pof[hi];
continue;
} // endif
Pof[min] = 1;
#ifdef DEBUG2
htrc("insert from min=%d\n", min);
#endif
for (lo = hi; !Pof[++hi]; lo = hi) {
while (lo >= min && (rc = Qcompare(Pex + lo, Pex + hi)) > 0)
if (Pof[lo] > 0)
lo -= Pof[lo];
else
return -2;
if (++lo != hi) {
c = Pex[hi];
for (i = j = hi; i > 0; i = j)
if (Pof[i - 1] <= 0)
return -3;
else if ((j -= Pof[i - 1]) >= lo) {
for (k = m = i; --m >= j; k--) // Move intermediate
Pex[k] = Pex[m]; // for conservation.
Pof[j + 1] = Pof[i] = Pof[j];
} else
break;
Pex[i] = c;
} // endif
if (rc)
Pof[lo] = 1;
else {
i = lo - Pof[lo - 1];
Pof[lo] = ++Pof[i];
} // endelse
#ifdef DEBUG2
htrc("rc=%d lo=%d hi=%d ofx=%d\n", rc, lo, hi, Pof[lo]);
#endif
} // endfor hi
} // endfor min
else
/*****************************************************************/
/* Call conservative insertion sort not using/setting offset. */
/*****************************************************************/
Istc(Pex, Pex + min(Nitem, Thresh), max);
} // endif Thresh
#ifdef DEBTRACE
htrc(" after insert sort num_comp=%d\n", num_comp);
num_comp += ncp;
#endif
if (Pof)
/*******************************************************************/
/* Reduce the Offset array. */
/*******************************************************************/
for (i = j = 0; i <= Nitem; j++, i += c) {
#ifdef DEBUG2
htrc(" Pof(%d)=%d Pof(%d)=%d c=%d\n",
i, Pof[i], j, Pof[j], c);
#endif
if ((c = Pof[i]))
Pof[j] = i;
else
return -4;
} // endfor i
return (j - 1);
} // end of Qsortc
/***********************************************************************/
/* Qstc: Do a quicksort on index elements (just one int int). */
/* First, find the median element, and set it as the discriminator. */
/* (This "median" is just the median of the first, last and middle */
/* elements). (Using this median instead of the first element is a */
/* big win). Then, the special partitioning/swapping, where elements */
/* smaller than the discriminator are placed in the sorted block, */
/* elements equal to the discriminator are placed backward from the */
/* top of the work area and elements greater than *j (discriminator) */
/* are placed in the work area from its bottom. Then the elements in */
/* the work area are placed back in the sort area in natural order, */
/* making the sort conservative. Non equal blocks shrink faster when */
/* equal elements exist. This is a huge win in case of repartitions */
/* with few different elements. The mid block being at its final */
/* position, its first and last elements are marked in the offset */
/* list (used to make break list). Then, figure out the sizes of the */
/* two partitions, do the smaller one recursively and the larger one */
/* via a repeat of this code. Stopping when there are less than */
/* THRESH elements in a partition and cleaning up with an insertion */
/* sort (in our caller) is a huge win (yet to be proved?). */
/***********************************************************************/
void CSORT::Qstc(int *base, int *max)
{
register int *i, *j, *jj, *lt, *eq, *gt, *mid;
int c, lo, hi, rc;
size_t zlo, zhi, cnm;
zlo = zhi = cnm = 0; // Avoid warning message
lo = max - base; // Number of elements as longs
if (Dup)
cnm = Cmpnum(lo);
do {
/*******************************************************************/
/* At the top here, lo is the number of integers of elements in */
/* the current partition. (Which should be max - base). Find the */
/* median of the first, last, and middle element and make that */
/* the compare element. Set jj to smallest of middle and last. */
/* If base is smaller or equal than that guy, then it's that guy, */
/* else compare base with loser of first and take smaller. Things */
/* are set up to prefer the top, then the middle in case of ties. */
/*******************************************************************/
i = base + (lo >> 1);
jj = mid = max - 1;
#ifdef DEBTRACE
htrc("--> block base=%d size=%d\n", base - Pex, lo);
DebugSort(2, 0, base, i, mid);
#endif
if (lo >= Mthresh) {
jj = ((rc = Qcompare(i, mid)) < 0) ? i : mid;
if (rc && Qcompare(base, jj) > 0) {
jj = (jj == mid) ? i : mid; // switch to first loser
if (Qcompare(base, jj) < 0)
jj = base;
} // endif
if (jj != mid) {
/***************************************************************/
/* The compare element must be at the top of the block so it */
/* cannot be overwritten while making the partitioning. So */
/* save the last block value which will be compared later. */
/***************************************************************/
c = *mid;
*mid = *jj;
} // endif
} else if (lo == 2) {
/*****************************************************************/
/* Small group. Do special quicker processing. */
/*****************************************************************/
if ((rc = Qcompare(base, (i = base + 1))) > 0)
c = *base, *base = *i, *i = c;
if (Pof)
Pof[base - Pex] = Pof[i - Pex] = (rc) ? 1 : 2;
break;
} // endif lo
#ifdef DEBTRACE
DebugSort(3, lo, NULL, jj, &rc);
#endif
/*******************************************************************/
/* Non-standard quicksort partitioning using additional storage */
/* to store values less than, equal or greater than the middle */
/* element. This uses more memory but provides conservation of */
/* the equal elements order. */
/*******************************************************************/
lt = base;
eq = Swix + lo;
gt = Swix;
if (jj == mid) {
/*****************************************************************/
/* Compare element was last. No problem. */
/*****************************************************************/
for (i = base; i < max; i++)
if ((rc = Qcompare(i, mid)) < 0)
*lt++ = *i;
else if (rc > 0)
*gt++ = *i;
else
*--eq = *i;
} else {
/*****************************************************************/
/* Compare element was not last and was copied to top of block. */
/*****************************************************************/
for (i = base; i < mid; i++)
if ((rc = Qcompare(i, mid)) < 0)
*lt++ = *i;
else if (rc > 0)
*gt++ = *i;
else
*--eq = *i;
/*****************************************************************/
/* Restore saved last value and do the comparison from there. */
/*****************************************************************/
*--i = c;
if ((rc = Qcompare(i, mid)) < 0)
*lt++ = *i;
else if (rc > 0)
*gt++ = *i;
else
*--eq = *i;
} // endif
/*******************************************************************/
/* Now copy the equal and greater values back in the main array in */
/* the same order they have been placed in the work area. */
/*******************************************************************/
for (j = Swix + lo, i = lt; j > eq; )
*i++ = *--j;
for (j = Swix, jj = i; j < gt; )
*i++ = *j++;
/*******************************************************************/
/* The mid block being placed at its final position we can now set */
/* the offset array values indicating break point and block size. */
/*******************************************************************/
if (Pof)
Pof[lt - Pex] = Pof[(jj - 1) - Pex] = jj - lt;
/*******************************************************************/
/* Look at sizes of the two partitions, do the smaller one first */
/* by recursion, then do the larger one by making sure lo is its */
/* size, base and max are update correctly, and branching back. */
/* But only repeat (recursively or by branching) if the partition */
/* is of at least size THRESH. */
/*******************************************************************/
lo = lt - base;
hi = gt - Swix;
if (Dup) { // Update progress information
zlo = Cmpnum(lo);
zhi = Cmpnum(hi);
Dup->ProgCur += cnm - (zlo + zhi);
} // endif Dup
#ifdef DEBTRACE
htrc(" done lo=%d hi=%d\n",
lo, /*Swix + lt - base - eq,*/ hi);
#endif
if (lo <= hi) {
if (lo >= Thresh)
Qstc(base, lt);
else if (lo == 1 && Pof)
Pof[base - Pex] = 1;
base = jj;
lo = hi;
cnm = zhi;
} else {
if (hi >= Thresh)
Qstc(jj, max);
else if (hi == 1 && Pof)
Pof[jj - Pex] = 1;
max = lt;
cnm = zlo;
} // endif
if (lo == 1 && Pof)
Pof[base - Pex] = 1;
} while (lo >= Thresh); // enddo
} // end of Qstc
/***********************************************************************/
/* Conservative insertion sort not using/setting offset array. */
/***********************************************************************/
void CSORT::Istc(int *base, int *hi, int *max)
{
register int c;
register int *lo;
register int *i, *j;
/*********************************************************************/
/* First put smallest element, which must be in the first THRESH, */
/* in the first position as a sentinel. This is done just by */
/* searching the 1st THRESH elements (or the 1st n if n < THRESH) */
/* finding the min, and shifting it into the first position. */
/*********************************************************************/
for (j = lo = base; ++lo < hi; )
if (Qcompare(j, lo) > 0)
j = lo;
if (j != base) { // shift j into place
c = *j;
for (i = j; --j >= base; i = j)
*i = *j;
*base = c;
} // endif j
#ifdef DEBTRACE
htrc("sentinel %d in place, base=%p hi=%p max=%p\n",
c, base, hi, max);
#endif
/*********************************************************************/
/* With our sentinel in place, we now run the following hyper- */
/* fast insertion sort. For each remaining element, lo, from [1] */
/* to [n-1], set hi to the index of the element AFTER which this */
/* one goes. Then, do the standard insertion sort shift for each */
/* element in the frob. */
/*********************************************************************/
for (lo = base; (hi = ++lo) < max;) {
while (Qcompare(--hi, lo) > 0) ;
#ifdef DEBUG2
htrc("after while: hi(%p)=%d lo(%p)=%d\n",
hi, *hi, lo, *lo);
#endif
if (++hi != lo) {
c = *lo;
for (i = j = lo; --j >= hi; i = j)
*i = *j;
*i = c;
} // endif hi
} // endfor lo
} // end of Istc
/* -------------------------- End of CSort --------------------------- */

106
storage/connect/csort.h Normal file
View File

@@ -0,0 +1,106 @@
/*************** Csort H Declares Source Code File (.H) ****************/
/* Name: CSORT.H Version 1.2 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 2000-2012 */
/* */
/* This file contains the CSORT class declares (not 64-bits ready) */
/* */
/* Note on use of this class: This class is meant to be used as a */
/* base class by the calling class. This is because the comparison */
/* routine must belong to both CSORT and the calling class. */
/* This avoids to pass explicitly to it the calling "this" pointer. */
/***********************************************************************/
#if !defined(CSORT_DEFINED)
#define CSORT_DEFINED
#include <math.h> /* Required for log function */
#undef DOMAIN // Was defined in math.h
/***********************************************************************/
/* Constant and external definitions. */
/***********************************************************************/
#define THRESH 4 /* Threshold for insertion (was 4) */
#define MTHRESH 6 /* Threshold for median */
#ifdef DEBTRACE
extern FILE *debug; /* Debug file */
#endif
typedef int* const CPINT;
/***********************************************************************/
/* This is the CSORT base class declaration. */
/***********************************************************************/
class DllExport CSORT {
public:
// Constructor
CSORT(bool cns, int th = THRESH, int mth = MTHRESH);
protected:
// Implementation
/*********************************************************************/
/* qsortx/qstx are NOT conservative but use less storage space. */
/* qsortc/qstc ARE conservative but use more storage space. */
/*********************************************************************/
int Qsortx(void); /* Index quick/insert sort */
void Qstx(int *base, int *max); /* Preliminary quick sort */
int Qsortc(void); /* Conservative q/ins sort */
void Qstc(int *base, int *max); /* Preliminary quick sort */
void Istc(int *base, int *hi, int *max); /* Insertion sort routine */
public:
// Methods
int Qsort(PGLOBAL g, int n); /* Sort calling routine */
//virtual void Print(PGLOBAL g, FILE *f, uint n);
//virtual void Print(PGLOBAL g, char *ps, uint z);
#ifdef DEBTRACE
int GetNcmp(void) {return num_comp;}
#endif
protected:
// Overridable
virtual int Qcompare(int *, int *) = 0; /* Item compare routine */
#ifdef DEBTRACE
virtual void DebugSort(int ph, int n, int *base, int *mid, int *tmp);
#endif
public:
// Utility
static void SetCmpNum(void)
{for (int i = 1; i < 1000; i++) Cpn[i] = Cmpnum(i); Limit = 1000;}
protected:
static size_t Cmpnum(int n)
#if defined(AIX)
{return (n < Limit) ? Cpn[n]
: (size_t)round(1.0 + (double)n * (log2((double)n) - 1.0));}
#else // !AIX
{return (n < Limit) ? Cpn[n]
: (size_t)(1.5 + (double)n * (log((double)n)/Lg2 - 1.0));}
#endif // !AIX
// Members
static int Limit; /* Size of precalculated array */
static size_t Cpn[1000]; /* Precalculated cmpnum values */
static double Lg2; /* Precalculated log(2) value */
PGLOBAL G;
PDBUSER Dup; /* Used for progress info */
bool Cons; /* true for conservative sort */
int Thresh; /* Threshold for using qsort */
int Mthresh; /* Threshold for median find */
int Nitem; /* Number of items to sort */
MBLOCK Index; /* Index allocation block */
MBLOCK Offset; /* Offset allocation block */
CPINT &Pex; /* Reference to sort index */
CPINT &Pof; /* Reference to offset array */
int *Swix; /* Pointer on EQ/GT work area */
int Savmax; /* Saved ProgMax value */
int Savcur; /* Saved ProgCur value */
LPCSTR Savstep; /* Saved progress step */
#ifdef DEBTRACE
int num_comp; /* Number of quick sort calls */
#endif
}; // end of class CSORT
#endif // CSORT_DEFINED

595
storage/connect/domdoc.cpp Normal file
View File

@@ -0,0 +1,595 @@
/******************************************************************/
/* Implementation of XML document processing using MS DOM */
/* Author: Olivier Bertrand 2007 - 2013 */
/******************************************************************/
#include "my_global.h"
#include <stdio.h>
#if defined(WIN32)
//#include <windows.h>
#if defined(MSX2)
#import "msxml2.dll" //Does not exist on Vista
#elif defined(MSX3)
#import "msxml3.dll" //Causes error C2872: DOMNodeType: ambiguous symbol ??
#else // MSX4
#import "msxml4.dll" //Causes error C2872: DOMNodeType: ambiguous symbol
#endif // MSX
using namespace MSXML2;
#else
#error This is a Windows implementation only
#endif
#define NODE_TYPE_LIST
#include "global.h"
#include "plgdbsem.h"
#include "xobject.h"
#include "domdoc.h"
inline bool TestHr(PGLOBAL g, HRESULT hr)
{
if FAILED(hr) {
sprintf(g->Message, "%s, hr=%d", MSG(COM_ERROR), hr);
return true;
} else
return false;
} // end of TestHr
/******************************************************************/
/* Return a DOMDOC as a XMLDOC. */
/******************************************************************/
PXDOC GetDomDoc(PGLOBAL g, char *nsl, char *nsdf,
char *enc, PFBLOCK fp)
{
return (PXDOC) new(g) DOMDOC(nsl, nsdf, enc, fp);
} // end of GetDomDoc
/***********************************************************************/
/* Close a loaded DOM XML file. */
/***********************************************************************/
void CloseXMLFile(PGLOBAL g, PFBLOCK fp, bool all)
{
PXBLOCK xp = (PXBLOCK)fp;
if (xp && xp->Count > 1 && !all) {
xp->Count--;
} else if (xp && xp->Count > 0) {
try {
xp->Docp->Release();
} catch(_com_error e) {
sprintf(g->Message, "%s %s", MSG(COM_ERROR), e.Description());
} catch(...) {}
CoUninitialize();
xp->Count = 0;
} // endif
} // end of CloseXMLFile
/* ------------------------ class DOMDOC ------------------------ */
/******************************************************************/
/* DOMDOC constructor. */
/******************************************************************/
DOMDOC::DOMDOC(char *nsl, char *nsdf, char *enc, PFBLOCK fp)
: XMLDOCUMENT(nsl, nsdf, enc)
{
assert (!fp || fp->Type == TYPE_FB_XML);
Docp = (fp) ? ((PXBLOCK)fp)->Docp : NULL;
Nlist = NULL;
Hr = 0;
} // end of DOMDOC constructor
/******************************************************************/
/* Initialize XML parser and check library compatibility. */
/******************************************************************/
bool DOMDOC::Initialize(PGLOBAL g)
{
if (TestHr(g, CoInitialize(NULL)))
return true;
if (TestHr(g, Docp.CreateInstance("msxml2.domdocument")))
return true;
return MakeNSlist(g);
} // end of Initialize
/******************************************************************/
/* Parse the XML file and construct node tree in memory. */
/******************************************************************/
bool DOMDOC::ParseFile(char *fn)
{
// Load the document
Docp->async = false;
if (!(bool)Docp->load((_bstr_t)fn))
return true;
return false;
} // end of ParseFile
/******************************************************************/
/* Create or reuse an Xblock for this document. */
/******************************************************************/
PFBLOCK DOMDOC::LinkXblock(PGLOBAL g, MODE m, int rc, char *fn)
{
PDBUSER dup = (PDBUSER)g->Activityp->Aptr;
PXBLOCK xp = (PXBLOCK)PlugSubAlloc(g, NULL, sizeof(XBLOCK));
memset(xp, 0, sizeof(XBLOCK));
xp->Next = (PXBLOCK)dup->Openlist;
dup->Openlist = (PFBLOCK)xp;
xp->Type = TYPE_FB_XML;
xp->Fname = (LPCSTR)PlugSubAlloc(g, NULL, strlen(fn) + 1);
strcpy((char*)xp->Fname, fn);
xp->Count = 1;
xp->Length = (m == MODE_READ) ? 1 : 0;
xp->Docp = Docp;
xp->Retcode = rc;
// Return xp as a fp
return (PFBLOCK)xp;
} // end of LinkXblock
/******************************************************************/
/* Create the XML node. */
/******************************************************************/
bool DOMDOC::NewDoc(PGLOBAL g, char *ver)
{
char buf[64];
MSXML2::IXMLDOMProcessingInstructionPtr pip;
sprintf(buf, "version=\"%s\" encoding=\"%s\"", ver, Encoding);
pip = Docp->createProcessingInstruction("xml", buf);
return(TestHr(g, Docp->appendChild(pip)));
} // end of NewDoc
/******************************************************************/
/* Add a comment to the document node. */
/******************************************************************/
void DOMDOC::AddComment(PGLOBAL g, char *com)
{
TestHr(g, Docp->appendChild(Docp->createComment(com)));
} // end of AddComment
/******************************************************************/
/* Return the node class of the root of the document. */
/******************************************************************/
PXNODE DOMDOC::GetRoot(PGLOBAL g)
{
MSXML2::IXMLDOMElementPtr root = Docp->documentElement;
if (root == NULL)
return NULL;
return new(g) DOMNODE(this, root);
} // end of GetRoot
/******************************************************************/
/* Create a new root element and return its class node. */
/******************************************************************/
PXNODE DOMDOC::NewRoot(PGLOBAL g, char *name)
{
MSXML2::IXMLDOMElementPtr ep = Docp->createElement(name);
if (ep == NULL || TestHr(g, Docp->appendChild(ep)))
return NULL;
return new(g) DOMNODE(this, ep);
} // end of NewRoot
/******************************************************************/
/* Return a void DOMNODE node class. */
/******************************************************************/
PXNODE DOMDOC::NewPnode(PGLOBAL g, char *name)
{
MSXML2::IXMLDOMElementPtr root = NULL;
if (name)
if ((root = Docp->createElement(name)) == NULL)
return NULL;
return new(g) DOMNODE(this, root);
} // end of NewPnode
/******************************************************************/
/* Return a void DOMATTR node class. */
/******************************************************************/
PXATTR DOMDOC::NewPattr(PGLOBAL g)
{
return new(g) DOMATTR(this, NULL);
} // end of NewPattr
/******************************************************************/
/* Return a void DOMATTR node class. */
/******************************************************************/
PXLIST DOMDOC::NewPlist(PGLOBAL g)
{
return new(g) DOMNODELIST(this, NULL);
} // end of NewPlist
/******************************************************************/
/* Dump the node tree to a new XML file. */
/******************************************************************/
int DOMDOC::DumpDoc(PGLOBAL g, char *ofn)
{
if (TestHr(g, Docp->save(ofn)))
return -1;
return 0;
} // end of Dump
/******************************************************************/
/* Free the document, cleanup the XML library, and */
/* debug memory for regression tests. */
/******************************************************************/
void DOMDOC::CloseDoc(PGLOBAL g, PFBLOCK xp)
{
CloseXMLFile(g, xp, false);
} // end of Close
/* ----------------------- class DOMNODE ------------------------ */
/******************************************************************/
/* DOMNODE constructor. */
/******************************************************************/
DOMNODE::DOMNODE(PXDOC dp, MSXML2::IXMLDOMNodePtr np) : XMLNODE(dp)
{
Docp = ((PDOMDOC)dp)->Docp;
Nodep = np;
Ws = NULL;
Len = 0;
} // end of DOMNODE constructor
/******************************************************************/
/* Return the node name. */
/******************************************************************/
char *DOMNODE::GetName(PGLOBAL g)
{
if (!WideCharToMultiByte(CP_ACP, 0, Nodep->nodeName, -1,
Name, sizeof(Name), NULL, NULL)) {
strcpy(g->Message, MSG(NAME_CONV_ERR));
return NULL;
} // endif
return Name;
} // end of GetName
/******************************************************************/
/* Return the node class of next sibling of the node. */
/******************************************************************/
PXNODE DOMNODE::GetNext(PGLOBAL g)
{
if (Nodep->nextSibling == NULL)
Next = NULL;
else if (!Next)
Next = new(g) DOMNODE(Doc, Nodep->nextSibling);
return Next;
} // end of GetNext
/******************************************************************/
/* Return the node class of first children of the node. */
/******************************************************************/
PXNODE DOMNODE::GetChild(PGLOBAL g)
{
if (Nodep->firstChild == NULL)
Children = NULL;
else if (!Children)
Children = new(g) DOMNODE(Doc, Nodep->firstChild);
return Children;
} // end of GetChild
/******************************************************************/
/* Return the content of a node and subnodes. */
/******************************************************************/
char *DOMNODE::GetText(char *buf, int len)
{
// Nodep can be null for a missing HTML table column
if (Nodep)
strncpy(buf, Nodep->text, len);
else
*buf = '\0';
return buf;
} // end of GetText
/******************************************************************/
/* Set the text content of an attribute. */
/******************************************************************/
bool DOMNODE::SetContent(PGLOBAL g, char *txtp, int len)
{
bool rc;
BSTR val;
if (len > Len || !Ws) {
Ws = (WCHAR*)PlugSubAlloc(g, NULL, (len + 1) * 2);
Len = len;
} // endif len
if (!MultiByteToWideChar(CP_ACP, 0, txtp, strlen(txtp) + 1,
Ws, Len + 1)) {
sprintf(g->Message, MSG(WS_CONV_ERR), txtp);
return true;
} // endif
val = SysAllocString(Ws);
rc = TestHr(g, Nodep->put_text(val));
SysFreeString(val);
return rc;
} // end of SetContent
/******************************************************************/
/* Return a clone of this node. */
/******************************************************************/
PXNODE DOMNODE::Clone(PGLOBAL g, PXNODE np)
{
if (np) {
((PDOMNODE)np)->Nodep = Nodep;
return np;
} else
return new(g) DOMNODE(Doc, Nodep);
} // end of Clone
/******************************************************************/
/* Return the list of all or matching children that are elements.*/
/******************************************************************/
PXLIST DOMNODE::GetChildElements(PGLOBAL g, char *xp, PXLIST lp)
{
MSXML2::IXMLDOMNodeListPtr dnlp;
if (xp) {
if (Nodep->nodeType == MSXML2::NODE_ELEMENT) {
MSXML2::IXMLDOMElementPtr ep = Nodep;
dnlp = ep->getElementsByTagName(xp);
} else
return NULL;
} else
dnlp = Nodep->childNodes;
if (lp) {
((PDOMLIST)lp)->Listp = dnlp;
return lp;
} else
return new(g) DOMNODELIST(Doc, dnlp);
} // end of GetChildElements
/******************************************************************/
/* Return the list of nodes verifying the passed Xapth. */
/******************************************************************/
PXLIST DOMNODE::SelectNodes(PGLOBAL g, char *xp, PXLIST lp)
{
MSXML2::IXMLDOMNodeListPtr dnlp = Nodep->selectNodes(xp);
if (lp) {
((PDOMLIST)lp)->Listp = dnlp;
return lp;
} else
return new(g) DOMNODELIST(Doc, dnlp);
} // end of SelectNodes
/******************************************************************/
/* Return the first node verifying the passed Xapth. */
/******************************************************************/
PXNODE DOMNODE::SelectSingleNode(PGLOBAL g, char *xp, PXNODE np)
{
MSXML2::IXMLDOMNodePtr dnp = Nodep->selectSingleNode(xp);
if (dnp) {
if (np) {
((PDOMNODE)np)->Nodep = dnp;
return np;
} else
return new(g) DOMNODE(Doc, dnp);
} else
return NULL;
} // end of SelectSingleNode
/******************************************************************/
/* Return the node attribute with the specified name. */
/******************************************************************/
PXATTR DOMNODE::GetAttribute(PGLOBAL g, char *name, PXATTR ap)
{
MSXML2::IXMLDOMElementPtr ep = Nodep;
MSXML2::IXMLDOMAttributePtr atp = ep->getAttributeNode(name);
if (atp) {
if (ap) {
((PDOMATTR)ap)->Atrp = atp;
return ap;
} else
return new(g) DOMATTR(Doc, atp);
} else
return NULL;
} // end of GetAttribute
/******************************************************************/
/* Add a new element child node to this node and return it. */
/******************************************************************/
PXNODE DOMNODE::AddChildNode(PGLOBAL g, char *name, PXNODE np)
{
char *p, *pn;
// char *p, *pn, *epf, *pf = NULL;
MSXML2::IXMLDOMNodePtr ep;
// _bstr_t uri((wchar_t*)NULL);
#if 0
// Is a prefix specified ?
if ((p = strchr(name, ':'))) {
pf = BufAlloc(g, name, p - name);
// Is it the pseudo default prefix
if (Doc->DefNs && !strcmp(pf, Doc->DefNs)) {
name = p + 1; // Suppress it from name
pf = NULL; // No real prefix
} // endif DefNs
} // endif p
// Look for matching namespace URI in context
for (ep = Nodep; ep; ep = ep->parentNode) {
epf = (_bstr_t)ep->prefix;
if ((!pf && !epf) || (pf && epf && !strcmp(pf, epf))) {
uri = Nodep->namespaceURI;
break;
} // endif
} // endfor ep
if ((wchar_t*)uri == NULL) {
if (!pf)
pf = Doc->DefNs;
// Look for the namespace URI corresponding to this node
if (pf)
for (PNS nsp = Doc->Namespaces; nsp; nsp = nsp->Next)
if (!strcmp(pf, nsp->Prefix)) {
uri = nsp->Uri;
break;
} // endfor nsp
} // endif pns
#endif // 0
// If name has the format m[n] only m is taken as node name
if ((p = strchr(name, '[')))
pn = BufAlloc(g, name, p - name);
else
pn = name;
// Construct the element node with eventual namespace
// ep = Docp->createNode(_variant_t("Element"), pn, uri);
ep = Docp->createElement(pn);
_bstr_t pfx = ep->prefix;
_bstr_t uri = ep->namespaceURI;
if (ep == NULL || TestHr(g, Nodep->appendChild(ep)))
return NULL;
if (np)
((PDOMNODE)np)->Nodep = ep;
else
np = new(g) DOMNODE(Doc, ep);
return NewChild(np);
} // end of AddChildNode
/******************************************************************/
/* Add a new property to this node and return it. */
/******************************************************************/
PXATTR DOMNODE::AddProperty(PGLOBAL g, char *name, PXATTR ap)
{
MSXML2::IXMLDOMAttributePtr atp = Docp->createAttribute(name);
if (atp) {
MSXML2::IXMLDOMElementPtr ep = Nodep;
ep->setAttributeNode(atp);
if (ap) {
((PDOMATTR)ap)->Atrp = atp;
return ap;
} else
return new(g) DOMATTR(Doc, atp);
} else
return NULL;
} // end of AddProperty
/******************************************************************/
/* Add a new text node to this node. */
/******************************************************************/
void DOMNODE::AddText(PGLOBAL g, char *txtp)
{
MSXML2::IXMLDOMTextPtr tp= Docp->createTextNode((_bstr_t)txtp);
if (tp != NULL)
TestHr(g, Nodep->appendChild(tp));
} // end of AddText
/******************************************************************/
/* Remove a child node from this node. */
/******************************************************************/
void DOMNODE::DeleteChild(PGLOBAL g, PXNODE dnp)
{
TestHr(g, Nodep->removeChild(((PDOMNODE)dnp)->Nodep));
// ((PDOMNODE)dnp)->Nodep->Release(); bad idea, causes a crash
Delete(dnp);
} // end of DeleteChild
/* --------------------- class DOMNODELIST ---------------------- */
/******************************************************************/
/* DOMNODELIST constructor. */
/******************************************************************/
DOMNODELIST::DOMNODELIST(PXDOC dp, MSXML2::IXMLDOMNodeListPtr lp)
: XMLNODELIST(dp)
{
Listp = lp;
} // end of DOMNODELIST constructor
/******************************************************************/
/* Return the nth element of the list. */
/******************************************************************/
PXNODE DOMNODELIST::GetItem(PGLOBAL g, int n, PXNODE np)
{
if (Listp == NULL || Listp->length <= n)
return NULL;
if (np) {
((PDOMNODE)np)->Nodep = Listp->item[n];
return np;
} else
return new(g) DOMNODE(Doc, Listp->item[n]);
} // end of GetItem
/* ----------------------- class DOMATTR ------------------------ */
/******************************************************************/
/* DOMATTR constructor. */
/******************************************************************/
DOMATTR::DOMATTR(PXDOC dp, MSXML2::IXMLDOMAttributePtr ap)
: XMLATTRIBUTE(dp)
{
Atrp = ap;
Ws = NULL;
Len = 0;
} // end of DOMATTR constructor
/******************************************************************/
/* Set the text content of an attribute. */
/******************************************************************/
bool DOMATTR::SetText(PGLOBAL g, char *txtp, int len)
{
bool rc;
BSTR val;
if (len > Len || !Ws) {
Ws = (WCHAR*)PlugSubAlloc(g, NULL, (len + 1) * 2);
Len = len;
} // endif len
if (!MultiByteToWideChar(CP_ACP, 0, txtp, strlen(txtp) + 1,
Ws, Len + 1)) {
sprintf(g->Message, MSG(WS_CONV_ERR), txtp);
return true;
} // endif
val = SysAllocString(Ws);
rc = TestHr(g, Atrp->put_text(val));
SysFreeString(val);
return rc;
} // end of SetText

138
storage/connect/domdoc.h Normal file
View File

@@ -0,0 +1,138 @@
/******************************************************************/
/* Declaration of XML document processing using MS DOM */
/* Author: Olivier Bertrand 2007 - 2012 */
/******************************************************************/
#include "plgxml.h"
typedef class DOMDOC *PDOMDOC;
typedef class DOMNODE *PDOMNODE;
typedef class DOMATTR *PDOMATTR;
typedef class DOMNODELIST *PDOMLIST;
/******************************************************************/
/* XML block. Must have the same layout than FBLOCK up to Type. */
/******************************************************************/
typedef struct _xblock { /* Loaded XML file block */
struct _xblock *Next;
LPCSTR Fname; /* Point on file name */
size_t Length; /* Used to tell if read mode */
short Count; /* Nb of times file is used */
short Type; /* TYPE_FB_XML */
int Retcode; /* Return code from Load */
MSXML2::IXMLDOMDocumentPtr Docp;/* Document interface pointer */
//IXMLDOMNodeListPtr Nlist;
} XBLOCK, *PXBLOCK;
/******************************************************************/
/* Declaration of DOM document. */
/******************************************************************/
class DOMDOC : public XMLDOCUMENT {
friend class DOMNODE;
public:
// Constructor
DOMDOC(char *nsl, char *nsdf, char *enc, PFBLOCK fp);
// Properties
virtual short GetDocType(void) {return TYPE_FB_XML;}
virtual void *GetDocPtr(void) {return Docp;}
// Methods
virtual bool Initialize(PGLOBAL g);
virtual bool ParseFile(char *fn);
virtual bool NewDoc(PGLOBAL g, char *ver);
virtual void AddComment(PGLOBAL g, char *com);
virtual PXNODE GetRoot(PGLOBAL g);
virtual PXNODE NewRoot(PGLOBAL g, char *name);
virtual PXNODE NewPnode(PGLOBAL g, char *name);
virtual PXATTR NewPattr(PGLOBAL g);
virtual PXLIST NewPlist(PGLOBAL g);
virtual int DumpDoc(PGLOBAL g, char *ofn);
virtual void CloseDoc(PGLOBAL g, PFBLOCK xp);
virtual PFBLOCK LinkXblock(PGLOBAL g, MODE m, int rc, char *fn);
protected:
// Members
MSXML2::IXMLDOMDocumentPtr Docp;
MSXML2::IXMLDOMNodeListPtr Nlist;
HRESULT Hr;
}; // end of class DOMDOC
/******************************************************************/
/* Declaration of DOM XML node. */
/******************************************************************/
class DOMNODE : public XMLNODE {
friend class DOMDOC;
friend class DOMNODELIST;
public:
// Properties
virtual char *GetName(PGLOBAL g);
virtual int GetType(void) {return Nodep->nodeType;}
virtual PXNODE GetNext(PGLOBAL g);
virtual PXNODE GetChild(PGLOBAL g);
// Methods
virtual char *GetText(char *buf, int len);
virtual bool SetContent(PGLOBAL g, char *txtp, int len);
virtual PXNODE Clone(PGLOBAL g, PXNODE np);
virtual PXLIST GetChildElements(PGLOBAL g, char *xp, PXLIST lp);
virtual PXLIST SelectNodes(PGLOBAL g, char *xp, PXLIST lp);
virtual PXNODE SelectSingleNode(PGLOBAL g, char *xp, PXNODE np);
virtual PXATTR GetAttribute(PGLOBAL g, char *name, PXATTR ap);
virtual PXNODE AddChildNode(PGLOBAL g, char *name, PXNODE np);
virtual PXATTR AddProperty(PGLOBAL g, char *name, PXATTR ap);
virtual void AddText(PGLOBAL g, char *txtp);
virtual void DeleteChild(PGLOBAL g, PXNODE dnp);
protected:
// Constructor
DOMNODE(PXDOC dp, MSXML2::IXMLDOMNodePtr np);
// Members
MSXML2::IXMLDOMDocumentPtr Docp;
MSXML2::IXMLDOMNodePtr Nodep;
char Name[64];
WCHAR *Ws;
int Len;
}; // end of class DOMNODE
/******************************************************************/
/* Declaration of DOM XML node list. */
/******************************************************************/
class DOMNODELIST : public XMLNODELIST {
friend class DOMDOC;
friend class DOMNODE;
public:
// Methods
virtual int GetLength(void) {return Listp->length;}
virtual PXNODE GetItem(PGLOBAL g, int n, PXNODE np);
protected:
// Constructor
DOMNODELIST(PXDOC dp, MSXML2::IXMLDOMNodeListPtr lp);
// Members
MSXML2::IXMLDOMNodeListPtr Listp;
}; // end of class DOMNODELIST
/******************************************************************/
/* Declaration of DOM XML attribute. */
/******************************************************************/
class DOMATTR : public XMLATTRIBUTE {
friend class DOMDOC;
friend class DOMNODE;
public:
// Properties
//virtual char *GetText(void);
// Methods
virtual bool SetText(PGLOBAL g, char *txtp, int len);
protected:
// Constructor
DOMATTR(PXDOC dp, MSXML2::IXMLDOMAttributePtr ap);
// Members
MSXML2::IXMLDOMAttributePtr Atrp;
WCHAR *Ws;
int Len;
}; // end of class DOMATTR

1013
storage/connect/engmsg.h Normal file

File diff suppressed because it is too large Load Diff

688
storage/connect/filamap.cpp Normal file
View File

@@ -0,0 +1,688 @@
/*********** File AM Map C++ Program Source Code File (.CPP) ***********/
/* PROGRAM NAME: FILAMAP */
/* ------------- */
/* Version 1.4 */
/* */
/* COPYRIGHT: */
/* ---------- */
/* (C) Copyright to the author Olivier BERTRAND 2005-2013 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
/* This program are the MAP file access method classes. */
/* */
/***********************************************************************/
/***********************************************************************/
/* Include relevant sections of the System header files. */
/***********************************************************************/
#include "my_global.h"
#if defined(WIN32)
#if defined(__BORLANDC__)
#define __MFC_COMPAT__ // To define min/max as macro
#endif // __BORLANDC__
//#include <windows.h>
#else // !WIN32
#if defined(UNIX)
#include <errno.h>
#include <unistd.h>
#else // !UNIX
#include <io.h>
#endif // !UNIX
#include <fcntl.h>
#endif // !WIN32
/***********************************************************************/
/* Include application header files: */
/* global.h is header containing all global declarations. */
/* plgdbsem.h is header containing the DB application declarations. */
/* filamtxt.h is header containing the file AM classes declarations. */
/* Note: these files are included inside the include files below. */
/***********************************************************************/
#include "global.h"
#include "plgdbsem.h"
#include "osutil.h"
#include "maputil.h"
#include "filamap.h"
#include "tabdos.h"
bool PushWarning(PGLOBAL, PTDBASE);
/* --------------------------- Class MAPFAM -------------------------- */
/***********************************************************************/
/* Constructors. */
/***********************************************************************/
MAPFAM::MAPFAM(PDOSDEF tdp) : TXTFAM(tdp)
{
Memory = NULL;
Mempos = NULL;
Tpos = NULL;
Fpos = NULL;
Spos = NULL;
Top = NULL;
} // end of MAPFAM standard constructor
MAPFAM::MAPFAM(PMAPFAM tmfp) : TXTFAM(tmfp)
{
Memory = tmfp->Memory;
Mempos = tmfp->Mempos;
Fpos = tmfp->Fpos;
Spos = tmfp->Spos;
Tpos = tmfp->Tpos;
Top = tmfp->Top;
} // end of MAPFAM copy constructor
/***********************************************************************/
/* Reset: reset position values at the beginning of file. */
/***********************************************************************/
void MAPFAM::Reset(void)
{
TXTFAM::Reset();
Fpos = Tpos = Spos = NULL;
} // end of Reset
/***********************************************************************/
/* MAP GetFileLength: returns file size in number of bytes. */
/***********************************************************************/
int MAPFAM::GetFileLength(PGLOBAL g)
{
int len;
len = (To_Fb) ? To_Fb->Length : TXTFAM::GetFileLength(g);
#ifdef DEBTRACE
htrc("Mapped file length=%d\n", len);
#endif
return len;
} // end of GetFileLength
/***********************************************************************/
/* OpenTableFile: Open a DOS/UNIX table file as a mapped file. */
/***********************************************************************/
bool MAPFAM::OpenTableFile(PGLOBAL g)
{
char filename[_MAX_PATH];
int len;
MODE mode = Tdbp->GetMode();
PFBLOCK fp;
PDBUSER dbuserp = (PDBUSER)g->Activityp->Aptr;
#if defined(_DEBUG)
// Insert mode is no more handled using file mapping
assert(mode != MODE_INSERT);
#endif // _DEBUG
/*********************************************************************/
/* We used the file name relative to recorded datapath. */
/*********************************************************************/
PlugSetPath(filename, To_File, Tdbp->GetPath());
/*********************************************************************/
/* Under Win32 the whole file will be mapped so we can use it as */
/* if it were entirely read into virtual memory. */
/* Firstly we check whether this file have been already mapped. */
/*********************************************************************/
if (mode == MODE_READ) {
for (fp = dbuserp->Openlist; fp; fp = fp->Next)
if (fp->Type == TYPE_FB_MAP && !stricmp(fp->Fname, filename)
&& fp->Count && fp->Mode == mode)
break;
#ifdef DEBTRACE
htrc("Mapping file, fp=%p\n", fp);
#endif
} else
fp = NULL;
if (fp) {
/*******************************************************************/
/* File already mapped. Just increment use count and get pointer. */
/*******************************************************************/
fp->Count++;
Memory = fp->Memory;
len = fp->Length;
} else {
/*******************************************************************/
/* If required, delete the whole file if no filtering is implied. */
/*******************************************************************/
bool del;
HANDLE hFile;
MEMMAP mm;
del = mode == MODE_DELETE && !Tdbp->GetNext();
if (del)
DelRows = Cardinality(g);
/*******************************************************************/
/* Create the mapping file object. */
/*******************************************************************/
hFile = CreateFileMap(g, filename, &mm, mode, del);
if (hFile == INVALID_HANDLE_VALUE) {
DWORD rc = GetLastError();
if (!(*g->Message))
sprintf(g->Message, MSG(OPEN_MODE_ERROR),
"map", rc, filename);
#ifdef DEBTRACE
htrc("%s\n", g->Message);
#endif
return (mode == MODE_READ && rc == ENOENT)
? PushWarning(g, Tdbp) : true;
} // endif hFile
/*******************************************************************/
/* Get the file size (assuming file is smaller than 4 GB) */
/*******************************************************************/
len = mm.lenL;
Memory = (char *)mm.memory;
if (!len) { // Empty or deleted file
CloseFileHandle(hFile);
Tdbp->ResetSize();
return false;
} // endif len
if (!Memory) {
CloseFileHandle(hFile);
sprintf(g->Message, MSG(MAP_VIEW_ERROR),
filename, GetLastError());
return true;
} // endif Memory
if (mode != MODE_DELETE) {
CloseFileHandle(hFile); // Not used anymore
hFile = INVALID_HANDLE_VALUE; // For Fblock
} // endif Mode
/*******************************************************************/
/* Link a Fblock. This make possible to reuse already opened maps */
/* and also to automatically unmap them in case of error g->jump. */
/* Note: block can already exist for previously closed file. */
/*******************************************************************/
fp = (PFBLOCK)PlugSubAlloc(g, NULL, sizeof(FBLOCK));
fp->Type = TYPE_FB_MAP;
fp->Fname = (char*)PlugSubAlloc(g, NULL, strlen(filename) + 1);
strcpy((char*)fp->Fname, filename);
fp->Next = dbuserp->Openlist;
dbuserp->Openlist = fp;
fp->Count = 1;
fp->Length = len;
fp->Memory = Memory;
fp->Mode = mode;
fp->File = NULL;
fp->Handle = hFile; // Used for Delete
} // endif fp
To_Fb = fp; // Useful when closing
/*********************************************************************/
/* The pseudo "buffer" is here the entire file mapping view. */
/*********************************************************************/
Fpos = Mempos = Memory;
Top = Memory + len;
#ifdef DEBTRACE
htrc("fp=%p count=%d MapView=%p len=%d Top=%p\n",
fp, fp->Count, Memory, len, Top);
#endif
return AllocateBuffer(g); // Useful for DBF files
} // end of OpenTableFile
/***********************************************************************/
/* GetRowID: return the RowID of last read record. */
/***********************************************************************/
int MAPFAM::GetRowID(void)
{
return Rows;
} // end of GetRowID
/***********************************************************************/
/* GetPos: return the position of last read record. */
/***********************************************************************/
int MAPFAM::GetPos(void)
{
return Fpos - Memory;
} // end of GetPos
/***********************************************************************/
/* GetNextPos: return the position of next record. */
/***********************************************************************/
int MAPFAM::GetNextPos(void)
{
return Mempos - Memory;
} // end of GetNextPos
/***********************************************************************/
/* SetPos: Replace the table at the specified position. */
/***********************************************************************/
bool MAPFAM::SetPos(PGLOBAL g, int pos)
{
Fpos = Mempos = Memory + pos;
if (Mempos >= Top || Mempos < Memory) {
strcpy(g->Message, MSG(INV_MAP_POS));
return true;
} // endif Mempos
Placed = true;
return false;
} // end of SetPos
/***********************************************************************/
/* Record file position in case of UPDATE or DELETE. */
/***********************************************************************/
bool MAPFAM::RecordPos(PGLOBAL g)
{
Fpos = Mempos;
return false;
} // end of RecordPos
/***********************************************************************/
/* Skip one record in file. */
/***********************************************************************/
int MAPFAM::SkipRecord(PGLOBAL g, bool header)
{
PDBUSER dup = (PDBUSER)g->Activityp->Aptr;
// Skip this record
while (*Mempos++ != '\n') ; // What about Unix ???
if (Mempos >= Top)
return RC_EF;
// Update progress information
dup->ProgCur = GetPos();
if (header)
Fpos = Tpos = Spos = Mempos; // For Delete
return RC_OK;
} // end of SkipRecord
/***********************************************************************/
/* ReadBuffer: Read one line for a mapped text file. */
/***********************************************************************/
int MAPFAM::ReadBuffer(PGLOBAL g)
{
int len;
// Are we at the end of the memory
if (Mempos >= Top)
return RC_EF;
if (!Placed) {
/*******************************************************************/
/* Record file position in case of UPDATE or DELETE. */
/*******************************************************************/
Fpos = Mempos;
CurBlk = (int)Rows++;
} else
Placed = false;
// Immediately calculate next position (Used by DeleteDB)
while (*Mempos++ != '\n') ; // What about Unix ???
// Set caller line buffer
len = (Mempos - Fpos) - Ending;
memcpy(Tdbp->GetLine(), Fpos, len);
Tdbp->GetLine()[len] = '\0';
return RC_OK;
} // end of ReadBuffer
/***********************************************************************/
/* WriteBuffer: File write routine for MAP access method. */
/***********************************************************************/
int MAPFAM::WriteBuffer(PGLOBAL g)
{
#if defined(_DEBUG)
// Insert mode is no more handled using file mapping
if (Tdbp->GetMode() == MODE_INSERT) {
strcpy(g->Message, MSG(NO_MAP_INSERT));
return RC_FX;
} // endif
#endif // _DEBUG
/*********************************************************************/
/* Copy the updated record back into the memory mapped file. */
/*********************************************************************/
memcpy(Fpos, Tdbp->GetLine(), strlen(Tdbp->GetLine()));
return RC_OK;
} // end of WriteBuffer
/***********************************************************************/
/* Data Base delete line routine for MAP (and FIX?) access methods. */
/* Lines between deleted lines are moved in the mapfile view. */
/***********************************************************************/
int MAPFAM::DeleteRecords(PGLOBAL g, int irc)
{
int n;
#ifdef DEBTRACE
fprintf(debug,
"MAP DeleteDB: irc=%d mempos=%p tobuf=%p Tpos=%p Spos=%p\n",
irc, Mempos, To_Buf, Tpos, Spos);
#endif
if (irc != RC_OK) {
/*******************************************************************/
/* EOF: position Fpos at the top of map position. */
/*******************************************************************/
Fpos = Top;
#ifdef DEBTRACE
htrc("Fpos placed at file top=%p\n", Fpos);
#endif
} // endif irc
if (Tpos == Spos)
/*******************************************************************/
/* First line to delete. Move of eventual preceeding lines is */
/* not required here, just setting of future Spos and Tpos. */
/*******************************************************************/
Tpos = Fpos; // Spos is set below
else if ((n = Fpos - Spos) > 0) {
/*******************************************************************/
/* Non consecutive line to delete. Move intermediate lines. */
/*******************************************************************/
memmove(Tpos, Spos, n);
Tpos += n;
#ifdef DEBTRACE
htrc("move %d bytes\n", n);
#endif
} // endif n
if (irc == RC_OK) {
Spos = Mempos; // New start position
#ifdef DEBTRACE
htrc("after: Tpos=%p Spos=%p\n", Tpos, Spos);
#endif
} else {
/*******************************************************************/
/* Last call after EOF has been reached. */
/* We must firstly Unmap the view and use the saved file handle */
/* to put an EOF at the end of the copied part of the file. */
/*******************************************************************/
PFBLOCK fp = To_Fb;
CloseMemMap(fp->Memory, (size_t)fp->Length);
fp->Count = 0; // Avoid doing it twice
/*******************************************************************/
/* Remove extra records. */
/*******************************************************************/
n = Tpos - Memory;
#if defined(WIN32)
DWORD drc = SetFilePointer(fp->Handle, n, NULL, FILE_BEGIN);
if (drc == 0xFFFFFFFF) {
sprintf(g->Message, MSG(FUNCTION_ERROR),
"SetFilePointer", GetLastError());
CloseHandle(fp->Handle);
return RC_FX;
} // endif
#ifdef DEBTRACE
htrc("done, Tpos=%p newsize=%d drc=%d\n", Tpos, n, drc);
#endif
if (!SetEndOfFile(fp->Handle)) {
sprintf(g->Message, MSG(FUNCTION_ERROR),
"SetEndOfFile", GetLastError());
CloseHandle(fp->Handle);
return RC_FX;
} // endif
CloseHandle(fp->Handle);
#else // UNIX
if (ftruncate(fp->Handle, (off_t)n)) {
sprintf(g->Message, MSG(TRUNCATE_ERROR), strerror(errno));
close(fp->Handle);
return RC_FX;
} // endif
close(fp->Handle);
#endif // UNIX
} // endif irc
return RC_OK; // All is correct
} // end of DeleteRecords
/***********************************************************************/
/* Table file close routine for MAP access method. */
/***********************************************************************/
void MAPFAM::CloseTableFile(PGLOBAL g)
{
PlugCloseFile(g, To_Fb);
To_Fb = NULL; // To get correct file size in Cardinality
#ifdef DEBTRACE
htrc("MAP Close: closing %s count=%d\n",
To_File, (To_Fb) ? To_Fb->Count : 0);
#endif
} // end of CloseTableFile
/***********************************************************************/
/* Rewind routine for MAP access method. */
/***********************************************************************/
void MAPFAM::Rewind(void)
{
Mempos = Memory;
} // end of Rewind
/* --------------------------- Class MBKFAM -------------------------- */
/***********************************************************************/
/* Constructors. */
/***********************************************************************/
MBKFAM::MBKFAM(PDOSDEF tdp) : MAPFAM(tdp)
{
Blocked = true;
Block = tdp->GetBlock();
Last = tdp->GetLast();
Nrec = tdp->GetElemt();
BlkPos = tdp->GetTo_Pos();
CurNum = Nrec;
} // end of MBKFAM standard constructor
/***********************************************************************/
/* Reset: reset position values at the beginning of file. */
/***********************************************************************/
void MBKFAM::Reset(void)
{
MAPFAM::Reset();
CurNum = Nrec; // To start by a new block
} // end of Reset
/***********************************************************************/
/* Cardinality: returns table cardinality in number of rows. */
/* This function can be called with a null argument to test the */
/* availability of Cardinality implementation (1 yes, 0 no). */
/***********************************************************************/
int MBKFAM::Cardinality(PGLOBAL g)
{
// Should not be called in this version
return (g) ? -1 : 0;
//return (g) ? (int)((Block - 1) * Nrec + Last) : 1;
} // end of Cardinality
/***********************************************************************/
/* Skip one record in file. */
/***********************************************************************/
int MBKFAM::SkipRecord(PGLOBAL g, bool header)
{
return RC_OK;
} // end of SkipRecord
/***********************************************************************/
/* GetRowID: return the RowID of last read record. */
/***********************************************************************/
int MBKFAM::GetRowID(void)
{
return CurNum + Nrec * CurBlk + 1;
} // end of GetRowID
/***********************************************************************/
/* ReadBuffer: Read one line for a mapped Fix file. */
/***********************************************************************/
int MBKFAM::ReadBuffer(PGLOBAL g)
{
int len;
/*********************************************************************/
/* Sequential block reading when Placed is not true. */
/*********************************************************************/
if (Placed) {
Placed = false;
} else if (Mempos >= Top) { // Are we at the end of the memory
return RC_EF;
} else if (++CurNum < Nrec) {
Fpos = Mempos;
} else {
/*******************************************************************/
/* New block. */
/*******************************************************************/
CurNum = 0;
if (++CurBlk >= Block)
return RC_EF;
Fpos = Mempos = Memory + BlkPos[CurBlk];
} // endif's
// Immediately calculate next position (Used by DeleteDB)
while (*Mempos++ != '\n') ; // What about Unix ???
// Set caller line buffer
len = (Mempos - Fpos) - Ending;
memcpy(Tdbp->GetLine(), Fpos, len);
Tdbp->GetLine()[len] = '\0';
return RC_OK;
} // end of ReadBuffer
/***********************************************************************/
/* Rewind routine for FIX MAP access method. */
/***********************************************************************/
void MBKFAM::Rewind(void)
{
Mempos = Memory + Headlen;
CurBlk = -1;
CurNum = Nrec;
} // end of Rewind
/* --------------------------- Class MPXFAM -------------------------- */
/***********************************************************************/
/* Constructors. */
/***********************************************************************/
MPXFAM::MPXFAM(PDOSDEF tdp) : MBKFAM(tdp)
{
Blksize = tdp->GetBlksize();
Padded = tdp->GetPadded();
if (Padded && Blksize)
Nrec = Blksize / Lrecl;
else {
Nrec = (tdp->GetElemt()) ? tdp->GetElemt() : DOS_BUFF_LEN;
Blksize = Nrec * Lrecl;
Padded = false;
} // endelse
CurNum = Nrec;
} // end of MPXFAM standard constructor
#if 0 // MBKFAM routine is correct
/***********************************************************************/
/* GetRowID: return the RowID of last read record. */
/***********************************************************************/
int MPXFAM::GetRowID(void)
{
return (Mempos - Memory - Headlen) / Lrecl;
} // end of GetRowID
#endif
/***********************************************************************/
/* GetPos: return the position of last read record. */
/***********************************************************************/
int MPXFAM::GetPos(void)
{
return (CurNum + Nrec * CurBlk); // Computed file index
} // end of GetPos
/***********************************************************************/
/* SetPos: Replace the table at the specified position. */
/***********************************************************************/
bool MPXFAM::SetPos(PGLOBAL g, int pos)
{
if (pos < 0) {
strcpy(g->Message, MSG(INV_REC_POS));
return true;
} // endif recpos
CurBlk = pos / Nrec;
CurNum = pos % Nrec;
Fpos = Mempos = Memory + Headlen + pos * Lrecl;
// Indicate the table position was externally set
Placed = true;
return false;
} // end of SetPos
/***********************************************************************/
/* ReadBuffer: Read one line for a mapped Fix file. */
/***********************************************************************/
int MPXFAM::ReadBuffer(PGLOBAL g)
{
/*********************************************************************/
/* Sequential block reading when Placed is not true. */
/*********************************************************************/
if (Placed) {
Placed = false;
} else if (Mempos >= Top) { // Are we at the end of the memory
return RC_EF;
} else if (++CurNum < Nrec) {
Fpos = Mempos;
} else {
/*******************************************************************/
/* New block. */
/*******************************************************************/
CurNum = 0;
if (++CurBlk >= Block)
return RC_EF;
Fpos = Mempos = Headlen + Memory + CurBlk * Blksize;
} // endif's
Tdbp->SetLine(Mempos);
// Immediately calculate next position (Used by DeleteDB)
Mempos += Lrecl;
return RC_OK;
} // end of ReadBuffer
/***********************************************************************/
/* WriteBuffer: File write routine for MAP access method. */
/***********************************************************************/
int MPXFAM::WriteBuffer(PGLOBAL g)
{
#if defined(_DEBUG)
// Insert mode is no more handled using file mapping
if (Tdbp->GetMode() == MODE_INSERT) {
strcpy(g->Message, MSG(NO_MAP_INSERT));
return RC_FX;
} // endif
#endif // _DEBUG
// In Update mode, file was modified in memory
return RC_OK;
} // end of WriteBuffer

114
storage/connect/filamap.h Normal file
View File

@@ -0,0 +1,114 @@
/*************** FilAMap H Declares Source Code File (.H) **************/
/* Name: FILAMAP.H Version 1.2 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 2005-2012 */
/* */
/* This file contains the MAP file access method classes declares. */
/***********************************************************************/
#ifndef __FILAMAP_H
#define __FILAMAP_H
#include "block.h"
#include "filamtxt.h"
typedef class MAPFAM *PMAPFAM;
/***********************************************************************/
/* This is the variable file access method using file mapping. */
/***********************************************************************/
class DllExport MAPFAM : public TXTFAM {
public:
// Constructor
MAPFAM(PDOSDEF tdp);
MAPFAM(PMAPFAM tmfp);
// Implementation
virtual AMT GetAmType(void) {return TYPE_AM_MAP;}
virtual int GetPos(void);
virtual int GetNextPos(void);
virtual PTXF Duplicate(PGLOBAL g)
{return (PTXF)new(g) MAPFAM(this);}
// Methods
virtual void Reset(void);
virtual int GetFileLength(PGLOBAL g);
virtual int Cardinality(PGLOBAL g) {return (g) ? -1 : 0;}
virtual int MaxBlkSize(PGLOBAL g, int s) {return s;}
virtual int GetRowID(void);
virtual bool RecordPos(PGLOBAL g);
virtual bool SetPos(PGLOBAL g, int recpos);
virtual int SkipRecord(PGLOBAL g, bool header);
virtual bool OpenTableFile(PGLOBAL g);
virtual bool DeferReading(void) {return false;}
virtual int ReadBuffer(PGLOBAL g);
virtual int WriteBuffer(PGLOBAL g);
virtual int DeleteRecords(PGLOBAL g, int irc);
virtual void CloseTableFile(PGLOBAL g);
virtual void Rewind(void);
protected:
// Members
char *Memory; // Pointer on file mapping view.
char *Mempos; // Position of next data to read
char *Fpos; // Position of last read record
char *Tpos; // Target Position for delete move
char *Spos; // Start position for delete move
char *Top; // Mark end of file mapping view
}; // end of class MAPFAM
/***********************************************************************/
/* This is the blocked file access method using file mapping. */
/***********************************************************************/
class DllExport MBKFAM : public MAPFAM {
public:
// Constructor
MBKFAM(PDOSDEF tdp);
MBKFAM(PMAPFAM tmfp) : MAPFAM(tmfp) {}
// Implementation
virtual PTXF Duplicate(PGLOBAL g)
{return (PTXF)new(g) MBKFAM(this);}
// Methods
virtual void Reset(void);
virtual int Cardinality(PGLOBAL g);
virtual int MaxBlkSize(PGLOBAL g, int s)
{return TXTFAM::MaxBlkSize(g, s);}
virtual int GetRowID(void);
virtual int SkipRecord(PGLOBAL g, bool header);
virtual int ReadBuffer(PGLOBAL g);
virtual void Rewind(void);
protected:
// No additional members
}; // end of class MBKFAM
/***********************************************************************/
/* This is the fixed file access method using file mapping. */
/***********************************************************************/
class DllExport MPXFAM : public MBKFAM {
public:
// Constructor
MPXFAM(PDOSDEF tdp);
MPXFAM(PMAPFAM tmfp) : MBKFAM(tmfp) {}
// Implementation
virtual int GetPos(void);
virtual PTXF Duplicate(PGLOBAL g)
{return (PTXF)new(g) MPXFAM(this);}
// Methods
virtual int Cardinality(PGLOBAL g) {return TXTFAM::Cardinality(g);}
virtual int MaxBlkSize(PGLOBAL g, int s)
{return TXTFAM::MaxBlkSize(g, s);}
//virtual int GetRowID(void);
virtual bool SetPos(PGLOBAL g, int recpos);
virtual bool DeferReading(void) {return false;}
virtual int ReadBuffer(PGLOBAL g);
virtual int WriteBuffer(PGLOBAL g);
protected:
// No additional members
}; // end of class MPXFAM
#endif // __FILAMAP_H

View File

@@ -0,0 +1,975 @@
/*********** File AM Dbf C++ Program Source Code File (.CPP) ****************/
/* PROGRAM NAME: FILAMDBF */
/* ------------- */
/* Version 1.6 */
/* */
/* COPYRIGHT: */
/* ---------- */
/* (C) Copyright to the author Olivier BERTRAND 2005-2013 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
/* This program are the DBF file access method classes. */
/* */
/* ACKNOWLEDGEMENT: */
/* ---------------- */
/* Somerset Data Systems, Inc. (908) 766-5845 */
/* Version 1.2 April 6, 1991 */
/* Programmer: Jay Parsons */
/****************************************************************************/
/***********************************************************************/
/* Include relevant sections of the System header files. */
/***********************************************************************/
#include "my_global.h"
#if defined(WIN32)
#include <io.h>
#include <fcntl.h>
//#include <errno.h>
//#include <windows.h>
#else // !WIN32
#if defined(UNIX)
#include <errno.h>
#include <unistd.h>
#else // !UNIX
//#include <io.h>
#endif // !UNIX
//#include <fcntl.h>
#endif // !WIN32
#include <ctype.h>
#include <stdio.h>
#include <string.h>
/***********************************************************************/
/* Include application header files: */
/* global.h is header containing all global declarations. */
/* plgdbsem.h is header containing the DB application declarations. */
/* tabdos.h is header containing the TABDOS class declarations. */
/***********************************************************************/
#include "global.h"
#include "plgdbsem.h"
//#include "catalog.h"
//#include "kindex.h"
#include "filamdbf.h"
#include "tabdos.h"
#include "valblk.h"
#define NO_FUNC
#include "plgcnx.h" // For DB types
#include "resource.h"
/****************************************************************************/
/* Definitions. */
/****************************************************************************/
#define HEADLEN 32 /* sizeof ( mainhead or thisfield ) */
//efine MEMOLEN 10 /* length of memo field in .dbf */
#define DBFTYPE 3 /* value of bits 0 and 1 if .dbf */
#define EOH 0x0D /* end-of-header marker in .dbf file */
/****************************************************************************/
/* Catalog utility function. */
/****************************************************************************/
PQRYRES PlgAllocResult(PGLOBAL, int, int, int, int *, int *,
unsigned int *, bool blank = true, bool nonull = false);
bool PushWarning(PGLOBAL, PTDBASE);
extern "C" int trace; // The general trace value
/****************************************************************************/
/* First 32 bytes of a .dbf file. */
/* Note: some reserved fields are used here to store info (Fields) */
/****************************************************************************/
typedef struct _dbfheader {
//uchar Dbf :2; /* both 1 for dBASE III or IV .dbf */
//uchar :1;
//uchar Db4dbt:1; /* 1 if a dBASE IV-type .dbt exists */
//uchar Dbfox :4; /* FoxPro if equal to 3 */
uchar Version; /* Version information flags */
char Filedate[3]; /* date, YYMMDD, binary. YY=year-1900 */
uint Records; /* records in the file */
ushort Headlen; /* bytes in the header */
ushort Reclen; /* bytes in a record */
ushort Fields; /* Reserved but used to store fields */
char Incompleteflag; /* 01 if incomplete, else 00 */
char Encryptflag; /* 01 if encrypted, else 00 */
char Reserved2[12]; /* for LAN use */
char Mdxflag; /* 01 if production .mdx, else 00 */
char Language; /* Codepage */
char Reserved3[2];
} DBFHEADER;
/****************************************************************************/
/* Column field descriptor of a .dbf file. */
/****************************************************************************/
typedef struct _descriptor {
char Name[11]; /* field name, in capitals, null filled*/
char Type; /* field type, C, D, F, L, M or N */
uint Offset; /* used in memvars, not in files. */
uchar Length; /* field length */
uchar Decimals; /* number of decimal places */
short Reserved4;
char Workarea; /* ??? */
char Reserved5[2];
char Setfield; /* ??? */
char Reserved6[7];
char Mdxfield; /* 01 if tag field in production .mdx */
} DESCRIPTOR;
/****************************************************************************/
/* dbfhead: Routine to analyze a .dbf header. */
/* Parameters: */
/* PGLOBAL g -- pointer to the Plug Global structure */
/* FILE *file -- pointer to file to analyze */
/* PSZ fn -- pathname of the file to analyze */
/* DBFHEADER *buf -- pointer to _dbfheader structure */
/* Returns: */
/* RC_OK, RC_NF, RC_INFO, or RC_FX if error. */
/* Side effects: */
/* Moves file pointer to byte 32; fills buffer at buf with */
/* first 32 bytes of file. */
/****************************************************************************/
static int dbfhead(PGLOBAL g, FILE *file, PSZ fn, DBFHEADER *buf)
{
char endmark[2];
int dbc = 2, rc = RC_OK;
*g->Message = '\0';
// Read the first 32 bytes into buffer
if (fread(buf, HEADLEN, 1, file) != 1) {
strcpy(g->Message, MSG(NO_READ_32));
return RC_NF;
} // endif fread
// Check first byte to be sure of .dbf type
if ((buf->Version & 0x03) != DBFTYPE) {
strcpy(g->Message, MSG(NOT_A_DBF_FILE));
rc = RC_INFO;
if ((buf->Version & 0x30) == 0x30) {
strcpy(g->Message, MSG(FOXPRO_FILE));
dbc = 264; // FoxPro database container
} // endif Version
} else
strcpy(g->Message, MSG(DBASE_FILE));
// Check last byte(s) of header
if (fseek(file, buf->Headlen - dbc, SEEK_SET) != 0) {
sprintf(g->Message, MSG(BAD_HEADER), fn);
return RC_FX;
} // endif fseek
if (fread(&endmark, 2, 1, file) != 1) {
strcpy(g->Message, MSG(BAD_HEAD_END));
return RC_FX;
} // endif fread
// Some files have just 1D others have 1D00 following fields
if (endmark[0] != EOH && endmark[1] != EOH) {
sprintf(g->Message, MSG(NO_0DH_HEAD), dbc);
if (rc == RC_OK)
return RC_FX;
} // endif endmark
// Calculate here the number of fields while we have the dbc info
buf->Fields = (buf->Headlen - dbc - 1) / 32;
fseek(file, HEADLEN, SEEK_SET);
return rc;
} // end of dbfhead
/* -------------------------- Function DBFColumns ------------------------- */
/****************************************************************************/
/* DBFColumns: constructs the result blocks containing the description */
/* of all the columns of a DBF file that will be retrieved by #GetData. */
/****************************************************************************/
PQRYRES DBFColumns(PGLOBAL g, char *fn, BOOL info)
{
static int dbtype[] = {DB_CHAR, DB_SHORT, DB_CHAR,
DB_INT, DB_INT, DB_SHORT};
static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING,
TYPE_INT, TYPE_INT, TYPE_SHORT};
static unsigned int length[] = {11, 6, 8, 10, 10, 6};
char buf[2], filename[_MAX_PATH];
int ncol = sizeof(dbtype) / sizeof(int);
int rc, type, field, fields;
BOOL bad;
DBFHEADER mainhead;
DESCRIPTOR thisfield;
FILE *infile;
PQRYRES qrp;
PCOLRES crp;
if (trace)
htrc("DBFColumns: File %s\n", SVP(fn));
if (!fn) {
strcpy(g->Message, MSG(MISSING_FNAME));
return NULL;
} // endif fn
/**************************************************************************/
/* Open the input file. */
/**************************************************************************/
PlugSetPath(filename, fn, PlgGetDataPath(g));
if (!(infile = fopen(filename, "rb"))) {
sprintf(g->Message, MSG(CANNOT_OPEN), filename);
return NULL;
} // endif file
/**************************************************************************/
/* Get the first 32 bytes of the header. */
/**************************************************************************/
if ((rc = dbfhead(g, infile, filename, &mainhead)) == RC_FX) {
fclose(infile);
return NULL;
} // endif dbfhead
/**************************************************************************/
/* Allocate the structures used to refer to the result set. */
/**************************************************************************/
//fields = (mainhead.Headlen - 33) / 32;
fields = mainhead.Fields;
qrp = PlgAllocResult(g, ncol, fields, IDS_COLUMNS + 3,
dbtype, buftyp, length);
qrp->Info = info || (rc == RC_INFO);
if (trace) {
htrc("Structure of %s\n", filename);
htrc("headlen=%hd reclen=%hd degree=%d\n",
mainhead.Headlen, mainhead.Reclen, fields);
htrc("flags(iem)=%d,%d,%d cp=%d\n", mainhead.Incompleteflag,
mainhead.Encryptflag, mainhead.Mdxflag, mainhead.Language);
htrc("%hd records, last changed %02d/%02d/%d\n",
mainhead.Records, mainhead.Filedate[1], mainhead.Filedate[2],
mainhead.Filedate[0] + (mainhead.Filedate[0] <= 30) ? 2000 : 1900);
htrc("Field Type Offset Len Dec Set Mdx\n");
} // endif trace
buf[1] = '\0';
/**************************************************************************/
/* Do it field by field. We are at byte 32 of file. */
/**************************************************************************/
for (field = 0; field < fields; field++) {
bad = FALSE;
if (fread(&thisfield, HEADLEN, 1, infile) != 1) {
sprintf(g->Message, MSG(ERR_READING_REC), field+1, fn);
goto err;
} // endif fread
if (trace)
htrc("%-11s %c %6ld %3d %2d %3d %3d\n",
thisfield.Name, thisfield.Type, thisfield.Offset, thisfield.Length,
thisfield.Decimals, thisfield.Setfield, thisfield.Mdxfield);
/************************************************************************/
/* Now get the results into blocks. */
/************************************************************************/
switch (thisfield.Type) {
case 'C': // Characters
case 'L': // Logical 'T' or 'F'
type = TYPE_STRING;
break;
case 'N':
type = (thisfield.Decimals) ? TYPE_FLOAT : TYPE_INT;
break;
case 'F':
type = TYPE_FLOAT;
break;
case 'D':
type = TYPE_DATE; // Is this correct ???
break;
default:
if (!info) {
sprintf(g->Message, MSG(BAD_DBF_TYPE), thisfield.Type);
goto err;
} // endif info
type = TYPE_ERROR;
bad = TRUE;
} // endswitch Type
crp = qrp->Colresp; // Column Name
crp->Kdata->SetValue(thisfield.Name, field);
crp = crp->Next; // Data Type
crp->Kdata->SetValue((int)type, field);
crp = crp->Next; // Type Name
if (bad) {
buf[0] = thisfield.Type;
crp->Kdata->SetValue(buf, field);
} else
crp->Kdata->SetValue(GetTypeName(type), field);
crp = crp->Next; // Precision
crp->Kdata->SetValue((int)thisfield.Length, field);
crp = crp->Next; // Length
crp->Kdata->SetValue((int)thisfield.Length, field);
crp = crp->Next; // Scale (precision)
crp->Kdata->SetValue((int)thisfield.Decimals, field);
} // endfor field
qrp->Nblin = field;
fclose(infile);
if (info) {
/************************************************************************/
/* Prepare return message for dbfinfo command. */
/************************************************************************/
char buf[64];
sprintf(buf,
"Ver=%02x ncol=%hu nlin=%u lrecl=%hu headlen=%hu date=%02d/%02d/%02d",
mainhead.Version, fields, mainhead.Records, mainhead.Reclen,
mainhead.Headlen, mainhead.Filedate[0], mainhead.Filedate[1],
mainhead.Filedate[2]);
strcat(g->Message, buf);
} // endif info
/**************************************************************************/
/* Return the result pointer for use by GetData routines. */
/**************************************************************************/
return qrp;
err:
fclose(infile);
return NULL;
} // end of DBFColumns
/* ---------------------------- Class DBFBASE ----------------------------- */
/****************************************************************************/
/* Constructors. */
/****************************************************************************/
DBFBASE::DBFBASE(PDOSDEF tdp)
{
Records = 0;
Nerr = 0;
Maxerr = tdp->Maxerr;
Accept = tdp->Accept;
ReadMode = tdp->ReadMode;
} // end of DBFBASE standard constructor
DBFBASE::DBFBASE(DBFBASE *txfp)
{
Records = txfp->Records;
Nerr = txfp->Nerr;
Maxerr = txfp->Maxerr;
Accept = txfp->Accept;
ReadMode = txfp->ReadMode;
} // end of DBFBASE copy constructor
/****************************************************************************/
/* ScanHeader: scan the DBF file header for number of records, record size,*/
/* and header length. Set Records, check that Reclen is equal to lrecl and */
/* return the header length or 0 in case of error. */
/****************************************************************************/
int DBFBASE::ScanHeader(PGLOBAL g, PSZ fname, int lrecl, char *defpath)
{
int rc;
char filename[_MAX_PATH];
DBFHEADER header;
FILE *infile;
/************************************************************************/
/* Open the input file. */
/************************************************************************/
PlugSetPath(filename, fname, defpath);
if (!(infile = fopen(filename, "rb"))) {
sprintf(g->Message, MSG(CANNOT_OPEN), filename);
return 0; // Assume file does not exist
} // endif file
/************************************************************************/
/* Get the first 32 bytes of the header. */
/************************************************************************/
rc = dbfhead(g, infile, filename, &header);
fclose(infile);
if (rc == RC_NF) {
Records = 0;
return 0;
} else if (rc == RC_FX)
return -1;
if ((int)header.Reclen != lrecl) {
sprintf(g->Message, MSG(BAD_LRECL), lrecl, header.Reclen);
return -1;
} // endif Lrecl
Records = (int)header.Records;
return (int)header.Headlen;
} // end of ScanHeader
/* ---------------------------- Class DBFFAM ------------------------------ */
/****************************************************************************/
/* Cardinality: returns table cardinality in number of rows. */
/* This function can be called with a null argument to test the */
/* availability of Cardinality implementation (1 yes, 0 no). */
/****************************************************************************/
int DBFFAM::Cardinality(PGLOBAL g)
{
if (!g)
return 1;
if (!Headlen)
if ((Headlen = ScanHeader(g, To_File, Lrecl, Tdbp->GetPath())) < 0)
return -1; // Error in ScanHeader
// Set number of blocks for later use
Block = (Records > 0) ? (Records + Nrec - 1) / Nrec : 0;
return Records;
} // end of Cardinality
#if 0 // Not compatible with ROWID block optimization
/***********************************************************************/
/* GetRowID: return the RowID of last read record. */
/***********************************************************************/
int DBFFAM::GetRowID(void)
{
return Rows;
} // end of GetRowID
#endif
/***********************************************************************/
/* OpenTableFile: Open a DBF table file using C standard I/Os. */
/* Binary mode cannot be used on Insert because of EOF (CTRL+Z) char. */
/***********************************************************************/
bool DBFFAM::OpenTableFile(PGLOBAL g)
{
char opmode[4], filename[_MAX_PATH];
//int ftype = Tdbp->GetFtype();
MODE mode = Tdbp->GetMode();
PDBUSER dbuserp = PlgGetUser(g);
switch (mode) {
case MODE_READ:
strcpy(opmode, "rb");
break;
case MODE_DELETE:
if (!Tdbp->GetNext()) {
// Store the number of deleted lines
DelRows = -1; // Means all lines deleted
// DelRows = Cardinality(g); no good because of soft deleted lines
// This will erase the entire file
strcpy(opmode, "w");
Tdbp->ResetSize();
Records = 0;
break;
} // endif
// Selective delete, pass thru
case MODE_UPDATE:
UseTemp = Tdbp->IsUsingTemp(g);
strcpy(opmode, (UseTemp) ? "rb" : "r+b");
break;
case MODE_INSERT:
// Must be in text mode to remove an eventual EOF character
strcpy(opmode, "a+");
break;
default:
sprintf(g->Message, MSG(BAD_OPEN_MODE), mode);
return true;
} // endswitch Mode
// Now open the file stream
PlugSetPath(filename, To_File, Tdbp->GetPath());
if (!(Stream = PlugOpenFile(g, filename, opmode))) {
sprintf(g->Message, MSG(OPEN_MODE_ERROR),
opmode, (int)errno, filename);
strcat(strcat(g->Message, ": "), strerror(errno));
#ifdef DEBTRACE
htrc("%s\n", g->Message);
#endif
return (errno == ENOENT) ? PushWarning(g, Tdbp) : true;
} // endif Stream
#ifdef DEBTRACE
htrc("File %s is open in mode %s\n", filename, opmode);
#endif
To_Fb = dbuserp->Openlist; // Keep track of File block
/*********************************************************************/
/* Allocate the line buffer. For mode Delete a bigger buffer has to */
/* be allocated because is it also used to move lines into the file.*/
/*********************************************************************/
return AllocateBuffer(g);
} // end of OpenTableFile
/****************************************************************************/
/* Allocate the block buffer for the table. */
/****************************************************************************/
bool DBFFAM::AllocateBuffer(PGLOBAL g)
{
int rc;
MODE mode = Tdbp->GetMode();
Buflen = Blksize;
To_Buf = (char*)PlugSubAlloc(g, NULL, Buflen);
if (mode == MODE_INSERT) {
#if defined(WIN32)
/************************************************************************/
/* Now we can revert to binary mode in particular because the eventual */
/* writing of a new header must be done in binary mode to avoid */
/* translating 0A bytes (LF) into 0D0A (CRLF) by Windows in text mode. */
/************************************************************************/
if (_setmode(_fileno(Stream), _O_BINARY) == -1) {
sprintf(g->Message, MSG(BIN_MODE_FAIL), strerror(errno));
return true;
} // endif setmode
#endif // WIN32
/************************************************************************/
/* If this is a new file, the header must be generated. */
/************************************************************************/
int len = GetFileLength(g);
if (!len) {
// Make the header for this DBF table file
struct tm *datm;
int hlen, n = 0, reclen = 1;
time_t t;
DBFHEADER *header;
DESCRIPTOR *descp;
PCOLDEF cdp;
PDOSDEF tdp = (PDOSDEF)Tdbp->GetDef();
// Count the number of columns
for (cdp = tdp->GetCols(); cdp; cdp = cdp->GetNext()) {
reclen += cdp->GetLong();
n++;
} // endfor cdp
if (Lrecl != reclen) {
sprintf(g->Message, MSG(BAD_LRECL), Lrecl, reclen);
return true;
} // endif Lrecl
hlen = HEADLEN * (n + 1) + 2;
header = (DBFHEADER*)PlugSubAlloc(g, NULL, hlen);
memset(header, 0, hlen);
header->Version = DBFTYPE;
t = time(NULL) - (time_t)DTVAL::GetShift();
datm = gmtime(&t);
header->Filedate[0] = datm->tm_year - 100;
header->Filedate[1] = datm->tm_mon + 1;
header->Filedate[2] = datm->tm_mday;
header->Headlen = (ushort)hlen;
header->Reclen = (ushort)reclen;
descp = (DESCRIPTOR*)header;
for (cdp = tdp->GetCols(); cdp; cdp = cdp->GetNext()) {
descp++;
strncpy(descp->Name, cdp->GetName(), 11);
descp->Type = *GetFormatType(cdp->GetType());
descp->Length = (uchar)cdp->GetLong();
descp->Decimals = (uchar)cdp->F.Prec;
} // endfor cdp
*(char*)(++descp) = EOH;
// Now write the header
if (fwrite(header, 1, hlen, Stream) != (unsigned)hlen) {
sprintf(g->Message, MSG(FWRITE_ERROR), strerror(errno));
return true;
} // endif fwrite
Records = 0;
Headlen = hlen;
} else if (len < 0)
return true; // Error in GetFileLength
/************************************************************************/
/* For Insert the buffer must be prepared. */
/************************************************************************/
memset(To_Buf, ' ', Buflen);
Rbuf = Nrec; // To be used by WriteDB
} else if (UseTemp) {
// Allocate a separate buffer so block reading can be kept
Dbflen = Nrec;
DelBuf = PlugSubAlloc(g, NULL, Blksize);
} // endif's
if (!Headlen) {
/************************************************************************/
/* Here is a good place to process the DBF file header */
/************************************************************************/
DBFHEADER header;
if ((rc = dbfhead(g, Stream, Tdbp->GetFile(g), &header)) == RC_OK) {
if (Lrecl != (int)header.Reclen) {
sprintf(g->Message, MSG(BAD_LRECL), Lrecl, header.Reclen);
return true;
} // endif Lrecl
Records = (int)header.Records;
Headlen = (int)header.Headlen;
} else if (rc == RC_NF) {
Records = 0;
Headlen = 0;
} else // RC_FX
return true; // Error in dbfhead
} // endif Headlen
/**************************************************************************/
/* Position the file at the begining of the data. */
/**************************************************************************/
if (Tdbp->GetMode() == MODE_INSERT)
rc = fseek(Stream, 0, SEEK_END);
else
rc = fseek(Stream, Headlen, SEEK_SET);
if (rc) {
sprintf(g->Message, MSG(BAD_DBF_FILE), Tdbp->GetFile(g));
return true;
} // endif fseek
return false;
} // end of AllocateBuffer
/***********************************************************************/
/* Reset buffer access according to indexing and to mode. */
/* >>>>>>>>>>>>>> TO BE RE-VISITED AND CHECKED <<<<<<<<<<<<<<<<<<<<<< */
/***********************************************************************/
void DBFFAM::ResetBuffer(PGLOBAL g)
{
/*********************************************************************/
/* If access is random, performances can be much better when the */
/* reads are done on only one row, except for small tables that can */
/* be entirely read in one block. If the index is just used as a */
/* bitmap filter, as for Update or delete, reading will be */
/* sequential and we better keep block reading. */
/*********************************************************************/
if (Tdbp->GetKindex() && Tdbp->GetMode() == MODE_READ &&
ReadBlks != 1) {
Nrec = 1; // Better for random access
Rbuf = 0;
Blksize = Lrecl;
OldBlk = -2; // Has no meaning anymore
Block = Tdbp->Cardinality(g); // Blocks are one line now
} // endif Mode
} // end of ResetBuffer
/***********************************************************************/
/* ReadBuffer: Read one line for a DBF file. */
/***********************************************************************/
int DBFFAM::ReadBuffer(PGLOBAL g)
{
if (!Placed && !Closing && GetRowID() == Records)
return RC_EF;
int rc = FIXFAM::ReadBuffer(g);
if (rc != RC_OK || Closing)
return rc;
switch (*Tdbp->GetLine()) {
case '*':
if (!ReadMode)
rc = RC_NF; // Deleted line
else
Rows++;
break;
case ' ':
if (ReadMode < 2)
Rows++; // Non deleted line
else
rc = RC_NF;
break;
default:
if (++Nerr >= Maxerr && !Accept) {
sprintf(g->Message, MSG(BAD_DBF_REC), Tdbp->GetFile(g), GetRowID());
rc = RC_FX;
} else
rc = (Accept) ? RC_OK : RC_NF;
} // endswitch To_Buf
return rc;
} // end of ReadBuffer
/***********************************************************************/
/* Copy the header into the temporary file. */
/***********************************************************************/
bool DBFFAM::CopyHeader(PGLOBAL g)
{
bool rc = true;
if (Headlen) {
void *hdr = PlugSubAlloc(g, NULL, Headlen);
size_t n, hlen = (size_t)Headlen;
int pos = ftell(Stream);
if (fseek(Stream, 0, SEEK_SET))
strcpy(g->Message, "Seek error in CopyHeader");
else if ((n = fread(hdr, 1, hlen, Stream)) != hlen)
sprintf(g->Message, MSG(BAD_READ_NUMBER), n, To_File);
else if ((n = fwrite(hdr, 1, hlen, T_Stream)) != hlen)
sprintf(g->Message, MSG(WRITE_STRERROR), To_Fbt->Fname
, strerror(errno));
else if (fseek(Stream, pos, SEEK_SET))
strcpy(g->Message, "Seek error in CopyHeader");
else
rc = false;
} else
rc = false;
return rc;
} // end of CopyHeader
/***********************************************************************/
/* Data Base delete line routine for DBF access methods. */
/* Deleted lines are just flagged in the first buffer character. */
/***********************************************************************/
int DBFFAM::DeleteRecords(PGLOBAL g, int irc)
{
if (irc == RC_OK) {
// T_Stream is the temporary stream or the table file stream itself
if (!T_Stream)
if (UseTemp) {
if (OpenTempFile(g))
return RC_FX;
if (CopyHeader(g)) // For DBF tables
return RC_FX;
} else
T_Stream = Stream;
*Tdbp->GetLine() = '*';
Modif++; // Modified line in Delete mode
} // endif irc
return RC_OK;
} // end of DeleteRecords
/***********************************************************************/
/* Rewind routine for DBF access method. */
/***********************************************************************/
void DBFFAM::Rewind(void)
{
BLKFAM::Rewind();
Nerr = 0;
} // end of Rewind
/***********************************************************************/
/* Table file close routine for DBF access method. */
/***********************************************************************/
void DBFFAM::CloseTableFile(PGLOBAL g)
{
int rc = RC_OK, wrc = RC_OK;
MODE mode = Tdbp->GetMode();
// Closing is True if last Write was in error
if (mode == MODE_INSERT && CurNum && !Closing) {
// Some more inserted lines remain to be written
Rbuf = CurNum--;
// Closing = true;
wrc = WriteBuffer(g);
} else if (mode == MODE_UPDATE || mode == MODE_DELETE) {
if (Modif && !Closing) {
// Last updated block remains to be written
Closing = true;
wrc = ReadBuffer(g);
} // endif Modif
if (UseTemp && T_Stream && wrc == RC_OK) {
// Copy any remaining lines
bool b;
Fpos = Tdbp->Cardinality(g);
if ((rc = MoveIntermediateLines(g, &b)) == RC_OK) {
// Delete the old file and rename the new temp file.
RenameTempFile(g);
goto fin;
} // endif rc
} // endif UseTemp
} // endif's mode
if (Tdbp->GetMode() == MODE_INSERT) {
int n = ftell(Stream) - Headlen;
rc = PlugCloseFile(g, To_Fb);
if (n >= 0 && !(n % Lrecl)) {
n /= Lrecl; // New number of lines
if (n > Records) {
// Update the number of rows in the file header
char filename[_MAX_PATH];
PlugSetPath(filename, To_File, Tdbp->GetPath());
Stream = fopen(filename, "r+b");
fseek(Stream, 4, SEEK_SET); // Get header.Records position
fwrite(&n, sizeof(int), 1, Stream);
fclose(Stream);
Stream = NULL;
Records = n; // Update Records value
} // endif n
} // endif n
} else // Finally close the file
rc = PlugCloseFile(g, To_Fb);
fin:
#ifdef DEBTRACE
htrc("DBF CloseTableFile: closing %s mode=%d wrc=%d rc=%d\n",
To_File, mode, wrc, rc);
#endif
Stream = NULL; // So we can know whether table is open
} // end of CloseTableFile
/* ---------------------------- Class DBMFAM ------------------------------ */
/****************************************************************************/
/* Cardinality: returns table cardinality in number of rows. */
/* This function can be called with a null argument to test the */
/* availability of Cardinality implementation (1 yes, 0 no). */
/****************************************************************************/
int DBMFAM::Cardinality(PGLOBAL g)
{
if (!g)
return 1;
if (!Headlen)
if ((Headlen = ScanHeader(g, To_File, Lrecl, Tdbp->GetPath())) < 0)
return -1; // Error in ScanHeader
// Set number of blocks for later use
Block = (Records > 0) ? (Records + Nrec - 1) / Nrec : 0;
return Records;
} // end of Cardinality
#if 0 // Not compatible with ROWID block optimization
/***********************************************************************/
/* GetRowID: return the RowID of last read record. */
/***********************************************************************/
int DBMFAM::GetRowID(void)
{
return Rows;
} // end of GetRowID
#endif
/***********************************************************************/
/* Just check that on all deletion the unknown deleted line number is */
/* sent back because Cardinality doesn't count soft deleted lines. */
/***********************************************************************/
int DBMFAM::GetDelRows(void)
{
if (Tdbp->GetMode() == MODE_DELETE && !Tdbp->GetNext())
return -1; // Means all lines deleted
else
return DelRows;
} // end of GetDelRows
/****************************************************************************/
/* Allocate the block buffer for the table. */
/****************************************************************************/
bool DBMFAM::AllocateBuffer(PGLOBAL g)
{
if (!Headlen) {
/************************************************************************/
/* Here is a good place to process the DBF file header */
/************************************************************************/
DBFHEADER *hp = (DBFHEADER*)Memory;
if (Lrecl != (int)hp->Reclen) {
sprintf(g->Message, MSG(BAD_LRECL), Lrecl, hp->Reclen);
return true;
} // endif Lrecl
Records = (int)hp->Records;
Headlen = (int)hp->Headlen;
} // endif Headlen
/**************************************************************************/
/* Position the file at the begining of the data. */
/**************************************************************************/
Fpos = Mempos = Memory + Headlen;
Top--; // Because of EOF marker
return false;
} // end of AllocateBuffer
/****************************************************************************/
/* ReadBuffer: Read one line for a FIX file. */
/****************************************************************************/
int DBMFAM::ReadBuffer(PGLOBAL g)
{
// if (!Placed && GetRowID() == Records)
// return RC_EF;
int rc = MPXFAM::ReadBuffer(g);
if (rc != RC_OK)
return rc;
switch (*Fpos) {
case '*':
if (!ReadMode)
rc = RC_NF; // Deleted line
else
Rows++;
break;
case ' ':
if (ReadMode < 2)
Rows++; // Non deleted line
else
rc = RC_NF;
break;
default:
if (++Nerr >= Maxerr && !Accept) {
sprintf(g->Message, MSG(BAD_DBF_REC), Tdbp->GetFile(g), GetRowID());
rc = RC_FX;
} else
rc = (Accept) ? RC_OK : RC_NF;
} // endswitch To_Buf
return rc;
} // end of ReadBuffer
/****************************************************************************/
/* Data Base delete line routine for DBF access methods. */
/* Deleted lines are just flagged in the first buffer character. */
/****************************************************************************/
int DBMFAM::DeleteRecords(PGLOBAL g, int irc)
{
if (irc == RC_OK)
*Fpos = '*';
return RC_OK;
} // end of DeleteRecords
/***********************************************************************/
/* Rewind routine for DBF access method. */
/***********************************************************************/
void DBMFAM::Rewind(void)
{
MBKFAM::Rewind();
Nerr = 0;
} // end of Rewind
/* --------------------------------- EOF ---------------------------------- */

111
storage/connect/filamdbf.h Normal file
View File

@@ -0,0 +1,111 @@
/***************** FilAmDbf H Declares Source Code File (.H) ****************/
/* Name: filamdbf.h Version 1.3 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 2005-2012 */
/* */
/* This file contains the DBF file access method classes declares. */
/****************************************************************************/
#ifndef __FILAMDBF_H
#define __FILAMDBF_H
#include "filamfix.h"
#include "filamap.h"
typedef class DBFBASE *PDBF;
typedef class DBFFAM *PDBFFAM;
typedef class DBMFAM *PDBMFAM;
/****************************************************************************/
/* This is the base class for dBASE file access methods. */
/****************************************************************************/
class DllExport DBFBASE {
public:
// Constructors
DBFBASE(PDOSDEF tdp);
DBFBASE(PDBF txfp);
// Implementation
int ScanHeader(PGLOBAL g, PSZ fname, int lrecl, char *defpath);
protected:
// Default constructor, not to be used
DBFBASE(void) {}
// Members
int Records; /* records in the file */
bool Accept; /* true if bad lines are accepted */
int Nerr; /* Number of bad records */
int Maxerr; /* Maximum number of bad records */
int ReadMode; /* 1: ALL 2: DEL 0: NOT DEL */
//PSZ Defpath; /* Default data path */
}; // end of class DBFBASE
/****************************************************************************/
/* This is the DOS/UNIX Access Method class declaration for DBase files. */
/****************************************************************************/
class DllExport DBFFAM : public FIXFAM, public DBFBASE {
public:
// Constructors
DBFFAM(PDOSDEF tdp) : FIXFAM(tdp), DBFBASE(tdp) {}
DBFFAM(PDBFFAM txfp) : FIXFAM(txfp), DBFBASE((PDBF)txfp) {}
// Implementation
virtual AMT GetAmType(void) {return TYPE_AM_DBF;}
virtual PTXF Duplicate(PGLOBAL g)
{return (PTXF)new(g) DBFFAM(this);}
// Methods
virtual int GetNerr(void) {return Nerr;}
virtual int Cardinality(PGLOBAL g);
//virtual int GetRowID(void); // Temporarily suppressed
virtual bool OpenTableFile(PGLOBAL g);
virtual bool AllocateBuffer(PGLOBAL g);
virtual void ResetBuffer(PGLOBAL g);
virtual int ReadBuffer(PGLOBAL g);
//virtual int WriteBuffer(PGLOBAL g);
virtual int DeleteRecords(PGLOBAL g, int irc);
virtual void CloseTableFile(PGLOBAL g);
virtual void Rewind(void);
protected:
// Members
virtual bool CopyHeader(PGLOBAL g);
//int Records; in TXTFAM
//int Headlen; in TXTFAM
}; // end of class DBFFAM
/****************************************************************************/
/* This is the DOS/UNIX Access Method class declaration for DBase files */
/* using file mapping to access the file. */
/****************************************************************************/
class DllExport DBMFAM : public MPXFAM, public DBFBASE {
public:
// Constructors
DBMFAM(PDOSDEF tdp) : MPXFAM(tdp), DBFBASE(tdp) {}
DBMFAM(PDBMFAM txfp) : MPXFAM(txfp), DBFBASE((PDBF)txfp) {}
// Implementation
virtual AMT GetAmType(void) {return TYPE_AM_DBF;}
virtual PTXF Duplicate(PGLOBAL g)
{return (PTXF)new(g) DBMFAM(this);}
virtual int GetDelRows(void);
// Methods
virtual int GetNerr(void) {return Nerr;}
virtual int Cardinality(PGLOBAL g);
//virtual int GetRowID(void); // Temporarily suppressed
virtual bool AllocateBuffer(PGLOBAL g);
virtual int ReadBuffer(PGLOBAL g);
//virtual int WriteBuffer(PGLOBAL g);
virtual int DeleteRecords(PGLOBAL g, int irc);
virtual void Rewind(void);
protected:
// Members
//int Records; in TXTFAM
//int Headlen; in TXTFAM
}; // end of class DBFFAM
#endif // __FILAMDBF_H

1446
storage/connect/filamfix.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,98 @@
/************** FilAMFix H Declares Source Code File (.H) **************/
/* Name: FILAMFIX.H Version 1.2 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 2005 - 2012 */
/* */
/* This file contains the FIX file access method classes declares. */
/***********************************************************************/
#ifndef __FILAMFIX_H
#define __FILAMFIX_H
#include "filamtxt.h"
typedef class FIXFAM *PFIXFAM;
typedef class BGXFAM *PBGXFAM;
/***********************************************************************/
/* This is the DOS/UNIX Access Method class declaration for standard */
/* files with fixed record format (FIX, BIN) */
/***********************************************************************/
class DllExport FIXFAM : public BLKFAM {
public:
// Constructor
FIXFAM(PDOSDEF tdp);
FIXFAM(PFIXFAM txfp);
// Implementation
virtual AMT GetAmType(void) {return TYPE_AM_FIX;}
virtual PTXF Duplicate(PGLOBAL g)
{return (PTXF)new(g) FIXFAM(this);}
// Methods
virtual int Cardinality(PGLOBAL g) {return TXTFAM::Cardinality(g);}
virtual int MaxBlkSize(PGLOBAL g, int s)
{return TXTFAM::MaxBlkSize(g, s);}
virtual bool AllocateBuffer(PGLOBAL g);
virtual void ResetBuffer(PGLOBAL g);
virtual int ReadBuffer(PGLOBAL g);
virtual int WriteBuffer(PGLOBAL g);
virtual int DeleteRecords(PGLOBAL g, int irc);
virtual void CloseTableFile(PGLOBAL g);
protected:
virtual bool CopyHeader(PGLOBAL g) {return false;}
virtual bool MoveIntermediateLines(PGLOBAL g, bool *b);
// No additional members
}; // end of class FIXFAM
#if defined(WIN32)
typedef __int64 BIGINT;
#else // !WIN32
typedef off64_t BIGINT;
#define FILE_BEGIN SEEK_SET
#define FILE_CURRENT SEEK_CUR
#define FILE_END SEEK_END
#endif // !WIN32
/***********************************************************************/
/* This is the DOS/UNIX Access Method class declaration for files */
/* that are standard files with columns starting at fixed offset */
/* This class is for fixed formatted files of more than 2 gigabytes. */
/***********************************************************************/
class BGXFAM : public FIXFAM {
public:
// Constructor
BGXFAM(PDOSDEF tdp);
BGXFAM(PBGXFAM txfp);
// Implementation
virtual PTXF Duplicate(PGLOBAL g)
{return (PTXF)new(g) BGXFAM(this);}
// Methods
//virtual void Reset(void);
virtual int Cardinality(PGLOBAL g);
virtual bool OpenTableFile(PGLOBAL g);
virtual int ReadBuffer(PGLOBAL g);
virtual int WriteBuffer(PGLOBAL g);
virtual int DeleteRecords(PGLOBAL g, int irc);
virtual void CloseTableFile(PGLOBAL g);
virtual void Rewind(void);
protected:
bool BigSeek(PGLOBAL g, HANDLE h, BIGINT pos
, int org = FILE_BEGIN);
int BigRead(PGLOBAL g, HANDLE h, void *inbuf, int req);
bool BigWrite(PGLOBAL g, HANDLE h, void *inbuf, int req);
virtual bool OpenTempFile(PGLOBAL g);
virtual bool MoveIntermediateLines(PGLOBAL g, bool *b = NULL);
// Members
HANDLE Hfile; // Handle(descriptor) to big file
HANDLE Tfile; // Handle(descriptor) to big temp file
//BIGINT Xpos; // Current file position
}; // end of class BGXFAM
#endif // __FILAMFIX_H

1422
storage/connect/filamtxt.cpp Normal file

File diff suppressed because it is too large Load Diff

198
storage/connect/filamtxt.h Normal file
View File

@@ -0,0 +1,198 @@
/************** FilAMTxt H Declares Source Code File (.H) **************/
/* Name: FILAMTXT.H Version 1.2 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 2005-2012 */
/* */
/* This file contains the file access method classes declares. */
/***********************************************************************/
#ifndef __FILAMTXT_H
#define __FILAMTXT_H
#include "block.h"
typedef class TXTFAM *PTXF;
typedef class DOSFAM *PDOSFAM;
typedef class BLKFAM *PBLKFAM;
typedef class DOSDEF *PDOSDEF;
typedef class TDBDOS *PTDBDOS;
#define TYPE_AM_BLK (AMT)160
/***********************************************************************/
/* This is the base class for all file access method classes. */
/***********************************************************************/
class DllExport TXTFAM : public BLOCK {
friend class TDBDOS;
friend class TDBCSV;
friend class TDBFIX;
friend class TDBVCT;
friend class DOSCOL;
friend class BINCOL;
friend class VCTCOL;
public:
// Constructor
TXTFAM(PDOSDEF tdp);
TXTFAM(PTXF txfp);
// Implementation
virtual AMT GetAmType(void) = 0;
virtual int GetPos(void) = 0;
virtual int GetNextPos(void) = 0;
virtual PTXF Duplicate(PGLOBAL g) = 0;
virtual bool GetUseTemp(void) {return false;}
virtual int GetDelRows(void) {return DelRows;}
int GetCurBlk(void) {return CurBlk;}
void SetTdbp(PTDBDOS tdbp) {Tdbp = tdbp;}
int GetBlock(void) {return Block;}
void SetBlkPos(int *bkp) {BlkPos = bkp;}
void SetNrec(int n) {Nrec = n;}
char *GetBuf(void) {return To_Buf;}
int GetRows(void) {return Rows;}
bool IsBlocked(void) {return Blocked;}
// Methods
virtual void Reset(void);
virtual int GetFileLength(PGLOBAL g);
virtual int Cardinality(PGLOBAL g);
virtual int MaxBlkSize(PGLOBAL g, int s);
virtual bool AllocateBuffer(PGLOBAL g) {return false;}
virtual void ResetBuffer(PGLOBAL g) {}
virtual int GetNerr(void) {return 0;}
virtual int GetRowID(void) = 0;
virtual bool RecordPos(PGLOBAL g) = 0;
virtual bool SetPos(PGLOBAL g, int recpos) = 0;
virtual int SkipRecord(PGLOBAL g, bool header) = 0;
virtual bool OpenTableFile(PGLOBAL g) = 0;
virtual bool DeferReading(void) {IsRead = false; return true;}
virtual int ReadBuffer(PGLOBAL g) = 0;
virtual int WriteBuffer(PGLOBAL g) = 0;
virtual int DeleteRecords(PGLOBAL g, int irc) = 0;
virtual void CloseTableFile(PGLOBAL g) = 0;
virtual void Rewind(void) = 0;
protected:
// Members
PTDBDOS Tdbp; // To table class
PSZ To_File; // Points to table file name
PFBLOCK To_Fb; // Pointer to file block
bool Placed; // true if Recpos was externally set
bool IsRead; // false for deferred reading
bool Blocked; // true if using blocked I/O
char *To_Buf; // Points to I/O buffer
void *DelBuf; // Buffer used to move lines in Delete
int *BlkPos; // To array of block positions
int BlkLen; // Current block length
int Buflen; // Buffer length
int Dbflen; // Delete buffer length
int Rows; // Number of rows read so far
int DelRows; // Number of deleted rows
int Headlen; // Number of bytes in header
int Lrecl; // Logical Record Length
int Block; // Number of blocks in table
int Last; // Number of elements of last block
int Nrec; // Number of records in buffer
int OldBlk; // Index of last read block
int CurBlk; // Index of current block
int CurNum; // Current buffer line number
int ReadBlks; // Number of blocks read (selected)
int Rbuf; // Number of lines read in buffer
int Modif; // Number of modified lines in block
int Blksize; // Size of padded blocks
int Ending; // Length of line end
bool Padded; // true if fixed size blocks are padded
bool Eof; // true if an EOF (0xA) character exists
char *CrLf; // End of line character(s)
}; // end of class TXTFAM
/***********************************************************************/
/* This is the DOS/UNIX Access Method class declaration for standard */
/* text files with variable record format (DOS, CSV, FMT) */
/***********************************************************************/
class DllExport DOSFAM : public TXTFAM {
public:
// Constructor
DOSFAM(PDOSDEF tdp);
DOSFAM(PDOSFAM txfp);
// Implementation
virtual AMT GetAmType(void) {return TYPE_AM_DOS;}
virtual bool GetUseTemp(void) {return UseTemp;}
virtual int GetPos(void);
virtual int GetNextPos(void);
virtual PTXF Duplicate(PGLOBAL g)
{return (PTXF)new(g) DOSFAM(this);}
// Methods
virtual void Reset(void);
virtual int GetFileLength(PGLOBAL g);
virtual int Cardinality(PGLOBAL g);
virtual int MaxBlkSize(PGLOBAL g, int s);
virtual bool AllocateBuffer(PGLOBAL g);
virtual int GetRowID(void);
virtual bool RecordPos(PGLOBAL g);
virtual bool SetPos(PGLOBAL g, int recpos);
virtual int SkipRecord(PGLOBAL g, bool header);
virtual bool OpenTableFile(PGLOBAL g);
virtual int ReadBuffer(PGLOBAL g);
virtual int WriteBuffer(PGLOBAL g);
virtual int DeleteRecords(PGLOBAL g, int irc);
virtual void CloseTableFile(PGLOBAL g);
virtual void Rewind(void);
protected:
virtual bool OpenTempFile(PGLOBAL g);
virtual bool MoveIntermediateLines(PGLOBAL g, bool *b);
virtual int RenameTempFile(PGLOBAL g);
// Members
FILE *Stream; // Points to Dos file structure
FILE *T_Stream; // Points to temporary file structure
PFBLOCK To_Fbt; // Pointer to temp file block
int Fpos; // Position of last read record
int Tpos; // Target Position for delete move
int Spos; // Start position for delete move
bool UseTemp; // True to use a temporary file in Delete
bool Bin; // True to force binary mode
}; // end of class DOSFAM
/***********************************************************************/
/* This is the DOS/UNIX Access Method class declaration for standard */
/* text files with variable record format (DOS, CSV, FMT) */
/***********************************************************************/
class DllExport BLKFAM : public DOSFAM {
public:
// Constructor
BLKFAM(PDOSDEF tdp);
BLKFAM(PBLKFAM txfp);
// Implementation
virtual AMT GetAmType(void) {return TYPE_AM_BLK;}
virtual int GetPos(void);
virtual int GetNextPos(void);
virtual PTXF Duplicate(PGLOBAL g)
{return (PTXF)new(g) BLKFAM(this);}
// Methods
virtual void Reset(void);
virtual int Cardinality(PGLOBAL g);
virtual int MaxBlkSize(PGLOBAL g, int s);
virtual bool AllocateBuffer(PGLOBAL g);
virtual int GetRowID(void);
virtual bool RecordPos(PGLOBAL g);
virtual bool SetPos(PGLOBAL g, int recpos);
virtual int SkipRecord(PGLOBAL g, bool header);
virtual int ReadBuffer(PGLOBAL g);
virtual int WriteBuffer(PGLOBAL g);
virtual void CloseTableFile(PGLOBAL g);
virtual void Rewind(void);
protected:
// Members
char *CurLine; // Position of current line in buffer
char *NxtLine; // Position of Next line in buffer
char *OutBuf; // Buffer to write in temporary file
bool Closing; // True when closing on Update
}; // end of class BLKFAM
#endif // __FILAMTXT_H

4221
storage/connect/filamvct.cpp Normal file

File diff suppressed because it is too large Load Diff

249
storage/connect/filamvct.h Normal file
View File

@@ -0,0 +1,249 @@
/************** FilAMVct H Declares Source Code File (.H) **************/
/* Name: FILAMVCT.H Version 1.5 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 2005-2012 */
/* */
/* This file contains the VCT file access method classes declares. */
/***********************************************************************/
#ifndef __FILAMVCT__
#define __FILAMVCT__
#include "filamfix.h"
typedef class VCTFAM *PVCTFAM;
typedef class VCTCOL *PVCTCOL;
typedef class VCMFAM *PVCMFAM;
typedef class VECFAM *PVECFAM;
typedef class VMPFAM *PVMPFAM;
typedef class BGVFAM *PBGVFAM;
/***********************************************************************/
/* This is the DOS/UNIX Access Method class declaration for files */
/* in vector format. If MaxBlk=0, each block containing "Elements" */
/* records, values of each columns are consecutively stored (vector). */
/* Otherwise, data is arranged by column in the file and MaxBlk is */
/* used to set the maximum number of blocks. This leave some white */
/* space allowing to insert new values up to this maximum size. */
/***********************************************************************/
class DllExport VCTFAM : public FIXFAM {
friend class TDBVCT;
friend class VCTCOL;
public:
// Constructor
VCTFAM(PVCTDEF tdp);
VCTFAM(PVCTFAM txfp);
// Implementation
virtual AMT GetAmType(void) {return TYPE_AM_VCT;}
virtual PTXF Duplicate(PGLOBAL g)
{return (PTXF)new(g) VCTFAM(this);}
// Methods
virtual void Reset(void);
virtual int MaxBlkSize(PGLOBAL g, int s);
virtual bool AllocateBuffer(PGLOBAL g);
virtual bool InitInsert(PGLOBAL g);
virtual void ResetBuffer(PGLOBAL g) {}
virtual int Cardinality(PGLOBAL g);
virtual int GetRowID(void);
// Database routines
virtual bool OpenTableFile(PGLOBAL g);
virtual int ReadBuffer(PGLOBAL g);
virtual int WriteBuffer(PGLOBAL g);
virtual int DeleteRecords(PGLOBAL g, int irc);
virtual void CloseTableFile(PGLOBAL g);
virtual void Rewind(void);
// Specific functions
virtual bool ReadBlock(PGLOBAL g, PVCTCOL colp);
virtual bool WriteBlock(PGLOBAL g, PVCTCOL colp);
protected:
virtual bool MakeEmptyFile(PGLOBAL g, char *fn);
virtual bool OpenTempFile(PGLOBAL g);
virtual bool MoveLines(PGLOBAL g) {return false;}
virtual bool MoveIntermediateLines(PGLOBAL g, bool *b = NULL);
virtual bool CleanUnusedSpace(PGLOBAL g);
virtual int GetBlockInfo(PGLOBAL g);
virtual bool SetBlockInfo(PGLOBAL g);
bool ResetTableSize(PGLOBAL g, int block, int last);
// Members
char *NewBlock; // To block written on Insert
char *Colfn; // Pattern for column file names (VER)
char *Tempat; // Pattern for temp file names (VER)
int *Clens; // Pointer to col size array
int *Deplac; // Pointer to col start position array
bool *Isnum; // Pointer to buffer type isnum result
bool AddBlock; // True when adding new blocks on Insert
bool Split; // true: split column file vector format
int Header; // 0: no, 1: separate, 2: in data file
int MaxBlk; // Max number of blocks (True vector format)
int Bsize; // Because Nrec can be modified
int Ncol; // The number of columns;
}; // end of class VCTFAM
/***********************************************************************/
/* This is the DOS/UNIX Access Method class declaration for files */
/* in vector format accessed using file mapping. */
/***********************************************************************/
class DllExport VCMFAM : public VCTFAM {
friend class TDBVCT;
friend class VCTCOL;
public:
// Constructor
VCMFAM(PVCTDEF tdp);
VCMFAM(PVCMFAM txfp);
// Implementation
virtual AMT GetAmType(void) {return TYPE_AM_VMP;}
virtual PTXF Duplicate(PGLOBAL g)
{return (PTXF)new(g) VCMFAM(this);}
// Methods
virtual bool AllocateBuffer(PGLOBAL g);
virtual bool InitInsert(PGLOBAL g);
// Database routines
virtual bool OpenTableFile(PGLOBAL g);
virtual int WriteBuffer(PGLOBAL g);
virtual int DeleteRecords(PGLOBAL g, int irc);
virtual void CloseTableFile(PGLOBAL g);
// Specific functions
virtual bool ReadBlock(PGLOBAL g, PVCTCOL colp);
virtual bool WriteBlock(PGLOBAL g, PVCTCOL colp);
// Members
char* Memory; // Pointer on file mapping view.
char* *Memcol; // Pointer on column start.
}; // end of class VCMFAM
/***********************************************************************/
/* This is the DOS/UNIX Access Method class declaration for files */
/* in full vertical format. Each column is contained in a separate */
/* file whose name is the table name followed by the column number. */
/***********************************************************************/
class DllExport VECFAM : public VCTFAM {
friend class TDBVCT;
friend class VCTCOL;
public:
// Constructor
VECFAM(PVCTDEF tdp);
VECFAM(PVECFAM txfp);
// Implementation
virtual PTXF Duplicate(PGLOBAL g)
{return (PTXF)new(g) VECFAM(this);}
// Methods
virtual bool AllocateBuffer(PGLOBAL g);
virtual bool InitInsert(PGLOBAL g);
virtual void ResetBuffer(PGLOBAL g);
// Database routines
virtual bool OpenTableFile(PGLOBAL g);
virtual int WriteBuffer(PGLOBAL g);
virtual int DeleteRecords(PGLOBAL g, int irc);
virtual void CloseTableFile(PGLOBAL g);
// Specific functions
virtual bool ReadBlock(PGLOBAL g, PVCTCOL colp);
virtual bool WriteBlock(PGLOBAL g, PVCTCOL colp);
protected:
virtual bool OpenTempFile(PGLOBAL g);
virtual bool MoveLines(PGLOBAL g);
virtual bool MoveIntermediateLines(PGLOBAL g, bool *b = NULL);
virtual int RenameTempFile(PGLOBAL g);
bool OpenColumnFile(PGLOBAL g, char *opmode, int i);
// Members
FILE* *Streams; // Points to Dos file structure array
FILE* *T_Streams; // Points to temp file structure array
PFBLOCK *To_Fbs; // Pointer to file block array
PFBLOCK *T_Fbs; // Pointer to temp file block array
void* *To_Bufs; // Pointer to col val block array
bool InitUpdate; // Used to initialize updating
}; // end of class VECFAM
/***********************************************************************/
/* This is the DOS/UNIX Access Method class declaration for files */
/* in full vertical format accessed using file mapping. */
/***********************************************************************/
class DllExport VMPFAM : public VCMFAM {
friend class TDBVCT;
friend class VCTCOL;
public:
// Constructor
VMPFAM(PVCTDEF tdp);
VMPFAM(PVMPFAM txfp);
// Implementation
virtual PTXF Duplicate(PGLOBAL g)
{return (PTXF)new(g) VMPFAM(this);}
// Methods
virtual bool AllocateBuffer(PGLOBAL g);
// Database routines
virtual bool OpenTableFile(PGLOBAL g);
virtual int DeleteRecords(PGLOBAL g, int irc);
virtual void CloseTableFile(PGLOBAL g);
protected:
bool MapColumnFile(PGLOBAL g, MODE mode, int i);
// Members
PFBLOCK *To_Fbs; // Pointer to file block array
}; // end of class VMPFAM
/***********************************************************************/
/* This is the DOS/UNIX Access Method class declaration for files */
/* in (possibly blocked) vector format that can be larger than 2GB. */
/***********************************************************************/
class BGVFAM : public VCTFAM {
friend class VCTCOL;
public:
// Constructors
BGVFAM(PVCTDEF tdp);
BGVFAM(PBGVFAM txfp);
// Implementation
virtual PTXF Duplicate(PGLOBAL g)
{return (PTXF)new(g) BGVFAM(this);}
// Methods
virtual bool AllocateBuffer(PGLOBAL g);
// Database routines
virtual bool OpenTableFile(PGLOBAL g);
virtual int WriteBuffer(PGLOBAL g);
virtual int DeleteRecords(PGLOBAL g, int irc);
virtual void CloseTableFile(PGLOBAL g);
virtual void Rewind(void);
// Specific functions
virtual bool ReadBlock(PGLOBAL g, PVCTCOL colp);
virtual bool WriteBlock(PGLOBAL g, PVCTCOL colp);
protected:
bool BigSeek(PGLOBAL g, HANDLE h, BIGINT pos, bool b = false);
bool BigRead(PGLOBAL g, HANDLE h, void *inbuf, int req);
bool BigWrite(PGLOBAL g, HANDLE h, void *inbuf, int req);
virtual bool MakeEmptyFile(PGLOBAL g, char *fn);
virtual bool OpenTempFile(PGLOBAL g);
virtual bool MoveIntermediateLines(PGLOBAL g, bool *b = NULL);
virtual bool CleanUnusedSpace(PGLOBAL g);
virtual bool SetBlockInfo(PGLOBAL g);
virtual int GetBlockInfo(PGLOBAL g);
// Members
HANDLE Hfile; // Handle to big file
HANDLE Tfile; // Handle to temporary file
BIGINT *BigDep; // Pointer to col start position array
}; // end of class BGVFAM
#endif // __FILAMVCT__

View File

@@ -0,0 +1,822 @@
/*********** File AM Zip C++ Program Source Code File (.CPP) ***********/
/* PROGRAM NAME: FILAMZIP */
/* ------------- */
/* Version 1.4 */
/* */
/* COPYRIGHT: */
/* ---------- */
/* (C) Copyright to the author Olivier BERTRAND 2005-2013 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
/* This program are the ZLIB compressed files classes. */
/* */
/***********************************************************************/
/***********************************************************************/
/* Include relevant MariaDB header file. */
/***********************************************************************/
#include "my_global.h"
#if defined(WIN32)
#include <io.h>
#include <fcntl.h>
#if defined(__BORLANDC__)
#define __MFC_COMPAT__ // To define min/max as macro
#endif
//#include <windows.h>
#else // !WIN32
#if defined(UNIX)
#include <errno.h>
#else // !UNIX
#include <io.h>
#endif
#include <fcntl.h>
#endif // !WIN32
/***********************************************************************/
/* Include application header files: */
/* global.h is header containing all global declarations. */
/* plgdbsem.h is header containing the DB application declarations. */
/* tabdos.h is header containing the TABDOS class declarations. */
/***********************************************************************/
#include "global.h"
#include "plgdbsem.h"
//#include "catalog.h"
//#include "reldef.h"
//#include "xobject.h"
//#include "kindex.h"
#include "filamtxt.h"
#include "tabdos.h"
#if defined(UNIX)
#include "osutil.h"
#endif
/***********************************************************************/
/* This define prepares ZLIB function declarations. */
/***********************************************************************/
//#define ZLIB_DLL
#include "filamzip.h"
/***********************************************************************/
/* DB static variables. */
/***********************************************************************/
extern int num_read, num_there, num_eq[]; // Statistics
bool PushWarning(PGLOBAL g, PTDBASE tdbp);
/* ------------------------------------------------------------------- */
/***********************************************************************/
/* Implementation of the ZIPFAM class. */
/***********************************************************************/
ZIPFAM::ZIPFAM(PZIPFAM txfp) : TXTFAM(txfp)
{
Zfile = txfp->Zfile;
Zpos = txfp->Zpos;
} // end of ZIPFAM copy constructor
/***********************************************************************/
/* Zerror: Error function for gz calls. */
/* gzerror returns the error message for the last error which occurred*/
/* on the given compressed file. errnum is set to zlib error number. */
/* If an error occurred in the file system and not in the compression */
/* library, errnum is set to Z_ERRNO and the application may consult */
/* errno to get the exact error code. */
/***********************************************************************/
int ZIPFAM::Zerror(PGLOBAL g)
{
int errnum;
strcpy(g->Message, gzerror(Zfile, &errnum));
if (errnum == Z_ERRNO)
#if defined(WIN32)
sprintf(g->Message, MSG(READ_ERROR), To_File, strerror(NULL));
#else // !WIN32
sprintf(g->Message, MSG(READ_ERROR), To_File, strerror(errno));
#endif // !WIN32
return (errnum == Z_STREAM_END) ? RC_EF : RC_FX;
} // end of Zerror
/***********************************************************************/
/* Reset: reset position values at the beginning of file. */
/***********************************************************************/
void ZIPFAM::Reset(void)
{
TXTFAM::Reset();
//gzrewind(Zfile); // Useful ?????
Zpos = 0;
} // end of Reset
/***********************************************************************/
/* ZIP GetFileLength: returns an estimate of what would be the */
/* uncompressed file size in number of bytes. */
/***********************************************************************/
int ZIPFAM::GetFileLength(PGLOBAL g)
{
int len = TXTFAM::GetFileLength(g);
if (len > 0)
// Estimate size reduction to a max of 6
len *= 6;
return len;
} // end of GetFileLength
/***********************************************************************/
/* ZIP Access Method opening routine. */
/***********************************************************************/
bool ZIPFAM::OpenTableFile(PGLOBAL g)
{
char opmode[4], filename[_MAX_PATH];
MODE mode = Tdbp->GetMode();
switch (mode) {
case MODE_READ:
strcpy(opmode, "r");
break;
case MODE_UPDATE:
/*****************************************************************/
/* Updating ZIP files not implemented yet. */
/*****************************************************************/
strcpy(g->Message, MSG(UPD_ZIP_NOT_IMP));
return true;
case MODE_DELETE:
if (!Tdbp->GetNext()) {
// Store the number of deleted lines
DelRows = Cardinality(g);
// This will erase the entire file
strcpy(opmode, "w");
// Block = 0; // For ZBKFAM
// Last = Nrec; // For ZBKFAM
Tdbp->ResetSize();
} else {
sprintf(g->Message, MSG(NO_PART_DEL), "ZIP");
return true;
} // endif filter
break;
case MODE_INSERT:
strcpy(opmode, "a+");
break;
default:
sprintf(g->Message, MSG(BAD_OPEN_MODE), mode);
return true;
} // endswitch Mode
/*********************************************************************/
/* Open according to logical input/output mode required. */
/* Use specific zlib functions. */
/* Treat files as binary. */
/*********************************************************************/
strcat(opmode, "b");
Zfile = gzopen(PlugSetPath(filename, To_File, Tdbp->GetPath()), opmode);
if (Zfile == NULL) {
sprintf(g->Message, MSG(GZOPEN_ERROR),
opmode, (int)errno, filename);
strcat(strcat(g->Message, ": "), strerror(errno));
return (mode == MODE_READ && errno == ENOENT)
? PushWarning(g, Tdbp) : true;
} // endif Zfile
/*********************************************************************/
/* Something to be done here. >>>>>>>> NOT DONE <<<<<<<< */
/*********************************************************************/
//To_Fb = dbuserp->Openlist; // Keep track of File block
/*********************************************************************/
/* Allocate the line buffer. */
/*********************************************************************/
return AllocateBuffer(g);
} // end of OpenTableFile
/***********************************************************************/
/* Allocate the line buffer. For mode Delete a bigger buffer has to */
/* be allocated because is it also used to move lines into the file. */
/***********************************************************************/
bool ZIPFAM::AllocateBuffer(PGLOBAL g)
{
MODE mode = Tdbp->GetMode();
Buflen = Lrecl + 2; // Lrecl does not include CRLF
//Buflen *= ((Mode == MODE_DELETE) ? DOS_BUFF_LEN : 1); NIY
#ifdef DEBTRACE
htrc("SubAllocating a buffer of %d bytes\n", Buflen);
#endif
To_Buf = (char*)PlugSubAlloc(g, NULL, Buflen);
if (mode == MODE_INSERT) {
/*******************************************************************/
/* For Insert buffer must be prepared. */
/*******************************************************************/
memset(To_Buf, ' ', Buflen);
To_Buf[Buflen - 2] = '\n';
To_Buf[Buflen - 1] = '\0';
} // endif Insert
return false;
} // end of AllocateBuffer
/***********************************************************************/
/* GetRowID: return the RowID of last read record. */
/***********************************************************************/
int ZIPFAM::GetRowID(void)
{
return Rows;
} // end of GetRowID
/***********************************************************************/
/* GetPos: return the position of last read record. */
/***********************************************************************/
int ZIPFAM::GetPos(void)
{
return (int)Zpos;
} // end of GetPos
/***********************************************************************/
/* GetNextPos: return the position of next record. */
/***********************************************************************/
int ZIPFAM::GetNextPos(void)
{
return gztell(Zfile);
} // end of GetNextPos
/***********************************************************************/
/* SetPos: Replace the table at the specified position. */
/***********************************************************************/
bool ZIPFAM::SetPos(PGLOBAL g, int pos)
{
sprintf(g->Message, MSG(NO_SETPOS_YET), "ZIP");
return true;
#if 0
Fpos = pos;
if (fseek(Stream, Fpos, SEEK_SET)) {
sprintf(g->Message, MSG(FSETPOS_ERROR), Fpos);
return true;
} // endif
Placed = true;
return false;
#endif // 0
} // end of SetPos
/***********************************************************************/
/* Record file position in case of UPDATE or DELETE. */
/***********************************************************************/
bool ZIPFAM::RecordPos(PGLOBAL g)
{
Zpos = gztell(Zfile);
return false;
} // end of RecordPos
/***********************************************************************/
/* Skip one record in file. */
/***********************************************************************/
int ZIPFAM::SkipRecord(PGLOBAL g, bool header)
{
// Skip this record
if (gzeof(Zfile))
return RC_EF;
else if (gzgets(Zfile, To_Buf, Buflen) == Z_NULL)
return Zerror(g);
if (header)
RecordPos(g);
return RC_OK;
} // end of SkipRecord
/***********************************************************************/
/* ReadBuffer: Read one line from a compressed text file. */
/***********************************************************************/
int ZIPFAM::ReadBuffer(PGLOBAL g)
{
char *p;
int rc;
if (!Zfile)
return RC_EF;
if (!Placed) {
/*******************************************************************/
/* Record file position in case of UPDATE or DELETE. */
/*******************************************************************/
if (RecordPos(g))
return RC_FX;
CurBlk = Rows++; // Update RowID
} else
Placed = false;
if (gzeof(Zfile)) {
rc = RC_EF;
} else if (gzgets(Zfile, To_Buf, Buflen) != Z_NULL) {
p = To_Buf + strlen(To_Buf) - 1;
if (*p == '\n')
*p = '\0'; // Eliminate ending new-line character
if (*(--p) == '\r')
*p = '\0'; // Eliminate eventuel carriage return
strcpy(Tdbp->GetLine(), To_Buf);
IsRead = true;
rc = RC_OK;
num_read++;
} else
rc = Zerror(g);
#ifdef DEBTRACE
htrc(" Read: '%s' rc=%d\n", To_Buf, rc);
#endif
return rc;
} // end of ReadBuffer
/***********************************************************************/
/* WriteDB: Data Base write routine for ZDOS access method. */
/* Update is not possible without using a temporary file (NIY). */
/***********************************************************************/
int ZIPFAM::WriteBuffer(PGLOBAL g)
{
/*********************************************************************/
/* Prepare the write buffer. */
/*********************************************************************/
strcat(strcpy(To_Buf, Tdbp->GetLine()), CrLf);
/*********************************************************************/
/* Now start the writing process. */
/*********************************************************************/
if (gzputs(Zfile, To_Buf) < 0)
return Zerror(g);
return RC_OK;
} // end of WriteBuffer
/***********************************************************************/
/* Data Base delete line routine for ZDOS access method. (NIY) */
/***********************************************************************/
int ZIPFAM::DeleteRecords(PGLOBAL g, int irc)
{
strcpy(g->Message, MSG(NO_ZIP_DELETE));
return RC_FX;
} // end of DeleteRecords
/***********************************************************************/
/* Data Base close routine for DOS access method. */
/***********************************************************************/
void ZIPFAM::CloseTableFile(PGLOBAL g)
{
int rc = gzclose(Zfile);
#ifdef DEBTRACE
htrc("ZIP CloseDB: closing %s rc=%d\n", To_File, rc);
#endif
Zfile = NULL; // So we can know whether table is open
//To_Fb->Count = 0; // Avoid double closing by PlugCloseAll
} // end of CloseTableFile
/***********************************************************************/
/* Rewind routine for ZIP access method. */
/***********************************************************************/
void ZIPFAM::Rewind(void)
{
gzrewind(Zfile);
} // end of Rewind
/* ------------------------------------------------------------------- */
/***********************************************************************/
/* Constructors. */
/***********************************************************************/
ZBKFAM::ZBKFAM(PDOSDEF tdp) : ZIPFAM(tdp)
{
Blocked = true;
Block = tdp->GetBlock();
Last = tdp->GetLast();
Nrec = tdp->GetElemt();
CurLine = NULL;
NxtLine = NULL;
Closing = false;
BlkPos = tdp->GetTo_Pos();
} // end of ZBKFAM standard constructor
ZBKFAM::ZBKFAM(PZBKFAM txfp) : ZIPFAM(txfp)
{
CurLine = txfp->CurLine;
NxtLine = txfp->NxtLine;
Closing = txfp->Closing;
} // end of ZBKFAM copy constructor
/***********************************************************************/
/* Use BlockTest to reduce the table estimated size. */
/***********************************************************************/
int ZBKFAM::MaxBlkSize(PGLOBAL g, int s)
{
int savcur = CurBlk;
int size;
// Roughly estimate the table size as the sum of blocks
// that can contain good rows
for (size = 0, CurBlk = 0; CurBlk < Block; CurBlk++)
size += (CurBlk == Block - 1) ? Last : Nrec;
CurBlk = savcur;
return size;
} // end of MaxBlkSize
/***********************************************************************/
/* ZBK Cardinality: returns table cardinality in number of rows. */
/* This function can be called with a null argument to test the */
/* availability of Cardinality implementation (1 yes, 0 no). */
/***********************************************************************/
int ZBKFAM::Cardinality(PGLOBAL g)
{
// Should not be called in this version
return (g) ? -1 : 0;
//return (g) ? (int)((Block - 1) * Nrec + Last) : 1;
} // end of Cardinality
/***********************************************************************/
/* Allocate the line buffer. For mode Delete a bigger buffer has to */
/* be allocated because is it also used to move lines into the file. */
/***********************************************************************/
bool ZBKFAM::AllocateBuffer(PGLOBAL g)
{
Buflen = Nrec * (Lrecl + 2);
CurLine = To_Buf = (char*)PlugSubAlloc(g, NULL, Buflen);
if (Tdbp->GetMode() == MODE_INSERT) {
// Set values so Block and Last can be recalculated
if (Last == Nrec) {
CurBlk = Block;
Rbuf = Nrec; // To be used by WriteDB
} else {
// The last block must be completed
CurBlk = Block - 1;
Rbuf = Nrec - Last; // To be used by WriteDB
} // endif Last
} // endif Insert
return false;
} // end of AllocateBuffer
/***********************************************************************/
/* GetRowID: return the RowID of last read record. */
/***********************************************************************/
int ZBKFAM::GetRowID(void)
{
return CurNum + Nrec * CurBlk + 1;
} // end of GetRowID
/***********************************************************************/
/* GetPos: return the position of last read record. */
/***********************************************************************/
int ZBKFAM::GetPos(void)
{
return CurNum + Nrec * CurBlk; // Computed file index
} // end of GetPos
/***********************************************************************/
/* Record file position in case of UPDATE or DELETE. */
/* Not used yet for fixed tables. */
/***********************************************************************/
bool ZBKFAM::RecordPos(PGLOBAL g)
{
//strcpy(g->Message, "RecordPos not implemented for zip blocked tables");
//return true;
return RC_OK;
} // end of RecordPos
/***********************************************************************/
/* Skip one record in file. */
/***********************************************************************/
int ZBKFAM::SkipRecord(PGLOBAL g, bool header)
{
//strcpy(g->Message, "SkipRecord not implemented for zip blocked tables");
//return RC_FX;
return RC_OK;
} // end of SkipRecord
/***********************************************************************/
/* ReadBuffer: Read one line from a compressed text file. */
/***********************************************************************/
int ZBKFAM::ReadBuffer(PGLOBAL g)
{
int n, rc = RC_OK;
/*********************************************************************/
/* Sequential reading when Placed is not true. */
/*********************************************************************/
if (++CurNum < Rbuf) {
CurLine = NxtLine;
// Get the position of the next line in the buffer
while (*NxtLine++ != '\n') ;
// Set caller line buffer
n = NxtLine - CurLine - Ending;
memcpy(Tdbp->GetLine(), CurLine, n);
Tdbp->GetLine()[n] = '\0';
return RC_OK;
} else if (Rbuf < Nrec && CurBlk != -1)
return RC_EF;
/*********************************************************************/
/* New block. */
/*********************************************************************/
CurNum = 0;
if (++CurBlk >= Block)
return RC_EF;
BlkLen = BlkPos[CurBlk + 1] - BlkPos[CurBlk];
if (!(n = gzread(Zfile, To_Buf, BlkLen))) {
rc = RC_EF;
} else if (n > 0) {
// Get the position of the current line
CurLine = To_Buf;
// Now get the position of the next line
for (NxtLine = CurLine; *NxtLine++ != '\n';) ;
// Set caller line buffer
n = NxtLine - CurLine - Ending;
memcpy(Tdbp->GetLine(), CurLine, n);
Tdbp->GetLine()[n] = '\0';
Rbuf = (CurBlk == Block - 1) ? Last : Nrec;
IsRead = true;
rc = RC_OK;
num_read++;
} else
rc = Zerror(g);
return rc;
} // end of ReadBuffer
/***********************************************************************/
/* WriteDB: Data Base write routine for ZDOS access method. */
/* Update is not possible without using a temporary file (NIY). */
/***********************************************************************/
int ZBKFAM::WriteBuffer(PGLOBAL g)
{
/*********************************************************************/
/* Prepare the write buffer. */
/*********************************************************************/
if (!Closing)
strcat(strcpy(CurLine, Tdbp->GetLine()), CrLf);
/*********************************************************************/
/* In Insert mode, blocs are added sequentialy to the file end. */
/* Note: Update mode is not handled for zip files. */
/*********************************************************************/
if (++CurNum == Rbuf) {
/*******************************************************************/
/* New block, start the writing process. */
/*******************************************************************/
BlkLen = CurLine + strlen(CurLine) - To_Buf;
if (gzwrite(Zfile, To_Buf, BlkLen) != BlkLen ||
gzflush(Zfile, Z_FULL_FLUSH)) {
Closing = true;
return Zerror(g);
} // endif gzwrite
Rbuf = Nrec;
CurBlk++;
CurNum = 0;
CurLine = To_Buf;
} else
CurLine += strlen(CurLine);
return RC_OK;
} // end of WriteBuffer
/***********************************************************************/
/* Data Base delete line routine for ZBK access method. */
/* Implemented only for total deletion of the table, which is done */
/* by opening the file in mode "wb". */
/***********************************************************************/
int ZBKFAM::DeleteRecords(PGLOBAL g, int irc)
{
if (irc == RC_EF) {
LPCSTR name = Tdbp->GetName();
PDOSDEF defp = (PDOSDEF)Tdbp->GetDef();
PCATLG cat = PlgGetCatalog(g);
defp->SetBlock(0);
defp->SetLast(Nrec);
if (!cat->SetIntCatInfo(name, "Blocks", 0) ||
!cat->SetIntCatInfo(name, "Last", 0)) {
sprintf(g->Message, MSG(UPDATE_ERROR), "Header");
return RC_FX;
} else
return RC_OK;
} else
return irc;
} // end of DeleteRecords
/***********************************************************************/
/* Data Base close routine for ZBK access method. */
/***********************************************************************/
void ZBKFAM::CloseTableFile(PGLOBAL g)
{
int rc = RC_OK;
if (Tdbp->GetMode() == MODE_INSERT) {
PCATLG cat = PlgGetCatalog(g);
LPCSTR name = Tdbp->GetName();
PDOSDEF defp = (PDOSDEF)Tdbp->GetDef();
if (CurNum && !Closing) {
// Some more inserted lines remain to be written
Last = (Nrec - Rbuf) + CurNum;
Block = CurBlk + 1;
Rbuf = CurNum--;
Closing = true;
rc = WriteBuffer(g);
} else if (Rbuf == Nrec) {
Last = Nrec;
Block = CurBlk;
} // endif CurNum
if (rc != RC_FX) {
defp->SetBlock(Block);
defp->SetLast(Last);
cat->SetIntCatInfo(name, "Blocks", Block);
cat->SetIntCatInfo(name, "Last", Last);
} // endif
gzclose(Zfile);
} else if (Tdbp->GetMode() == MODE_DELETE) {
rc = DeleteRecords(g, RC_EF);
gzclose(Zfile);
} else
rc = gzclose(Zfile);
#ifdef DEBTRACE
htrc("ZIP CloseDB: closing %s rc=%d\n", To_File, rc);
#endif
Zfile = NULL; // So we can know whether table is open
//To_Fb->Count = 0; // Avoid double closing by PlugCloseAll
} // end of CloseTableFile
/***********************************************************************/
/* Rewind routine for ZBK access method. */
/***********************************************************************/
void ZBKFAM::Rewind(void)
{
gzrewind(Zfile);
CurBlk = -1;
CurNum = Rbuf;
} // end of Rewind
/* ------------------------------------------------------------------- */
/***********************************************************************/
/* Constructors. */
/***********************************************************************/
ZIXFAM::ZIXFAM(PDOSDEF tdp) : ZBKFAM(tdp)
{
//Block = tdp->GetBlock();
//Last = tdp->GetLast();
Nrec = (tdp->GetElemt()) ? tdp->GetElemt() : DOS_BUFF_LEN;
Blksize = Nrec * Lrecl;
} // end of ZIXFAM standard constructor
/***********************************************************************/
/* ZIX Cardinality: returns table cardinality in number of rows. */
/* This function can be called with a null argument to test the */
/* availability of Cardinality implementation (1 yes, 0 no). */
/***********************************************************************/
int ZIXFAM::Cardinality(PGLOBAL g)
{
if (Last)
return (g) ? (int)((Block - 1) * Nrec + Last) : 1;
else // Last and Block not defined, cannot do it yet
return 0;
} // end of Cardinality
/***********************************************************************/
/* Allocate the line buffer. For mode Delete a bigger buffer has to */
/* be allocated because is it also used to move lines into the file. */
/***********************************************************************/
bool ZIXFAM::AllocateBuffer(PGLOBAL g)
{
Buflen = Blksize;
To_Buf = (char*)PlugSubAlloc(g, NULL, Buflen);
if (Tdbp->GetMode() == MODE_INSERT) {
/*******************************************************************/
/* For Insert the buffer must be prepared. */
/*******************************************************************/
memset(To_Buf, ' ', Buflen);
if (Tdbp->GetFtype() < 2)
// if not binary, the file is physically a text file
for (int len = Lrecl; len <= Buflen; len += Lrecl) {
#if defined(WIN32)
To_Buf[len - 2] = '\r';
#endif // WIN32
To_Buf[len - 1] = '\n';
} // endfor len
// Set values so Block and Last can be recalculated
if (Last == Nrec) {
CurBlk = Block;
Rbuf = Nrec; // To be used by WriteDB
} else {
// The last block must be completed
CurBlk = Block - 1;
Rbuf = Nrec - Last; // To be used by WriteDB
} // endif Last
} // endif Insert
return false;
} // end of AllocateBuffer
/***********************************************************************/
/* ReadBuffer: Read one line from a compressed text file. */
/***********************************************************************/
int ZIXFAM::ReadBuffer(PGLOBAL g)
{
int n, rc = RC_OK;
/*********************************************************************/
/* Sequential reading when Placed is not true. */
/*********************************************************************/
if (++CurNum < Rbuf) {
Tdbp->IncLine(Lrecl); // Used by DOSCOL functions
return RC_OK;
} else if (Rbuf < Nrec && CurBlk != -1)
return RC_EF;
/*********************************************************************/
/* New block. */
/*********************************************************************/
CurNum = 0;
Tdbp->SetLine(To_Buf);
//if (++CurBlk >= Block)
// return RC_EF;
if (!(n = gzread(Zfile, To_Buf, Buflen))) {
rc = RC_EF;
} else if (n > 0) {
Rbuf = n / Lrecl;
IsRead = true;
rc = RC_OK;
num_read++;
} else
rc = Zerror(g);
return rc;
} // end of ReadBuffer
/***********************************************************************/
/* WriteDB: Data Base write routine for ZDOS access method. */
/* Update is not possible without using a temporary file (NIY). */
/***********************************************************************/
int ZIXFAM::WriteBuffer(PGLOBAL g)
{
/*********************************************************************/
/* In Insert mode, blocs are added sequentialy to the file end. */
/* Note: Update mode is not handled for zip files. */
/*********************************************************************/
if (++CurNum == Rbuf) {
/*******************************************************************/
/* New block, start the writing process. */
/*******************************************************************/
BlkLen = Rbuf * Lrecl;
if (gzwrite(Zfile, To_Buf, BlkLen) != BlkLen ||
gzflush(Zfile, Z_FULL_FLUSH)) {
Closing = true;
return Zerror(g);
} // endif gzwrite
Rbuf = Nrec;
CurBlk++;
CurNum = 0;
Tdbp->SetLine(To_Buf);
} else
Tdbp->IncLine(Lrecl); // Used by FIXCOL functions
return RC_OK;
} // end of WriteBuffer
/* ------------------------ End of ZipFam ---------------------------- */

174
storage/connect/filamzip.h Normal file
View File

@@ -0,0 +1,174 @@
/************** FilAmZip H Declares Source Code File (.H) **************/
/* Name: FILAMZIP.H Version 1.1 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 2005-2012 */
/* */
/* This file contains the GZIP access method classes declares. */
/***********************************************************************/
#ifndef __FILAMZIP_H
#define __FILAMZIP_H
#include "zlib.h"
#define TYPE_AM_ZIP (AMT)150
#define TYPE_AM_ZLIB (AMT)155
typedef class ZIPFAM *PZIPFAM;
typedef class ZBKFAM *PZBKFAM;
typedef class ZIXFAM *PZIXFAM;
typedef class ZLBFAM *PZLBFAM;
/***********************************************************************/
/* This is the access method class declaration for not optimized */
/* variable record length files compressed using the gzip library */
/* functions. File is accessed record by record (row). */
/***********************************************************************/
class DllExport ZIPFAM : public TXTFAM {
// friend class DOSCOL;
public:
// Constructor
ZIPFAM(PDOSDEF tdp) : TXTFAM(tdp) {Zfile = NULL; Zpos = 0;}
ZIPFAM(PZIPFAM txfp);
// Implementation
virtual AMT GetAmType(void) {return TYPE_AM_ZIP;}
virtual int GetPos(void);
virtual int GetNextPos(void);
virtual PTXF Duplicate(PGLOBAL g)
{return (PTXF)new(g) ZIPFAM(this);}
// Methods
virtual void Reset(void);
virtual int GetFileLength(PGLOBAL g);
virtual int Cardinality(PGLOBAL g) {return (g) ? -1 : 0;}
virtual int MaxBlkSize(PGLOBAL g, int s) {return s;}
virtual bool AllocateBuffer(PGLOBAL g);
virtual int GetRowID(void);
virtual bool RecordPos(PGLOBAL g);
virtual bool SetPos(PGLOBAL g, int recpos);
virtual int SkipRecord(PGLOBAL g, bool header);
virtual bool OpenTableFile(PGLOBAL g);
virtual int ReadBuffer(PGLOBAL g);
virtual int WriteBuffer(PGLOBAL g);
virtual int DeleteRecords(PGLOBAL g, int irc);
virtual void CloseTableFile(PGLOBAL g);
virtual void Rewind(void);
protected:
int Zerror(PGLOBAL g); // GZ error function
// Members
gzFile Zfile; // Points to GZ file structure
z_off_t Zpos; // Uncompressed file position
}; // end of class ZIPFAM
/***********************************************************************/
/* This is the access method class declaration for optimized variable */
/* record length files compressed using the gzip library functions. */
/* The File is accessed by block (requires an opt file). */
/***********************************************************************/
class DllExport ZBKFAM : public ZIPFAM {
public:
// Constructor
ZBKFAM(PDOSDEF tdp);
ZBKFAM(PZBKFAM txfp);
// Implementation
virtual int GetPos(void);
virtual int GetNextPos(void) {return 0;}
virtual PTXF Duplicate(PGLOBAL g)
{return (PTXF)new(g) ZBKFAM(this);}
// Methods
virtual int Cardinality(PGLOBAL g);
virtual int MaxBlkSize(PGLOBAL g, int s);
virtual bool AllocateBuffer(PGLOBAL g);
virtual int GetRowID(void);
virtual bool RecordPos(PGLOBAL g);
virtual int SkipRecord(PGLOBAL g, bool header);
virtual int ReadBuffer(PGLOBAL g);
virtual int WriteBuffer(PGLOBAL g);
virtual int DeleteRecords(PGLOBAL g, int irc);
virtual void CloseTableFile(PGLOBAL g);
virtual void Rewind(void);
protected:
// Members
char *CurLine; // Position of current line in buffer
char *NxtLine; // Position of Next line in buffer
bool Closing; // True when closing on Insert
}; // end of class ZBKFAM
/***********************************************************************/
/* This is the access method class declaration for fixed record */
/* length files compressed using the gzip library functions. */
/* The file is always accessed by block. */
/***********************************************************************/
class DllExport ZIXFAM : public ZBKFAM {
public:
// Constructor
ZIXFAM(PDOSDEF tdp);
ZIXFAM(PZIXFAM txfp) : ZBKFAM(txfp) {}
// Implementation
virtual int GetNextPos(void) {return 0;}
virtual PTXF Duplicate(PGLOBAL g)
{return (PTXF)new(g) ZIXFAM(this);}
// Methods
virtual int Cardinality(PGLOBAL g);
virtual bool AllocateBuffer(PGLOBAL g);
virtual int ReadBuffer(PGLOBAL g);
virtual int WriteBuffer(PGLOBAL g);
protected:
// No additional Members
}; // end of class ZIXFAM
#ifdef NOT_USED
/***********************************************************************/
/* This is the DOS/UNIX Access Method class declaration for PlugDB */
/* fixed/variable files compressed using the zlib library functions. */
/* Physically these are written and read using the same technique */
/* than blocked variable files, only the contain of each block is */
/* compressed using the deflate zlib function. The purpose of this */
/* specific format is to have a fast mechanism for direct access of */
/* records so blocked optimization is fast and direct access (joins) */
/* is allowed. Note that the block length is written ahead of each */
/* block to enable reading when optimization file is not available. */
/***********************************************************************/
class DllExport ZLBFAM : public BLKFAM {
public:
// Constructor
ZLBFAM(PDOSDEF tdp);
ZLBFAM(PZLBFAM txfp);
// Implementation
virtual AMT GetAmType(void) {return TYPE_AM_ZLIB;}
virtual int GetPos(void);
virtual int GetNextPos(void);
virtual PTXF Duplicate(PGLOBAL g)
{return (PTXF)new(g) ZLBFAM(this);}
inline void SetOptimized(bool b) {Optimized = b;}
// Methods
virtual int GetFileLength(PGLOBAL g);
virtual bool AllocateBuffer(PGLOBAL g);
virtual int ReadBuffer(PGLOBAL g);
virtual int WriteBuffer(PGLOBAL g);
virtual void CloseTableFile(PGLOBAL g);
virtual void Rewind(void);
protected:
bool WriteCompressedBuffer(PGLOBAL g);
int ReadCompressedBuffer(PGLOBAL g, void *rdbuf);
// Members
z_streamp Zstream; // Compression/decompression stream
Byte *Zbuffer; // Compressed block buffer
int *Zlenp; // Pointer to block length
bool Optimized; // true when opt file is available
}; // end of class ZLBFAM
#endif // NOT_USED
#endif // __FILAMZIP_H

1522
storage/connect/fmdlex.c Normal file

File diff suppressed because it is too large Load Diff

1013
storage/connect/frmsg1.h Normal file

File diff suppressed because it is too large Load Diff

1013
storage/connect/frmsg2.h Normal file

File diff suppressed because it is too large Load Diff

273
storage/connect/global.h Normal file
View File

@@ -0,0 +1,273 @@
/***********************************************************************/
/* GLOBAL.H: Declaration file used by all CONNECT implementations. */
/* (C) Copyright Olivier Bertrand 1993-2012 */
/***********************************************************************/
/***********************************************************************/
/* Included C-definition files common to all Plug routines */
/***********************************************************************/
#include <string.h> /* String manipulation declares */
#include <stdlib.h> /* C standard library */
#include <ctype.h> /* C language specific types */
#include <stdio.h> /* FOPEN_MAX declaration */
#include <time.h> /* time_t type declaration */
#include <setjmp.h> /* Long jump declarations */
#if defined(WIN32) && !defined(NOEX)
#define DllExport __declspec( dllexport )
#else // !WIN32
#define DllExport
#endif // !WIN32
#if defined(XMSG)
// Definition used to read messages from message file.
#include "msgid.h"
#define MSG(I) PlugReadMessage(NULL, MSG_##I, #I)
#define STEP(I) PlugReadMessage(g, MSG_##I, #I)
#elif defined(NEWMSG)
// Definition used to get messages from resource.
#include "msgid.h"
#define MSG(I) PlugGetMessage(NULL, MSG_##I)
#define STEP(I) PlugGetMessage(g, MSG_##I)
#else // !XMSG and !NEWMSG
// Definition used to replace messages ID's by their definition.
#include "messages.h"
#define MSG(I) MSG_##I
#define STEP(I) MSG_##I
#endif // !XMSG and !NEWMSG
#if defined(WIN32)
#define CRLF 2
#else // !WIN32
#define CRLF 1
#define BOOL my_bool
#endif // !WIN32
/***********************************************************************/
/* Miscellaneous Constants */
/***********************************************************************/
#define NO_IVAL -95684275 /* Used by GetIntegerOption */
#define VMLANG 370 /* Size of olf VM lang blocks */
#define MAX_JUMP 24 /* Maximum jump level number */
#define MAX_STR 1024 /* Maximum string length */
#define STR_SIZE 501 /* Length of char strings. */
#define STD_INPUT 0 /* Standard language input */
#define STD_OUTPUT 1 /* Standard language output */
#define ERROR_OUTPUT 2 /* Error message output */
#define DEBUG_OUTPUT 3 /* Debug info output */
#define PROMPT_OUTPUT 4 /* Prompt message output */
#define COPY_OUTPUT 5 /* Copy of language input */
#define STD_MSG 6 /* System message file */
#define DEBUG_MSG 7 /* Debug message file */
#define DUMMY 0 /* Dummy file index in Ldm block */
#define STDIN 1 /* stdin file index in Ldm block */
#define STDOUT 2 /* stdout file index in Ldm block */
#define STDERR 3 /* stderr file index in Ldm block */
#define STDEBUG 4 /* debug file index in Ldm block */
#define STDPRN 5 /* stdprn file index in Ldm block */
#define STDFREE 6 /* Free file index in Ldm block */
#define TYPE_SEM -2 /* Returned semantic function */
#define TYPE_DFONC -2 /* Indirect sem ref in FPARM */
#define TYPE_VOID -1
#define TYPE_SBPAR -1 /* Phrase reference in FPARM */
#define TYPE_SEMX 0 /* Initial semantic function type? */
#define TYPE_ERROR 0
#define TYPE_STRING 1
#define TYPE_FLOAT 2
#define TYPE_SHORT 3
#define TYPE_LIST 6
#define TYPE_INT 7
#if defined(OS32)
#define SYS_STAMP "OS32"
#elif defined(UNIX) || defined(LINUX) || defined(UNIV_LINUX)
#define SYS_STAMP "UNIX"
#elif defined(OS16)
#define SYS_STAMP "OS16"
#elif defined(DOSR)
#define SYS_STAMP "DOSR"
#elif defined(WIN)
#define SYS_STAMP "WIN1"
#elif defined(WIN32)
#define SYS_STAMP "WIN2"
#else
#define SYS_STAMP "XXXX"
#endif
#if defined(__cplusplus)
extern "C" {
#endif
/***********************************************************************/
/* Static variables */
/***********************************************************************/
#if defined(STORAGE)
char sys_stamp[4] = SYS_STAMP;
#else
extern char sys_stamp[];
#endif
/***********************************************************************/
/* File-Selection Indicators */
/***********************************************************************/
#define PAT_LOG "log"
#if defined(UNIX) || defined(LINUX) || defined(UNIV_LINUX)
/*********************************************************************/
/* printf does not accept null pointer for %s target. */
/*********************************************************************/
#define SVP(S) ((S) ? S : "<null>")
#else
/*********************************************************************/
/* printf accepts null pointer for %s target. */
/*********************************************************************/
#define SVP(S) S
#endif
#if defined(STORAGE)
FILE *debug;
#else
extern FILE *debug;
#endif
/***********************************************************************/
/* General purpose type definitions. */
/***********************************************************************/
#if !defined(WIN32)
typedef const char *LPCTSTR;
typedef const char *LPCSTR;
typedef unsigned char BYTE;
typedef char *LPSTR;
typedef char *PSZ;
#if !defined(NODW)
typedef int DWORD;
#endif // !NODW
#undef HANDLE
typedef int HANDLE;
#ifdef __cplusplus
typedef int bool;
#else
#define bool my_bool
#endif
#define _MAX_PATH PATH_MAX
#define stricmp strcasecmp
#define _stricmp strcasecmp
#define strnicmp strncasecmp
#define _strnicmp strncasecmp
#define _MAX_PATH 260
#define _MAX_DRIVE 3
#define _MAX_DIR 256
#define _MAX_FNAME 256
#define _MAX_EXT 256
#define INVALID_HANDLE_VALUE (-1)
#define __stdcall
#endif // !WIN32
typedef uint OFFSET;
typedef char NAME[9];
typedef struct {
ushort Length;
char String[2];
} VARSTR;
#if !defined(PGLOBAL_DEFINED)
typedef struct _global *PGLOBAL;
#define PGLOBAL_DEFINED
#endif
typedef struct _globplg *PGS;
typedef struct _activity *PACTIVITY;
typedef struct _parm *PPARM;
/***********************************************************************/
/* Segment Sub-Allocation block structure declares. */
/* Next block is an implementation dependent segment suballoc save */
/* structure used to keep the suballocation system offsets and to */
/* restore them if needed. This scheme implies that no SubFree be used */
/***********************************************************************/
typedef struct { /* Plug Area SubAlloc header */
OFFSET To_Free; /* Offset of next free block */
uint FreeBlk; /* Size of remaining free memory */
} POOLHEADER, *PPOOLHEADER;
/***********************************************************************/
/* Language block. Containing all global information for the language */
/* this block is saved and retrieved with the language. Information */
/* in this block can be set and modified under Grammar editing. */
/***********************************************************************/
#if defined(BIT64)
typedef int TIME_T; /* Lang block size must not change */
#else // BIT32
typedef time_t TIME_T; /* time_t */
#endif // BIT32
typedef struct {
uint Memsize;
uint Size;
} AREADEF;
typedef struct Lang_block {
NAME LangName; /* Language name */
NAME Application; /* Application name */
} LANG, *PLANG;
/***********************************************************************/
/* Application block. It contains all global information for the */
/* current parse and execution using the corresponding language. */
/* This block is dynamically allocated and set at language init. */
/***********************************************************************/
typedef struct _activity { /* Describes activity and language */
void *Aptr; /* Points to user work area(s) */
NAME Ap_Name; /* Current application name */
} ACTIVITY;
/*---------------- UNIT ?????????? VERSION ? ----------------------*/
typedef struct _parm {
void *Value;
short Type, Domain;
PPARM Next;
} PARM;
/***********************************************************************/
/* Global Structure Block. This block contains, or points to, all */
/* information used by CONNECT tables. Passed as an argument */
/* to any routine allows it to have access to the entire information */
/* currently available for the whole set of loaded languages. */
/***********************************************************************/
typedef struct _global { /* Global structure */
void *Sarea; /* Points to work area */
uint Sarea_Size; /* Work area size */
PACTIVITY Activityp, ActivityStart;
char Message[MAX_STR];
short Trace;
int jump_level;
jmp_buf jumper[MAX_JUMP + 2];
} GLOBAL;
/***********************************************************************/
/* Exported routine declarations. */
/***********************************************************************/
#if defined(XMSG)
DllExport char *PlugReadMessage(PGLOBAL, int, char *);
#elif defined(NEWMSG)
DllExport char *PlugGetMessage(PGLOBAL, int);
#endif // XMSG || NEWMSG
#if defined(WIN32)
DllExport short GetLineLength(PGLOBAL); // Console line length
#endif // WIN32
DllExport PGLOBAL PlugInit(LPCSTR, uint); // Plug global initialization
DllExport int PlugExit(PGLOBAL); // Plug global termination
DllExport LPSTR PlugRemoveType(LPSTR, LPCSTR);
DllExport LPCSTR PlugSetPath(LPSTR, LPCSTR, LPCSTR);
DllExport void *PlugAllocMem(PGLOBAL, uint);
DllExport BOOL PlugSubSet(PGLOBAL, void *, uint);
DllExport void *PlugSubAlloc(PGLOBAL, void *, size_t);
DllExport void *MakePtr(void *, OFFSET);
DllExport void htrc(char const *fmt, ...);
#if defined(__cplusplus)
} // extern "C"
#endif
/*-------------------------- End of Global.H --------------------------*/

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,392 @@
/* Copyright (C) Olivier Bertrand 2004 - 2011
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/** @file ha_connect.h
@brief
The ha_connect engine is a prototype storage engine to access external data.
@see
/sql/handler.h and /storage/connect/ha_connect.cc
*/
#ifdef USE_PRAGMA_INTERFACE
#pragma interface /* gcc class implementation */
#endif
/****************************************************************************/
/* Structures used to pass info between CONNECT and ha_connect. */
/****************************************************************************/
typedef struct _create_xinfo {
char *Type; /* Retrieved from table comment */
char *Filename; /* Set if not standard */
char *IndexFN; /* Set if not standard */
ulonglong Maxrows; /* Estimated max nb of rows */
ulong Lrecl; /* Set if not default */
ulong Elements; /* Number of lines in blocks */
bool Fixed; /* False for DOS type */
void *Pcf; /* To list of columns */
void *Pxdf; /* To list of indexes */
} CRXINFO, *PCXF;
typedef struct _xinfo {
ulonglong data_file_length; /* Length of data file */
ha_rows records; /* Records in table */
ulong mean_rec_length; /* Physical record length */
char *data_file_name; /* Physical file name */
} XINFO, *PXF;
typedef class user_connect *PCONNECT;
typedef struct ha_table_option_struct TOS, *PTOS;
typedef struct ha_field_option_struct FOS, *PFOS;
/** @brief
CONNECT_SHARE is a structure that will be shared among all open handlers.
This example implements the minimum of what you will probably need.
*/
typedef struct st_connect_share {
char *table_name;
uint table_name_length, use_count;
mysql_mutex_t mutex;
THR_LOCK lock;
#if !defined(MARIADB)
PTOS table_options;
PFOS field_options;
#endif // !MARIADB
} CONNECT_SHARE;
typedef class ha_connect *PHC;
/** @brief
Class definition for the storage engine
*/
class ha_connect: public handler
{
THR_LOCK_DATA lock; ///< MySQL lock
CONNECT_SHARE *share; ///< Shared lock info
public:
ha_connect(handlerton *hton, TABLE_SHARE *table_arg);
~ha_connect();
// CONNECT Implementation
static bool connect_init(void);
static bool connect_end(void);
char *GetStringOption(char *opname, char *sdef= NULL);
PTOS GetTableOptionStruct(TABLE *table_arg);
bool GetBooleanOption(char *opname, bool bdef);
int GetIntegerOption(char *opname);
bool SetIntegerOption(char *opname, int n);
PFOS GetFieldOptionStruct(Field *fp);
void *GetColumnOption(void *field, PCOLINFO pcf);
PIXDEF GetIndexInfo(int n);
const char *GetDBName(const char *name);
const char *GetTableName(void);
int GetColNameLen(Field *fp);
char *GetColName(Field *fp);
void AddColName(char *cp, Field *fp);
TABLE *GetTable(void) {return table;}
PCONNECT GetUser(THD *thd);
PGLOBAL GetPlug(THD *thd);
PTDB GetTDB(PGLOBAL g);
bool OpenTable(PGLOBAL g, bool del= false);
bool IsOpened(void);
int CloseTable(PGLOBAL g);
int MakeRecord(char *buf);
int ScanRecord(PGLOBAL g, uchar *buf);
int CheckRecord(PGLOBAL g, const uchar *oldbuf, uchar *newbuf);
int ReadIndexed(uchar *buf, OPVAL op, const uchar* key= NULL,
uint key_len= 0);
/** @brief
The name that will be used for display purposes.
*/
const char *table_type() const {return "CONNECT";}
/** @brief
The name of the index type that will be used for display.
Don't implement this method unless you really have indexes.
*/
const char *index_type(uint inx) { return "XPLUG"; }
/** @brief
The file extensions.
*/
const char **bas_ext() const;
/** @brief
This is a list of flags that indicate what functionality the storage engine
implements. The current table flags are documented in handler.h
*/
ulonglong table_flags() const
{
return (HA_NO_TRANSACTIONS | HA_REC_NOT_IN_SEQ | HA_HAS_RECORDS |
/*HA_NO_AUTO_INCREMENT |*/ HA_NO_PREFIX_CHAR_KEYS |
#if defined(MARIADB)
HA_CAN_VIRTUAL_COLUMNS |
#endif // MARIADB
HA_NULL_IN_KEY | HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE);
}
/** @brief
This is a bitmap of flags that indicates how the storage engine
implements indexes. The current index flags are documented in
handler.h. If you do not implement indexes, just return zero here.
@details
part is the key part to check. First key part is 0.
If all_parts is set, MySQL wants to know the flags for the combined
index, up to and including 'part'.
*/
ulong index_flags(uint inx, uint part, bool all_parts) const
{
return HA_READ_NEXT | HA_READ_RANGE;
}
/** @brief
unireg.cc will call max_supported_record_length(), max_supported_keys(),
max_supported_key_parts(), uint max_supported_key_length()
to make sure that the storage engine can handle the data it is about to
send. Return *real* limits of your storage engine here; MySQL will do
min(your_limits, MySQL_limits) automatically.
*/
uint max_supported_record_length() const { return HA_MAX_REC_LENGTH; }
/** @brief
unireg.cc will call this to make sure that the storage engine can handle
the data it is about to send. Return *real* limits of your storage engine
here; MySQL will do min(your_limits, MySQL_limits) automatically.
@details
There is no need to implement ..._key_... methods if your engine doesn't
support indexes.
*/
uint max_supported_keys() const { return 10; }
/** @brief
unireg.cc will call this to make sure that the storage engine can handle
the data it is about to send. Return *real* limits of your storage engine
here; MySQL will do min(your_limits, MySQL_limits) automatically.
@details
There is no need to implement ..._key_... methods if your engine doesn't
support indexes.
*/
uint max_supported_key_parts() const { return 10; }
/** @brief
unireg.cc will call this to make sure that the storage engine can handle
the data it is about to send. Return *real* limits of your storage engine
here; MySQL will do min(your_limits, MySQL_limits) automatically.
@details
There is no need to implement ..._key_... methods if your engine doesn't
support indexes.
*/
uint max_supported_key_length() const { return 255; }
/** @brief
Called in test_quick_select to determine if indexes should be used.
*/
virtual double scan_time() { return (double) (stats.records+stats.deleted) / 20.0+10; }
/** @brief
This method will never be called if you do not implement indexes.
*/
virtual double read_time(uint, uint, ha_rows rows)
{ return (double) rows / 20.0+1; }
/*
Everything below are methods that we implement in ha_connect.cc.
Most of these methods are not obligatory, skip them and
MySQL will treat them as not implemented
*/
virtual bool get_error_message(int error, String *buf);
/**
Push condition down to the table handler.
@param cond Condition to be pushed. The condition tree must not be
modified by the by the caller.
@return
The 'remainder' condition that caller must use to filter out records.
NULL means the handler will not return rows that do not match the
passed condition.
@note
The pushed conditions form a stack (from which one can remove the
last pushed condition using cond_pop).
The table handler filters out rows using (pushed_cond1 AND pushed_cond2
AND ... AND pushed_condN)
or less restrictive condition, depending on handler's capabilities.
handler->ha_reset() call empties the condition stack.
Calls to rnd_init/rnd_end, index_init/index_end etc do not affect the
condition stack.
*/
virtual const COND *cond_push(const COND *cond);
PFIL CheckCond(PGLOBAL g, PFIL filp, AMT tty, Item *cond);
char *GetValStr(OPVAL vop, bool neg);
/**
Number of rows in table. It will only be called if
(table_flags() & (HA_HAS_RECORDS | HA_STATS_RECORDS_IS_EXACT)) != 0
*/
virtual ha_rows records();
/** @brief
We implement this in ha_connect.cc; it's a required method.
*/
int open(const char *name, int mode, uint test_if_locked); // required
/** @brief
We implement this in ha_connect.cc; it's a required method.
*/
int close(void); // required
/** @brief
We implement this in ha_connect.cc. It's not an obligatory method;
skip it and and MySQL will treat it as not implemented.
*/
int write_row(uchar *buf);
/** @brief
We implement this in ha_connect.cc. It's not an obligatory method;
skip it and and MySQL will treat it as not implemented.
*/
int update_row(const uchar *old_data, uchar *new_data);
/** @brief
We implement this in ha_connect.cc. It's not an obligatory method;
skip it and and MySQL will treat it as not implemented.
*/
int delete_row(const uchar *buf);
// Added to the connect handler
int index_init(uint idx, bool sorted);
int index_end();
int index_read(uchar * buf, const uchar * key, uint key_len,
enum ha_rkey_function find_flag);
int index_next_same(uchar *buf, const uchar *key, uint keylen);
/** @brief
We implement this in ha_connect.cc. It's not an obligatory method;
skip it and and MySQL will treat it as not implemented.
*/
//int index_read_map(uchar *buf, const uchar *key,
// key_part_map keypart_map, enum ha_rkey_function find_flag);
/** @brief
We implement this in ha_connect.cc. It's not an obligatory method;
skip it and and MySQL will treat it as not implemented.
*/
int index_next(uchar *buf);
/** @brief
We implement this in ha_connect.cc. It's not an obligatory method;
skip it and and MySQL will treat it as not implemented.
*/
//int index_prev(uchar *buf);
/** @brief
We implement this in ha_connect.cc. It's not an obligatory method;
skip it and and MySQL will treat it as not implemented.
*/
int index_first(uchar *buf);
/** @brief
We implement this in ha_connect.cc. It's not an obligatory method;
skip it and and MySQL will treat it as not implemented.
*/
//int index_last(uchar *buf);
/** @brief
Unlike index_init(), rnd_init() can be called two consecutive times
without rnd_end() in between (it only makes sense if scan=1). In this
case, the second call should prepare for the new table scan (e.g if
rnd_init() allocates the cursor, the second call should position the
cursor to the start of the table; no need to deallocate and allocate
it again. This is a required method.
*/
int rnd_init(bool scan); //required
int rnd_end();
int rnd_next(uchar *buf); ///< required
int rnd_pos(uchar *buf, uchar *pos); ///< required
void position(const uchar *record); ///< required
int info(uint); ///< required
int extra(enum ha_extra_function operation);
int external_lock(THD *thd, int lock_type); ///< required
int delete_all_rows(void);
ha_rows records_in_range(uint inx, key_range *min_key,
key_range *max_key);
int delete_table(const char *from);
bool pre_create(THD *thd, void *alter_info);
int create(const char *name, TABLE *form,
HA_CREATE_INFO *create_info); ///< required
bool check_if_incompatible_data(HA_CREATE_INFO *info,
uint table_changes);
THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
enum thr_lock_type lock_type); ///< required
int optimize(THD* thd, HA_CHECK_OPT* check_opt);
protected:
char *GetListOption(char *opname, const char *oplist);
bool add_fields(THD *thd, void *alter_info,
LEX_STRING *field_name,
enum_field_types type,
char *length, char *decimals,
uint type_modifier,
// Item *default_value, Item *on_update_value,
LEX_STRING *comment,
// char *change,
// List<String> *interval_list,
CHARSET_INFO *cs,
// uint uint_geom_type,
void *vcol_info,
engine_option_value *create_options);
// Members
static ulong num; // Tracable handler number
PCONNECT xp; // To user_connect associated class
ulong hnum; // The number of this handler
query_id_t valid_query_id; // The one when tdbp was allocated
query_id_t creat_query_id; // The one when handler was allocated
PTDB tdbp; // To table class object
PVAL sdval; // Used to convert date values
bool istable; // True for table handler
//char tname[64]; // The table name
MODE xmod; // Table mode
XINFO xinfo; // The table info structure
bool valid_info; // True if xinfo is valid
bool stop; // Used when creating index
//bool hascond; // Too late for Delete
int indexing; // Type of indexing for CONNECT
#if !defined(MARIADB)
PTOS table_options;
PFOS field_options;
#endif // !MARIADB
THR_LOCK_DATA lock_data;
public:
TABLE_SHARE *tshp; // Used by called tables
char *data_file_name;
char *index_file_name;
uint int_table_flags; // Inherited from MyISAM
bool enable_activate_all_index; // Inherited from MyISAM
}; // end of ha_connect class definition

1327
storage/connect/inihandl.c Normal file

File diff suppressed because it is too large Load Diff

766
storage/connect/libdoc.cpp Normal file
View File

@@ -0,0 +1,766 @@
/******************************************************************/
/* Implementation of XML document processing using libxml2 */
/* Author: Olivier Bertrand 2007-2013 */
/******************************************************************/
#include <string.h>
#include <stdio.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
#include <libxml/xpath.h>
#include <libxml/xpathInternals.h>
//#if defined(WIN32)
//#include <windows.h>
//#else // !WIN32
#include "my_global.h"
//#endif // !WIN32
#if !defined(LIBXML_XPATH_ENABLED) || !defined(LIBXML_SAX1_ENABLED)
#error "XPath not supported"
#endif
#include "global.h"
#include "plgdbsem.h"
#include "xobject.h"
#include "libdoc.h"
extern "C" {
extern char version[];
extern int trace;
} // "C"
/******************************************************************/
/* Return a LIBXMLDOC as a XMLDOC. */
/******************************************************************/
PXDOC GetLibxmlDoc(PGLOBAL g, char *nsl, char *nsdf,
char *enc, PFBLOCK fp)
{
return (PXDOC) new(g) LIBXMLDOC(nsl, nsdf, enc, fp);
} // end of GetLibxmlDoc
/******************************************************************/
/* XML library initialization function. */
/******************************************************************/
void XmlInitParserLib(void)
{
xmlInitParser();
} // end of XmlInitParserLib
/******************************************************************/
/* XML library cleanup function. */
/******************************************************************/
void XmlCleanupParserLib(void)
{
xmlCleanupParser();
xmlMemoryDump();
} // end of XmlCleanupParserLib
/******************************************************************/
/* Close a loaded libxml2 XML file. */
/******************************************************************/
void CloseXML2File(PGLOBAL g, PFBLOCK fp, bool all)
{
PX2BLOCK xp = (PX2BLOCK)fp;
if (xp && xp->Count > 1 && !all) {
xp->Count--;
} else if (xp && xp->Count > 0) {
iconv_close(xp->Cd);
iconv_close(xp->Cd2);
xmlFreeDoc(xp->Docp);
xp->Count = 0;
} // endif
} // end of CloseXML2File
/* ---------------------- class LIBXMLDOC ----------------------- */
/******************************************************************/
/* LIBXMLDOC constructor. */
/******************************************************************/
LIBXMLDOC::LIBXMLDOC(char *nsl, char *nsdf, char *enc, PFBLOCK fp)
: XMLDOCUMENT(nsl, nsdf, enc)
{
assert (!fp || fp->Type == TYPE_FB_XML2);
Docp = (fp) ? ((PX2BLOCK)fp)->Docp : NULL;
Nlist = NULL;
Ctxp = NULL;
Xop = NULL;
Cd = (fp) ? ((PX2BLOCK)fp)->Cd : NULL;
Cd2 = (fp) ? ((PX2BLOCK)fp)->Cd2 : NULL;
} // end of LIBXMLDOC constructor
/******************************************************************/
/* Initialize XML parser and check library compatibility. */
/******************************************************************/
bool LIBXMLDOC::Initialize(PGLOBAL g)
{
//int n = xmlKeepBlanksDefault(0);
Cd = iconv_open("ISO-8859-1", "UTF-8");
Cd2 = iconv_open("UTF-8", "ISO-8859-1");
return MakeNSlist(g);
} // end of Initialize
/******************************************************************/
/* Parse the XML file and construct node tree in memory. */
/******************************************************************/
bool LIBXMLDOC::ParseFile(char *fn)
{
if ((Docp = xmlParseFile(fn))) {
if (Docp->encoding)
Encoding = (char*)Docp->encoding;
return false;
} else
return true;
} // end of ParseFile
/******************************************************************/
/* Create or reuse an Xblock for this document. */
/******************************************************************/
PFBLOCK LIBXMLDOC::LinkXblock(PGLOBAL g, MODE m, int rc, char *fn)
{
PDBUSER dup = (PDBUSER)g->Activityp->Aptr;
PX2BLOCK xp = (PX2BLOCK)PlugSubAlloc(g, NULL, sizeof(X2BLOCK));
memset(xp, 0, sizeof(X2BLOCK));
xp->Next = (PX2BLOCK)dup->Openlist;
dup->Openlist = (PFBLOCK)xp;
xp->Type = TYPE_FB_XML2;
xp->Fname = (LPCSTR)PlugSubAlloc(g, NULL, strlen(fn) + 1);
strcpy((char*)xp->Fname, fn);
xp->Count = 1;
xp->Length = (m == MODE_READ) ? 1 : 0;
xp->Retcode = rc;
xp->Docp = Docp;
// xp->Ctxp = Ctxp;
// xp->Xop = Xop;
xp->Cd = Cd;
xp->Cd2 = Cd2; // Temporary
// Return xp as a fp
return (PFBLOCK)xp;
} // end of LinkXblock
/******************************************************************/
/* Construct and add the XML processing instruction node. */
/******************************************************************/
bool LIBXMLDOC::NewDoc(PGLOBAL g, char *ver)
{
return ((Docp = xmlNewDoc(BAD_CAST ver)) == NULL);
} // end of NewDoc
/******************************************************************/
/* Add a new comment node to the document. */
/******************************************************************/
void LIBXMLDOC::AddComment(PGLOBAL g, char *txtp)
{
xmlNodePtr cp = xmlNewDocComment(Docp, BAD_CAST txtp);
xmlAddChild((xmlNodePtr)Docp, cp);
} // end of AddText
/******************************************************************/
/* Return the node class of the root of the document. */
/******************************************************************/
PXNODE LIBXMLDOC::GetRoot(PGLOBAL g)
{
xmlNodePtr root = xmlDocGetRootElement(Docp);
if (!root)
return NULL;
return new(g) XML2NODE(this, root);
} // end of GetRoot
/******************************************************************/
/* Create a new root element and return its class node. */
/******************************************************************/
PXNODE LIBXMLDOC::NewRoot(PGLOBAL g, char *name)
{
xmlNodePtr root = xmlNewDocNode(Docp, NULL, BAD_CAST name, NULL);
if (root) {
xmlDocSetRootElement(Docp, root);
return new(g) XML2NODE(this, root);
} else
return NULL;
} // end of NewRoot
/******************************************************************/
/* Return a void XML2NODE node class. */
/******************************************************************/
PXNODE LIBXMLDOC::NewPnode(PGLOBAL g, char *name)
{
xmlNodePtr nop;
if (name) {
nop = xmlNewDocNode(Docp, NULL, BAD_CAST name, NULL);
if (nop == NULL)
return NULL;
} else
nop = NULL;
return new(g) XML2NODE(this, nop);
} // end of NewPnode
/******************************************************************/
/* Return a void XML2ATTR node class. */
/******************************************************************/
PXATTR LIBXMLDOC::NewPattr(PGLOBAL g)
{
return new(g) XML2ATTR(this, NULL, NULL);
} // end of NewPattr
/******************************************************************/
/* Return a void XML2ATTR node class. */
/******************************************************************/
PXLIST LIBXMLDOC::NewPlist(PGLOBAL g)
{
return new(g) XML2NODELIST(this, NULL);
} // end of NewPlist
/******************************************************************/
/* Dump the node tree to a new XML file. */
/******************************************************************/
int LIBXMLDOC::DumpDoc(PGLOBAL g, char *ofn)
{
int rc;
FILE *of;
if (!(of = fopen(ofn, "w")))
return -1;
#if 1
// This function does not crash (
rc = xmlSaveFormatFileEnc((const char *)ofn, Docp, Encoding, 0);
// rc = xmlDocDump(of, Docp);
#else // 0
// Until this function is fixed, do the job ourself
xmlNodePtr Rootp;
// Save the modified document
fprintf(of, "<?xml version=\"1.0\" encoding=\"%s\"?>\n", Encoding);
fprintf(of, "<!-- Created by CONNECT %s -->\n", version);
if (!(Rootp = xmlDocGetRootElement(Docp)))
return 1;
Buf = (char*)PlugSubAlloc(g, NULL, 1024);
rc = iconv_close(Cd2);
Cd2 = iconv_open(Encoding, "UTF-8");
rc = CheckDocument(of, Rootp);
#endif // 0
fclose(of);
return rc;
} // end of Dump
/******************************************************************/
/* Free the document, cleanup the XML library, and */
/* debug memory for regression tests. */
/******************************************************************/
void LIBXMLDOC::CloseDoc(PGLOBAL g, PFBLOCK xp)
{
if (xp && xp->Count == 1) {
if (Xop)
xmlXPathFreeObject(Xop);
if (Ctxp)
xmlXPathFreeContext(Ctxp);
} // endif Count
CloseXML2File(g, xp, false);
} // end of Close
/******************************************************************/
/* Evaluate the passed Xpath from the passed context node. */
/******************************************************************/
xmlNodeSetPtr LIBXMLDOC::GetNodeList(PGLOBAL g, xmlNodePtr np, char *xp)
{
xmlNodeSetPtr nl;
if (trace)
htrc("GetNodeList %s np=%p\n", xp, np);
if (!Ctxp) {
// Init Xpath
xmlXPathInit();
// Create xpath evaluation context
if (!(Ctxp = xmlXPathNewContext(Docp))) {
strcpy(g->Message, MSG(XPATH_CNTX_ERR));
if (trace)
htrc("Context error: %s\n", g->Message);
return NULL;
} // endif xpathCtx
// Register namespaces from list (if any)
for (PNS nsp = Namespaces; nsp; nsp = nsp->Next)
if (xmlXPathRegisterNs(Ctxp, BAD_CAST nsp->Prefix,
BAD_CAST nsp->Uri)) {
sprintf(g->Message, MSG(REGISTER_ERR), nsp->Prefix, nsp->Uri);
if (trace)
htrc("Ns error: %s\n", g->Message);
return NULL;
} // endif Registering
} else
xmlXPathFreeNodeSetList(Xop); // To be checked
// Set the context to the calling node
Ctxp->node = np;
// Evaluate table xpath
if (!(Xop = xmlXPathEval(BAD_CAST xp, Ctxp))) {
sprintf(g->Message, MSG(XPATH_EVAL_ERR), xp);
if (trace)
htrc("Path error: %s\n", g->Message);
return NULL;
} else
nl = Xop->nodesetval;
if (trace)
htrc("GetNodeList nl=%p n=%p\n", nl, (nl) ? nl->nodeNr : 0);
return nl;
} // end of GetNodeList
/******************************************************************/
/* CheckDocument: check if the document is ok to dump. */
/* Currently this does the dumping of the document. */
/******************************************************************/
bool LIBXMLDOC::CheckDocument(FILE *of, xmlNodePtr np)
{
int n;
bool b;
if (!np)
return true;
if (np->type == XML_ELEMENT_NODE) {
n = fprintf(of, "<%s", np->name);
b = CheckDocument(of, (xmlNodePtr)np->properties);
if (np->children)
n = fprintf(of, ">");
else
n = fprintf(of, "/>");
} else if (np->type == XML_ATTRIBUTE_NODE)
n = fprintf(of, " %s=\"", np->name);
else if (np->type == XML_TEXT_NODE)
n = fprintf(of, "%s", Encode(NULL, (char*)np->content));
else if (np->type == XML_COMMENT_NODE)
n = fprintf(of, "%s", Encode(NULL, (char*)np->content));
b = CheckDocument(of, np->children);
if (np->type == XML_ATTRIBUTE_NODE)
n = fprintf(of, "\"");
else if (!b && np->type == XML_ELEMENT_NODE)
n = fprintf(of, "</%s>", np->name);
b = CheckDocument(of, np->next);
return false;
} // end of CheckDocument
/******************************************************************/
/* Convert node or attribute content to latin characters. */
/******************************************************************/
int LIBXMLDOC::Decode(xmlChar *cnt, char *buf, int n)
{
#if defined(WIN32) || defined(AIX)
const char *inp = (const char *)cnt;
#else
char *inp = (char *)cnt;
#endif
char *outp = buf;
size_t i = strlen(inp), o = n;
int rc = iconv(Cd, &inp, &i, &outp, &o);
buf[n - o] = '\0';
return rc;
} // end of Decode
/******************************************************************/
/* Convert node or attribute content to latin characters. */
/******************************************************************/
xmlChar *LIBXMLDOC::Encode(PGLOBAL g, char *txt)
{
#if defined(WIN32) || defined(AIX)
const char *inp = (const char *)txt;
#else
char *inp = (char *)txt;
#endif
int rc;
size_t i = strlen(inp);
size_t n, o = 2*i + 1;
char *outp, *buf;
if (g) {
n = o;
buf = (char*)PlugSubAlloc(g, NULL, n);
} else {
n = o = 1024;
buf = Buf;
} // endif g
outp = buf;
rc = iconv(Cd2, &inp, &i, &outp, &o);
buf[n - o] = '\0';
return BAD_CAST buf;
} // end of Encode
/* ---------------------- class XML2NODE ------------------------ */
/******************************************************************/
/* XML2NODE constructor. */
/******************************************************************/
XML2NODE::XML2NODE(PXDOC dp, xmlNodePtr np) : XMLNODE(dp)
{
Docp = ((PXDOC2)dp)->Docp;
Content = NULL;
Nodep = np;
} // end of XML2NODE constructor
int XML2NODE::GetType(void)
{
if (trace)
htrc("GetType type=%d\n", Nodep->type);
return Nodep->type;
} // end of GetType
/******************************************************************/
/* Return the node class of next sibling of the node. */
/******************************************************************/
PXNODE XML2NODE::GetNext(PGLOBAL g)
{
if (!Nodep->next)
Next = NULL;
else if (!Next)
Next = new(g) XML2NODE(Doc, Nodep->next);
return Next;
} // end of GetNext
/******************************************************************/
/* Return the node class of first children of the node. */
/******************************************************************/
PXNODE XML2NODE::GetChild(PGLOBAL g)
{
if (!Nodep->children)
Children = NULL;
else if (!Children)
Children = new(g) XML2NODE(Doc, Nodep->children);
return Children;
} // end of GetChild
/******************************************************************/
/* Return the content of a node and subnodes. */
/******************************************************************/
char *XML2NODE::GetText(char *buf, int len)
{
if (Content)
xmlFree(Content);
if ((Content = xmlNodeGetContent(Nodep))) {
int rc = ((PXDOC2)Doc)->Decode(Content, buf, len);
if (trace)
htrc("GetText buf='%s' len=%d rc=%d\n", buf, len, rc);
xmlFree(Content);
Content = NULL;
} else
*buf = '\0';
return buf;
} // end of GetText
/******************************************************************/
/* Set the content of a node. */
/******************************************************************/
bool XML2NODE::SetContent(PGLOBAL g, char *txtp, int len)
{
if (trace)
htrc("SetContent %s\n", txtp);
xmlNodeSetContent(Nodep, ((PXDOC2)Doc)->Encode(g, txtp));
return false;
} // end of SetContent
/******************************************************************/
/* Return a clone of this node. */
/******************************************************************/
PXNODE XML2NODE::Clone(PGLOBAL g, PXNODE np)
{
if (np) {
((PNODE2)np)->Nodep = Nodep;
return np;
} else
return new(g) XML2NODE(Doc, Nodep);
} // end of Clone
/******************************************************************/
/* Return the list of all or matching children that are elements.*/
/******************************************************************/
PXLIST XML2NODE::GetChildElements(PGLOBAL g, char *xp, PXLIST lp)
{
if (trace)
htrc("GetChildElements %s\n", xp);
return SelectNodes(g, (xp) ? xp : (char*)"*", lp);
} // end of GetChildElements
/******************************************************************/
/* Return the list of nodes verifying the passed Xpath. */
/******************************************************************/
PXLIST XML2NODE::SelectNodes(PGLOBAL g, char *xp, PXLIST lp)
{
if (trace)
htrc("SelectNodes %s\n", xp);
xmlNodeSetPtr nl = ((PXDOC2)Doc)->GetNodeList(g, Nodep, xp);
if (lp) {
((PLIST2)lp)->Listp = nl;
return lp;
} else
return new(g) XML2NODELIST(Doc, nl);
} // end of SelectNodes
/******************************************************************/
/* Return the first node verifying the passed Xapth. */
/******************************************************************/
PXNODE XML2NODE::SelectSingleNode(PGLOBAL g, char *xp, PXNODE np)
{
if (trace)
htrc("SelectSingleNode %s\n", xp);
xmlNodeSetPtr nl = ((PXDOC2)Doc)->GetNodeList(g, Nodep, xp);
if (nl && nl->nodeNr) {
if (np) {
((PNODE2)np)->Nodep = nl->nodeTab[0];
return np;
} else
return new(g) XML2NODE(Doc, nl->nodeTab[0]);
} else
return NULL;
} // end of SelectSingleNode
/******************************************************************/
/* Return the node attribute with the specified name. */
/******************************************************************/
PXATTR XML2NODE::GetAttribute(PGLOBAL g, char *name, PXATTR ap)
{
if (trace)
htrc("GetAttribute %s\n", name);
xmlAttrPtr atp = xmlHasProp(Nodep, BAD_CAST name);
if (atp) {
if (ap) {
((PATTR2)ap)->Atrp = atp;
((PATTR2)ap)->Parent = Nodep;
return ap;
} else
return new(g) XML2ATTR(Doc, atp, Nodep);
} else
return NULL;
} // end of GetAttribute
/******************************************************************/
/* Add a new child node to this node and return it. */
/******************************************************************/
PXNODE XML2NODE::AddChildNode(PGLOBAL g, char *name, PXNODE np)
{
char *p, *pn, *pf = NULL;
if (trace)
htrc("AddChildNode %s\n", name);
// Is a prefix specified
if ((pn = strchr(name, ':'))) {
pf = name;
*pn++ = '\0'; // Separate name from prefix
} else
pn = name;
// If name has the format m[n] only m is taken as node name
if ((p = strchr(pn, '[')))
p = BufAlloc(g, pn, p - pn);
else
p = pn;
xmlNodePtr nop = xmlNewChild(Nodep, NULL, BAD_CAST p, NULL);
if (!nop)
return NULL;
if (pf) {
// Prefixed name, is it the default NS prefix?
if (Doc->DefNs && !strcmp(pf, Doc->DefNs))
pf = NULL; // Default namespace
xmlNsPtr nsp = xmlSearchNs(Docp, nop, BAD_CAST pf);
if (!nsp)
nsp = xmlNewNs(nop, NULL, BAD_CAST pf);
// Set node namespace
nop->ns = nsp;
*(--p) = ':'; // Restore Xname
} else if (Doc->DefNs && xmlSearchNs(Docp, nop, NULL))
// Not in default namespace
nop->ns = xmlNewNs(nop, BAD_CAST "", NULL);
if (np)
((PNODE2)np)->Nodep = nop;
else
np = new(g) XML2NODE(Doc, nop);
return NewChild(np);
} // end of AddChildNode
/******************************************************************/
/* Add a new property to this node and return it. */
/******************************************************************/
PXATTR XML2NODE::AddProperty(PGLOBAL g, char *name, PXATTR ap)
{
if (trace)
htrc("AddProperty %s\n", name);
xmlAttrPtr atp = xmlNewProp(Nodep, BAD_CAST name, NULL);
if (atp) {
if (ap) {
((PATTR2)ap)->Atrp = atp;
((PATTR2)ap)->Parent = Nodep;
return ap;
} else
return new(g) XML2ATTR(Doc, atp, Nodep);
} else
return NULL;
} // end of AddProperty
/******************************************************************/
/* Add a new text node to this node. */
/******************************************************************/
void XML2NODE::AddText(PGLOBAL g, char *txtp)
{
if (trace)
htrc("AddText %s\n", txtp);
// This is to avoid a blank line when inserting a new line
xmlNodePtr np = xmlGetLastChild(Nodep);
if (np && np->type == XML_TEXT_NODE) {
xmlUnlinkNode(np);
xmlFreeNode(np);
} // endif type
// Add the new text
xmlAddChild(Nodep, xmlNewText(BAD_CAST txtp));
} // end of AddText
/******************************************************************/
/* Remove a child node from this node. */
/******************************************************************/
void XML2NODE::DeleteChild(PGLOBAL g, PXNODE dnp)
{
xmlNodePtr np = ((PNODE2)dnp)->Nodep;
xmlNodePtr text = np->next;
// This is specific to row nodes
if (text && text->type == XML_TEXT_NODE) {
xmlUnlinkNode(text);
xmlFreeNode(text);
} // endif type
xmlUnlinkNode(np);
xmlFreeNode(np);
Delete(dnp);
} // end of DeleteChild
/* -------------------- class XML2NODELIST ---------------------- */
/******************************************************************/
/* XML2NODELIST constructor. */
/******************************************************************/
XML2NODELIST::XML2NODELIST(PXDOC dp, xmlNodeSetPtr lp)
: XMLNODELIST(dp)
{
Listp = lp;
} // end of XML2NODELIST constructor
/******************************************************************/
/* Return the length of the list. */
/******************************************************************/
int XML2NODELIST::GetLength(void)
{
return (Listp) ? Listp->nodeNr : 0;
} // end of GetLength
/******************************************************************/
/* Return the nth element of the list. */
/******************************************************************/
PXNODE XML2NODELIST::GetItem(PGLOBAL g, int n, PXNODE np)
{
if (trace)
htrc("GetItem %d\n", n);
if (!Listp || Listp->nodeNr <= n)
return NULL;
if (np) {
((PNODE2)np)->Nodep = Listp->nodeTab[n];
return np;
} else
return new(g) XML2NODE(Doc, Listp->nodeTab[n]);
} // end of GetItem
/* ---------------------- class XML2ATTR ------------------------ */
/******************************************************************/
/* XML2ATTR constructor. */
/******************************************************************/
XML2ATTR::XML2ATTR(PXDOC dp, xmlAttrPtr ap, xmlNodePtr np)
: XMLATTRIBUTE(dp)
{
Atrp = ap;
Parent = np;
} // end of XML2ATTR constructor
/******************************************************************/
/* Set the content of an attribute. */
/******************************************************************/
bool XML2ATTR::SetText(PGLOBAL g, char *txtp, int len)
{
if (trace)
htrc("SetText %s\n", txtp);
xmlSetProp(Parent, Atrp->name, ((PXDOC2)Doc)->Encode(g, txtp));
return false;
} // end of SetText

148
storage/connect/libdoc.h Normal file
View File

@@ -0,0 +1,148 @@
/******************************************************************/
/* Declaration of XML document processing using libxml2 */
/* Author: Olivier Bertrand 2007-2012 */
/******************************************************************/
#include "plgxml.h"
typedef class LIBXMLDOC *PXDOC2;
typedef class XML2NODE *PNODE2;
typedef class XML2ATTR *PATTR2;
typedef class XML2NODELIST *PLIST2;
/******************************************************************/
/* XML2 block. Must have the same layout than FBLOCK up to Type. */
/******************************************************************/
typedef struct _x2block { /* Loaded XML file block */
struct _x2block *Next;
LPCSTR Fname; /* Point on file name */
size_t Length; /* Used to tell if read mode */
short Count; /* Nb of times file is used */
short Type; /* TYPE_FB_XML */
int Retcode; /* Return code from Load */
xmlDocPtr Docp; /* Document interface pointer */
// xmlXPathContextPtr Ctxp;
// xmlXPathObjectPtr Xop;
iconv_t Cd;
iconv_t Cd2;
} X2BLOCK, *PX2BLOCK;
/******************************************************************/
/* Declaration of libxml2 document. */
/******************************************************************/
class LIBXMLDOC : public XMLDOCUMENT {
friend class XML2NODE;
friend class XML2ATTR;
public:
// Constructor
LIBXMLDOC(char *nsl, char *nsdf, char *enc, PFBLOCK fp);
// Properties
virtual short GetDocType(void) {return TYPE_FB_XML2;}
virtual void *GetDocPtr(void) {return Docp;}
// Methods
virtual bool Initialize(PGLOBAL g);
virtual bool ParseFile(char *fn);
virtual bool NewDoc(PGLOBAL g, char *ver);
virtual void AddComment(PGLOBAL g, char *com);
virtual PXNODE GetRoot(PGLOBAL g);
virtual PXNODE NewRoot(PGLOBAL g, char *name);
virtual PXNODE NewPnode(PGLOBAL g, char *name);
virtual PXATTR NewPattr(PGLOBAL g);
virtual PXLIST NewPlist(PGLOBAL g);
virtual int DumpDoc(PGLOBAL g, char *ofn);
virtual void CloseDoc(PGLOBAL g, PFBLOCK xp);
virtual PFBLOCK LinkXblock(PGLOBAL g, MODE m, int rc, char *fn);
protected:
bool CheckDocument(FILE *of, xmlNodePtr np);
xmlNodeSetPtr GetNodeList(PGLOBAL g, xmlNodePtr np, char *xp);
int Decode(xmlChar *cnt, char *buf, int n);
xmlChar *Encode(PGLOBAL g, char *txt);
// Members
xmlDocPtr Docp;
xmlNodeSetPtr Nlist;
xmlXPathContextPtr Ctxp;
xmlXPathObjectPtr Xop;
iconv_t Cd;
iconv_t Cd2; // Temporary
char *Buf; // Temporary
}; // end of class LIBXMLDOC
/******************************************************************/
/* Declaration of libxml2 node. */
/******************************************************************/
class XML2NODE : public XMLNODE {
friend class LIBXMLDOC;
friend class XML2NODELIST;
public:
// Properties
virtual char *GetName(PGLOBAL g) {return (char*)Nodep->name;}
virtual int GetType(void);
virtual PXNODE GetNext(PGLOBAL g);
virtual PXNODE GetChild(PGLOBAL g);
// Methods
virtual char *GetText(char *buf, int len);
virtual bool SetContent(PGLOBAL g, char *txtp, int len);
virtual PXNODE Clone(PGLOBAL g, PXNODE np);
virtual PXLIST GetChildElements(PGLOBAL g, char *xp, PXLIST lp);
virtual PXLIST SelectNodes(PGLOBAL g, char *xp, PXLIST lp);
virtual PXNODE SelectSingleNode(PGLOBAL g, char *xp, PXNODE np);
virtual PXATTR GetAttribute(PGLOBAL g, char *name, PXATTR ap);
virtual PXNODE AddChildNode(PGLOBAL g, char *name, PXNODE np);
virtual PXATTR AddProperty(PGLOBAL g, char *name, PXATTR ap);
virtual void AddText(PGLOBAL g, char *txtp);
virtual void DeleteChild(PGLOBAL g, PXNODE dnp);
protected:
// Constructor
XML2NODE(PXDOC dp, xmlNodePtr np);
// Members
xmlDocPtr Docp;
xmlChar *Content;
xmlNodePtr Nodep;
}; // end of class XML2NODE
/******************************************************************/
/* Declaration of libxml2 node list. */
/******************************************************************/
class XML2NODELIST : public XMLNODELIST {
friend class LIBXMLDOC;
friend class XML2NODE;
public:
// Methods
virtual int GetLength(void);
virtual PXNODE GetItem(PGLOBAL g, int n, PXNODE np);
protected:
// Constructor
XML2NODELIST(PXDOC dp, xmlNodeSetPtr lp);
// Members
xmlNodeSetPtr Listp;
}; // end of class XML2NODELIST
/******************************************************************/
/* Declaration of libxml2 attribute. */
/******************************************************************/
class XML2ATTR : public XMLATTRIBUTE {
friend class LIBXMLDOC;
friend class XML2NODE;
public:
// Properties
//virtual char *GetText(void);
// Methods
virtual bool SetText(PGLOBAL g, char *txtp, int len);
protected:
// Constructor
XML2ATTR(PXDOC dp, xmlAttrPtr ap, xmlNodePtr np);
// Members
xmlAttrPtr Atrp;
xmlNodePtr Parent;
}; // end of class XML2ATTR

318
storage/connect/macutil.cpp Normal file
View File

@@ -0,0 +1,318 @@
/***********************************************************************/
/* MACUTIL: Author Olivier Bertrand -- 2008-2012 */
/* From the article and sample code by Khalid Shaikh. */
/***********************************************************************/
#if defined(WIN32)
#include "my_global.h"
#else // !WIN32
#error This is WIN32 only DLL
#endif // !WIN32
#include "global.h"
#include "plgdbsem.h"
#include "macutil.h"
#if 0 // This is placed here just to know what are the actual values
#define MAX_ADAPTER_DESCRIPTION_LENGTH 128
#define MAX_ADAPTER_NAME_LENGTH 256
#define MAX_ADAPTER_ADDRESS_LENGTH 8
#define DEFAULT_MINIMUM_ENTITIES 32
#define MAX_HOSTNAME_LEN 128
#define MAX_DOMAIN_NAME_LEN 128
#define MAX_SCOPE_ID_LEN 256
#define BROADCAST_NODETYPE 1
#define PEER_TO_PEER_NODETYPE 2
#define MIXED_NODETYPE 4
#define HYBRID_NODETYPE 8
#define IP_ADAPTER_DDNS_ENABLED 0x01
#define IP_ADAPTER_REGISTER_ADAPTER_SUFFIX 0x02
#define IP_ADAPTER_DHCP_ENABLED 0x04
#define IP_ADAPTER_RECEIVE_ONLY 0x08
#define IP_ADAPTER_NO_MULTICAST 0x10
#define IP_ADAPTER_IPV6_OTHER_STATEFUL_CONFIG 0x20
#endif // 0
/***********************************************************************/
/* Implementation of the MACINFO class. */
/***********************************************************************/
MACINFO::MACINFO(bool adap, bool fix)
{
Fip = NULL;
Piaf = NULL;
Curp = NULL;
Buflen = 0;
Fix = fix;
Adap = adap;
N = -1;
} // end of MACINFO constructor
/***********************************************************************/
/* MACINFO: Return an error message. */
/***********************************************************************/
void MACINFO::MakeErrorMsg(PGLOBAL g, DWORD drc)
{
if (drc == ERROR_BUFFER_OVERFLOW)
sprintf(g->Message,
"GetAdaptersInfo: Buffer Overflow buflen=%d nbofadap=%d",
Buflen, N);
else if (drc == ERROR_INVALID_PARAMETER)
strcpy(g->Message, "GetAdaptersInfo: Invalid parameters");
else if (drc == ERROR_NO_DATA)
strcpy(g->Message,
"No adapter information exists for the local computer");
else if (drc == ERROR_NOT_SUPPORTED)
strcpy(g->Message, "GetAdaptersInfo is not supported");
else
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(),
0, g->Message, sizeof(g->Message), NULL);
} // end of MakeErrorMsg
/***********************************************************************/
/* MAC: Get the number of found adapters. */
/***********************************************************************/
int MACINFO::GetNadap(PGLOBAL g)
{
if (N < 0) {
// Best method
if (Adap) {
DWORD drc = GetAdaptersInfo(NULL, &Buflen);
if (drc == ERROR_SUCCESS)
N = (Fix) ? 1 : 0;
else if (drc == ERROR_BUFFER_OVERFLOW)
N = Buflen / sizeof(IP_ADAPTER_INFO);
else
MakeErrorMsg(g, drc);
} else
N = (Fix) ? 1 : 0;
#if 0
// This method returns too many adapters
DWORD dw, drc = GetNumberOfInterfaces((PDWORD)&dw);
if (drc == NO_ERROR) {
N = (int)dw;
Buflen = N * sizeof(IP_ADAPTER_INFO);
} else
MakeErrorMsg(g, 0);
#endif
} // endif MaxSize
return N;
} // end of GetMaxSize
/***********************************************************************/
/* GetMacInfo: Get info for all found adapters. */
/***********************************************************************/
bool MACINFO::GetMacInfo(PGLOBAL g)
{
DWORD drc;
if (GetNadap(g) < 0)
return true;
else if (N == 0)
return false;
Piaf = (PIP_ADAPTER_INFO)PlugSubAlloc(g, NULL, Buflen);
drc = GetAdaptersInfo(Piaf, &Buflen);
if (drc == ERROR_SUCCESS) {
Curp = Piaf; // Curp is the first one
return false; // Success
} // endif drc
MakeErrorMsg(g, drc);
return true;
} // end of GetMacInfo
/***********************************************************************/
/* GetMacInfo: Get info for all found adapters. */
/***********************************************************************/
bool MACINFO::GetFixedInfo(PGLOBAL g)
{
ULONG len = (uint)sizeof(FIXED_INFO);
DWORD drc;
Fip = (FIXED_INFO*)PlugSubAlloc(g, NULL, len);
drc = GetNetworkParams(Fip, &len);
if (drc == ERROR_BUFFER_OVERFLOW) {
Fip = (FIXED_INFO*)PlugSubAlloc(g, NULL, len);
drc = GetNetworkParams(Fip, &len);
} // endif drc
if (drc != ERROR_SUCCESS) {
sprintf(g->Message, "GetNetworkParams failed. Rc=%08x\n", drc);
return true;
} // endif drc
return false;
} // end of GetFip
#if 0
#define IF_OTHER_ADAPTERTYPE 0
#define IF_ETHERNET_ADAPTERTYPE 1
#define IF_TOKEN_RING_ADAPTERTYPE 2
#define IF_FDDI_ADAPTERTYPE 3
#define IF_PPP_ADAPTERTYPE 4
#define IF_LOOPBACK_ADAPTERTYPE 5
#endif // 0
/***********************************************************************/
/* Get next MAC info. */
/***********************************************************************/
bool MACINFO::NextMac(void)
{
if (Curp)
Curp = Curp->Next;
return Curp != NULL;
} // end of NextMac
/***********************************************************************/
/* Get the next MAC address elements. */
/***********************************************************************/
bool MACINFO::GetOneInfo(PGLOBAL g, int flag, void *v, int lv)
{
char *p = NULL, buf[260] = "";
unsigned int i;
int n = 0;
if (!Curp && flag >= 10) {
// Fix info row, no adapter info available
switch (flag) {
case 13:
case 14:
case 19:
case 22:
case 23:
break;
default:
p = "";
} // endswitch flag
} else switch (flag) {
// FIXED INFO
case 1: // Host Name
p = Fip->HostName;
break;
case 2: // Domain Name
p = Fip->DomainName;
break;
case 3: // DNS IPaddress
p = (Fip->CurrentDnsServer)
? (char*)&Fip->CurrentDnsServer->IpAddress
: (char*)&Fip->DnsServerList.IpAddress;
break;
case 4: // Node Type
n = (int)Fip->NodeType;
break;
case 5: // Scope ID ???
p = Fip->ScopeId;
break;
case 6: // Routing enabled
n = (int)Fip->EnableRouting;
break;
case 7: // Proxy enabled
n = (int)Fip->EnableProxy;
break;
case 8: // DNS enabled
n = (int)Fip->EnableDns;
break;
// ADAPTERS INFO
case 10: // Name
p = Curp->AdapterName;
break;
case 11: // Description
if ((p = strstr(Curp->Description, " - Packet Scheduler Miniport"))) {
strncpy(buf, Curp->Description, p - Curp->Description);
i = p - Curp->Description;
strncpy(buf, Curp->Description, i);
buf[i] = 0;
p = buf;
} else if ((p = strstr(Curp->Description,
" - Miniport d'ordonnancement de paquets"))) {
i = p - Curp->Description;
strncpy(buf, Curp->Description, i);
buf[i] = 0;
p = buf;
} else
p = Curp->Description;
break;
case 12: // MAC Address
for (p = buf, i = 0; i < Curp->AddressLength; i++) {
if (i)
strcat(p++, "-");
p += sprintf(p, "%.2X", Curp->Address[i]);
} // endfor i
p = buf;
break;
case 13: // Type
#if 0 // This is not found in the SDK
switch (Curp->Type) {
case IF_ETHERNET_ADAPTERTYPE: p = "Ethernet Adapter"; break;
case IF_TOKEN_RING_ADAPTERTYPE: p = "Token Ring Adapter"; break;
case IF_FDDI_ADAPTERTYPE: p = "FDDI Adapter"; break;
case IF_PPP_ADAPTERTYPE: p = "PPP Adapter"; break;
case IF_LOOPBACK_ADAPTERTYPE: p = "Loop Back Adapter"; break;
// case IF_SLIP_ADAPTERTYPE: p = "Generic Slip Adapter"; break;
default:
sprintf(buf, "Other Adapter, type=%d", Curp->Type);
p = buf;
} // endswitch Type
#endif // 0
n = (int)Curp->Type;
break;
case 14: // DHCP enabled
n = (int)Curp->DhcpEnabled;
break;
case 15: // IP Address
p = (Curp->CurrentIpAddress)
? (char*)&Curp->CurrentIpAddress->IpAddress
: (char*)&Curp->IpAddressList.IpAddress;
break;
case 16: // Subnet Mask
p = (Curp->CurrentIpAddress)
? (char*)&Curp->CurrentIpAddress->IpMask
: (char*)&Curp->IpAddressList.IpMask;
break;
case 17: // Gateway
p = (char*)&Curp->GatewayList.IpAddress;
break;
case 18: // DHCP Server
p = (char*)&Curp->DhcpServer.IpAddress;
break;
case 19: // Have WINS
n = (Curp->HaveWins) ? 1 : 0;
break;
case 20: // Primary WINS
p = (char*)&Curp->PrimaryWinsServer.IpAddress;
break;
case 21: // Secondary WINS
p = (char*)&Curp->SecondaryWinsServer.IpAddress;
break;
case 22: // Lease obtained
n = (int)Curp->LeaseObtained;
break;
case 23: // Lease expires
n = (int)Curp->LeaseExpires;
break;
default:
sprintf(g->Message, "Invalid flag value %d", flag);
return true;
} // endswitch flag
if (p)
strncpy((char*)v, p, lv);
else
*((int*)v) = n;
return false;
} // end of ReadColumn

36
storage/connect/macutil.h Normal file
View File

@@ -0,0 +1,36 @@
// MACUTIL.H Olivier Bertrand 2008-2012
// Get Mac Addresses via GetAdaptersInfo
#if defined(WIN32)
#include <iphlpapi.h>
#else // !WIN32
#error This is WIN32 only
#endif // !WIN32
#include "block.h"
typedef class MACINFO *MACIP;
/***********************************************************************/
/* This is the class declaration for MACINFO. */
/***********************************************************************/
class DllExport MACINFO : public BLOCK {
public:
// Constructor
MACINFO(bool adap, bool fix);
// Implementation
int GetNadap(PGLOBAL g);
bool GetMacInfo(PGLOBAL g);
bool GetFixedInfo(PGLOBAL g);
void MakeErrorMsg(PGLOBAL g, DWORD drc);
bool NextMac(void);
bool GetOneInfo(PGLOBAL g, int flag, void *v, int lv);
// Members
FIXED_INFO *Fip; // Points to fixed info structure
PIP_ADAPTER_INFO Piaf; // Points on Adapter info array
PIP_ADAPTER_INFO Curp; // Points on current Adapt info
ULONG Buflen; // Buffer length
bool Fix; // true if FixedInfo is needed
bool Adap; // true if Piaf is needed
int N; // Number of adapters
}; // end of class MACINFO

173
storage/connect/maputil.cpp Normal file
View File

@@ -0,0 +1,173 @@
#include "my_global.h"
#ifdef UNIX
#include "osutil.h"
#include <errno.h>
#include <stddef.h>
//typedef int HANDLE; done in os2def.h
#else /* WINDOWS */
//#include <windows.h>
#include "osutil.h"
#endif /* WINDOWS */
#include <stdlib.h>
#include <stdio.h>
#include "global.h"
#include "plgdbsem.h"
#include "maputil.h"
#ifdef WIN32
/***********************************************************************/
/* In Insert mode, just open the file for append. Otherwise */
/* create the mapping file object. The map handle can be released */
/* immediately because they will not be used anymore. */
/* If del is true in DELETE mode, then delete the whole file. */
/* Returns the file handle that can be used by caller. */
/***********************************************************************/
HANDLE CreateFileMap(PGLOBAL g, LPCSTR filename,
MEMMAP *mm, MODE mode, bool del)
{
HANDLE hFile;
HANDLE hFileMap;
DWORD access, share, disposition;
memset(mm, 0, sizeof(MEMMAP));
*g->Message = '\0';
switch (mode) {
case MODE_READ:
access = GENERIC_READ;
share = FILE_SHARE_READ;
disposition = OPEN_EXISTING;
break;
case MODE_UPDATE:
case MODE_DELETE:
access = GENERIC_READ | GENERIC_WRITE;
share = 0;
disposition = (del) ? TRUNCATE_EXISTING : OPEN_EXISTING;
break;
case MODE_INSERT:
access = GENERIC_WRITE;
share = 0;
disposition = OPEN_ALWAYS;
break;
default:
sprintf(g->Message, MSG(BAD_FUNC_MODE), "CreateFileMap", mode);
return INVALID_HANDLE_VALUE;
} // endswitch
hFile = CreateFile(filename, access, share, NULL, disposition,
FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE)
if (mode != MODE_INSERT) {
/*****************************************************************/
/* Create the file-mapping object. */
/*****************************************************************/
access = (mode == MODE_READ) ? PAGE_READONLY : PAGE_READWRITE;
hFileMap = CreateFileMapping(hFile, NULL, access, 0, 0, NULL);
if (!hFileMap) {
DWORD ler = GetLastError();
if (ler && ler != 1006) {
sprintf(g->Message, MSG(FILE_MAP_ERROR), filename, ler);
CloseHandle(hFile);
return INVALID_HANDLE_VALUE;
} else {
sprintf(g->Message, MSG(FILE_IS_EMPTY), filename);
return hFile;
} // endif ler
} // endif hFileMap
access = (mode == MODE_READ) ? FILE_MAP_READ : FILE_MAP_WRITE;
mm->memory = MapViewOfFile(hFileMap, access, 0, 0, 0);
// lenH is the high-order word of the file size
mm->lenL = GetFileSize(hFile, &mm->lenH);
CloseHandle(hFileMap); // Not used anymore
} else // MODE_INSERT
/*****************************************************************/
/* The starting point must be the end of file as for append. */
/*****************************************************************/
SetFilePointer(hFile, 0, NULL, FILE_END);
return hFile;
} // end of CreateFileMap
bool CloseMemMap(LPVOID memory, size_t dwSize)
{
return (memory) ? !UnmapViewOfFile(memory) : false;
} // end of CloseMemMap
#else /* UNIX */
// Code to handle Linux and Solaris
#include <sys/types.h>
#include <sys/mman.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
/***********************************************************************/
/* In Insert mode, just open the file for append. Otherwise */
/* create the mapping file object. The map handle can be released */
/* immediately because they will not be used anymore. */
/* If del is true in DELETE mode, then delete the whole file. */
/* Returns the file handle that can be used by caller. */
/***********************************************************************/
HANDLE CreateFileMap(PGLOBAL g, LPCSTR fileName,
MEMMAP *mm, MODE mode, bool del)
{
unsigned int openMode;
HANDLE fd;
size_t filesize;
struct stat st;
memset(mm, 0, sizeof(MEMMAP));
*g->Message = '\0';
switch (mode) {
case MODE_READ:
openMode = O_RDONLY;
break;
case MODE_UPDATE:
case MODE_DELETE:
openMode = (del) ? (O_RDWR | O_TRUNC) : O_RDWR;
break;
case MODE_INSERT:
openMode = (O_WRONLY | O_CREAT | O_APPEND);
break;
default:
sprintf(g->Message, MSG(BAD_FUNC_MODE), "CreateFileMap", mode);
return INVALID_HANDLE_VALUE;
} // endswitch
// Try to open the addressed file.
fd = open(fileName, openMode);
if (fd != INVALID_HANDLE_VALUE && mode != MODE_INSERT) {
/* We must know about the size of the file. */
if (fstat(fd, &st)) {
sprintf(g->Message, MSG(FILE_MAP_ERROR), fileName, errno);
close(fd);
return INVALID_HANDLE_VALUE;
} // endif fstat
filesize = st.st_size;
// Now we are ready to load the file. If mmap() is available we try
// this first. If not available or it failed we try to load it.
mm->memory = mmap(NULL, filesize, PROT_READ, MAP_PRIVATE, fd, 0);
mm->lenL = (mm->memory != 0) ? filesize : 0;
mm->lenH = 0;
} /* endif fd */
// mmap() call was successful. ??????????
return fd;
} // end of CreateFileMap
bool CloseMemMap(void *memory, size_t dwSize)
{
return (memory) ? ((munmap(memory, dwSize)) ? true : false) : false;
} // end of CloseMemMap
#endif // UNIX

22
storage/connect/maputil.h Normal file
View File

@@ -0,0 +1,22 @@
#ifndef __MAPUTIL_H__
#define __MAPUTIL_H__
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
void *memory;
DWORD lenL;
DWORD lenH;
} MEMMAP;
HANDLE CreateFileMap(PGLOBAL, LPCSTR, MEMMAP *, MODE, bool);
bool CloseMemMap(void *memory, size_t dwSize);
my_bool CloseFileHandle(HANDLE h);
#ifdef __cplusplus
}
#endif
#endif /* __MAPUTIL_H__ */

View File

@@ -0,0 +1,13 @@
/**************************************************************************/
/* NLS messsages definition. */
/**************************************************************************/
#if defined(FRENCH)
#if defined(CPX)
#include "frmsg1.h"
#else /* not CPX */
#include "frmsg2.h"
#endif /* CPX */
#else /* not FRENCH */
#include "engmsg.h"
#endif /* FRENCH */
/* ---------------------------------------------------------------------- */

1013
storage/connect/msgid.h Normal file

File diff suppressed because it is too large Load Diff

567
storage/connect/mycat.cc Normal file
View File

@@ -0,0 +1,567 @@
/* Copyright (C) Olivier Bertrand 2004 - 2012
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/*************** Mycat CC Program Source Code File (.CC) ***************/
/* PROGRAM NAME: MYCAT */
/* ------------- */
/* Version 1.2 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
/* This program are the DB description related routines. */
/***********************************************************************/
/***********************************************************************/
/* Include relevant MariaDB header file. */
/***********************************************************************/
#if defined(WIN32)
//#include <windows.h>
//#include <sqlext.h>
#elif defined(UNIX)
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#endif
#define DONT_DEFINE_VOID
//#include <mysql/plugin.h>
#include "handler.h"
#undef OFFSET
/***********************************************************************/
/* Include application header files */
/* */
/* global.h is header containing all global declarations. */
/* plgdbsem.h is header containing DB application declarations. */
/* tabdos.h is header containing TDBDOS classes declarations. */
/* MYCAT.h is header containing DB description declarations. */
/***********************************************************************/
#if defined(UNIX)
#include "osutil.h"
#endif // UNIX
#include "global.h"
#include "plgdbsem.h"
#include "reldef.h"
#include "tabcol.h"
#include "xtable.h"
#include "filamtxt.h"
#include "tabdos.h"
#include "tabfmt.h"
#include "tabvct.h"
#include "tabsys.h"
#if defined(WIN32)
#include "tabmac.h"
#include "tabwmi.h"
#endif // WIN32
#include "tabtbl.h"
#if defined(XML_SUPPORT)
#include "tabxml.h"
#endif // XML_SUPPORT
#include "tabmul.h"
#if defined(MYSQL_SUPPORT)
#include "tabmysql.h"
#endif // MYSQL_SUPPORT
#if defined(ODBC_SUPPORT)
#define NODBC
#include "tabodbc.h"
#endif // ODBC_SUPPORT
#if defined(PIVOT_SUPPORT)
#include "tabpivot.h"
#endif // PIVOT_SUPPORT
#include "ha_connect.h"
#include "mycat.h"
/***********************************************************************/
/* General DB routines. */
/***********************************************************************/
//bool PlugCheckPattern(PGLOBAL, LPCSTR, LPCSTR);
#if !defined(WIN32)
extern "C" int GetRcString(int id, char *buf, int bufsize);
#endif // !WIN32
//void ptrc(char const *fmt, ...);
extern int xtrace;
/* ------------------------- Class CATALOG --------------------------- */
/***********************************************************************/
/* CATALOG Constructor. */
/***********************************************************************/
CATALOG::CATALOG(void)
{
To_Desc= NULL;
//*DescFile= '\0';
#if defined(WIN32)
DataPath= ".\\";
#else // !WIN32
DataPath= "./";
#endif // !WIN32
Descp= NULL;
//memset(&DescArea, 0, sizeof(AREADEF));
memset(&Ctb, 0, sizeof(CURTAB));
Cbuf= NULL;
Cblen= 0;
DefHuge= false;
} // end of CATALOG constructor
/* -------------------------- Class MYCAT ---------------------------- */
/***********************************************************************/
/* MYCAT Constructor. */
/***********************************************************************/
MYCAT::MYCAT(PHC hc) : CATALOG()
{
Hc= hc;
To_Desc= NULL;
DefHuge= false;
SepIndex= true; // Temporay until we can store offet and size
} // end of MYCAT constructor
/***********************************************************************/
/* When using volatile storage, reset values pointing to Sarea. */
/***********************************************************************/
void MYCAT::Reset(void)
{
To_Desc= NULL;
} // end of Reset
/***********************************************************************/
/* This function sets the current database path. */
/***********************************************************************/
void MYCAT::SetPath(PGLOBAL g, LPCSTR *datapath, const char *path)
{
if (path) {
size_t len= strlen(path) + (*path != '.' ? 4 : 1);
char *buf= (char*)PlugSubAlloc(g, NULL, len);
if (*path != '.') {
#if defined(WIN32)
char *s= "\\";
#else // !WIN32
char *s= "/";
#endif // !WIN32
strcat(strcat(strcat(strcpy(buf, "."), s), path), s);
} else
strcpy(buf, path);
*datapath= buf;
} // endif path
} // end of SetDataPath
/***********************************************************************/
/* This function sets an integer MYCAT information. */
/***********************************************************************/
bool MYCAT::SetIntCatInfo(LPCSTR name, PSZ what, int n)
{
return Hc->SetIntegerOption(what, n);
} // end of SetIntCatInfo
/***********************************************************************/
/* This function returns integer MYCAT information. */
/***********************************************************************/
int MYCAT::GetIntCatInfo(LPCSTR name, PSZ what, int idef)
{
int n= Hc->GetIntegerOption(what);
return (n == NO_IVAL) ? idef : n;
} // end of GetIntCatInfo
/***********************************************************************/
/* This function returns Boolean MYCAT information. */
/***********************************************************************/
bool MYCAT::GetBoolCatInfo(LPCSTR name, PSZ what, bool bdef)
{
bool b= Hc->GetBooleanOption(what, bdef);
return b;
} // end of GetBoolCatInfo
/***********************************************************************/
/* This function returns size catalog information. */
/***********************************************************************/
int MYCAT::GetSizeCatInfo(LPCSTR name, PSZ what, PSZ sdef)
{
char * s, c;
int i, n= 0;
if (!(s= Hc->GetStringOption(what)))
s= sdef;
if ((i= sscanf(s, " %d %c ", &n, &c)) == 2)
switch (toupper(c)) {
case 'M':
n *= 1024;
case 'K':
n *= 1024;
} // endswitch c
return n;
} // end of GetSizeCatInfo
/***********************************************************************/
/* This function sets char MYCAT information in buf. */
/***********************************************************************/
int MYCAT::GetCharCatInfo(LPCSTR name, PSZ what,
PSZ sdef, char *buf, int size)
{
char *s= Hc->GetStringOption(what);
strncpy(buf, ((s) ? s : sdef), size);
return size;
} // end of GetCharCatInfo
/***********************************************************************/
/* This function returns string MYCAT information. */
/* Default parameter is "*" to get the handler default. */
/***********************************************************************/
char *MYCAT::GetStringCatInfo(PGLOBAL g, PSZ name, PSZ what, PSZ sdef)
{
char *sval, *s= Hc->GetStringOption(what, sdef);
if (s) {
sval= (char*)PlugSubAlloc(g, NULL, strlen(s) + 1);
strcpy(sval, s);
} else
sval = NULL;
return sval;
} // end of GetStringCatInfo
/***********************************************************************/
/* This function returns column MYCAT information. */
/***********************************************************************/
int MYCAT::GetColCatInfo(PGLOBAL g, PTABDEF defp)
{
char *type= GetStringCatInfo(g, NULL, "Type", "DOS");
int i, loff, poff, nof, nlg;
void *field= NULL;
PCOLDEF cdp, lcdp= NULL, tocols= NULL;
PCOLINFO pcf= (PCOLINFO)PlugSubAlloc(g, NULL, sizeof(COLINFO));
/*********************************************************************/
/* Get a unique char identifier for types. The letter used are: */
/* ABCDEF..IJKLM.OPQRSTUV.XYZ */
/*********************************************************************/
char tc= (!stricmp(type, "FMT")) ? 'T' // fmT
: (!stricmp(type, "DBF")) ? 'A' // dbAse
: (!stricmp(type, "TBL")) ? 'L' // tbL
: (!stricmp(type, "OEM")) ? 'E' // oEm
: (!stricmp(type, "DIR")) ? 'R' : toupper(*type);
// Take care of the column definitions
i= poff= nof= nlg= 0;
// Offsets of HTML and DIR tables start from 0, DBF at 1
loff= (tc == 'A') ? 1 : (tc == 'X' || tc == 'R') ? -1 : 0;
while (true) {
// Default Offset depends on table type
switch (tc) {
case 'D': // DOS
case 'F': // FIX
case 'B': // BIN
case 'V': // VEC
case 'A': // DBF
poff= loff + nof; // Default next offset
nlg= max(nlg, poff); // Default lrecl
break;
case 'C': // CSV
case 'T': // FMT
nlg+= nof;
case 'R': // DIR
case 'X': // XML
poff= loff + 1;
break;
case 'I': // INI
case 'M': // MAC
case 'L': // TBL
case 'E': // OEM
poff = 0; // Offset represents an independant flag
break;
default: // VCT PLG ODBC MYSQL WMI...
poff = 0; // NA
break;
} // endswitch tc
do {
field= Hc->GetColumnOption(field, pcf);
} while (field && (*pcf->Name =='*' /*|| pcf->Flags & U_VIRTUAL*/));
if (tc == 'A' && pcf->Type == TYPE_DATE && !pcf->Datefmt) {
// DBF date format defaults to 'YYYMMDD'
pcf->Datefmt= "YYYYMMDD";
pcf->Length= 8;
} // endif tc
if (!field)
break;
// Allocate the column description block
cdp= new(g) COLDEF;
if ((nof= cdp->Define(g, NULL, pcf, poff)) < 0)
return -1; // Error, probably unhandled type
else if (nof)
loff= cdp->GetOffset();
switch (tc) {
case 'V':
cdp->SetOffset(0); // Not to have shift
case 'B':
// BIN/VEC are packed by default
if (nof)
// Field width is the internal representation width
// that can also depend on the column format
switch (cdp->Fmt ? *cdp->Fmt : 'X') {
case 'C': break;
case 'R':
case 'F':
case 'L':
case 'I': nof= 4; break;
case 'D': nof= 8; break;
case 'S': nof= 2; break;
case 'T': nof= 1; break;
default: nof= cdp->Clen;
} // endswitch Fmt
break;
} // endswitch tc
if (lcdp)
lcdp->SetNext(cdp);
else
tocols= cdp;
lcdp= cdp;
i++;
} // endwhile
// Degree is the the number of defined columns (informational)
if (i != defp->GetDegree())
defp->SetDegree(i);
if (defp->GetDefType() == TYPE_AM_DOS) {
int ending, recln= 0;
PDOSDEF ddp= (PDOSDEF)defp;
// Was commented because sometimes ending is 0 even when
// not specified (for instance if quoted is specified)
// if ((ending= Hc->GetIntegerOption("Ending")) < 0) {
if ((ending= Hc->GetIntegerOption("Ending")) <= 0) {
#if defined(WIN32)
ending= 2;
#else
ending= 1;
#endif
Hc->SetIntegerOption("Ending", ending);
} // endif ending
// Calculate the default record size
switch (tc) {
case 'F':
recln= nlg + ending; // + length of line ending
break;
case 'B':
case 'V':
recln= nlg;
// if ((k= (pak < 0) ? 8 : pak) > 1)
// See above for detailed comment
// Round up lrecl to multiple of 8 or pak
// recln= ((recln + k - 1) / k) * k;
break;
case 'D':
case 'A':
recln= nlg;
break;
case 'C':
case 'T':
// The number of separators (assuming an extra one can exist)
// recln= poff * ((qotd) ? 3 : 1); to be investigated
recln= nlg + poff * 3; // To be safe
break;
} // endswitch tc
// lrecl must be at least recln to avoid buffer overflow
recln= max(recln, Hc->GetIntegerOption("Lrecl"));
Hc->SetIntegerOption("Lrecl", recln);
ddp->SetLrecl(recln);
} // endif Lrecl
// Attach the column definition to the tabdef
defp->SetCols(tocols);
return poff;
} // end of GetColCatInfo
/***********************************************************************/
/* GetIndexInfo: retrieve index description from the table structure. */
/***********************************************************************/
bool MYCAT::GetIndexInfo(PGLOBAL g, PTABDEF defp)
{
PIXDEF xdp, pxd= NULL, toidx= NULL;
// Now take care of the index definitions
for (int n= 0; ; n++) {
if (xtrace)
printf("Getting index %d info\n", n + 1);
if (!(xdp= Hc->GetIndexInfo(n)))
break;
if (pxd)
pxd->SetNext(xdp);
else
toidx= xdp;
pxd= xdp;
} // endfor n
// All is correct, attach new index(es)
defp->SetIndx(toidx);
return false;
} // end of GetIndexInfo
/***********************************************************************/
/* GetTableDesc: retrieve a table descriptor. */
/* Look for a table descriptor matching the name and type. If found */
/* in storage, return a pointer to it, else look in the XDB file. If */
/* found, make and add the descriptor and return a pointer to it. */
/***********************************************************************/
PRELDEF MYCAT::GetTableDesc(PGLOBAL g, LPCSTR name,
LPCSTR am, PRELDEF *prp)
{
LPCSTR type;
if (xtrace)
printf("GetTableDesc: name=%s am=%s\n", name, SVP(am));
// Firstly check whether this table descriptor is in memory
if (To_Desc)
return To_Desc;
// Here get the type of this table
if (!(type= Hc->GetStringOption("Type")))
type= "DOS";
return MakeTableDesc(g, name, type);
} // end of GetTableDesc
/***********************************************************************/
/* MakeTableDesc: make a table/view description. */
/* Note: caller must check if name already exists before calling it. */
/***********************************************************************/
PRELDEF MYCAT::MakeTableDesc(PGLOBAL g, LPCSTR name, LPCSTR am)
{
PRELDEF tdp= NULL;
if (xtrace)
printf("MakeTableDesc: name=%s am=%s\n", name, SVP(am));
/*********************************************************************/
/* Get a unique char identifier for types. The letter used are: */
/* ABCDEF..IJKLM.OPQRSTUVWXYZ and Allocate table definition class */
/*********************************************************************/
switch ((!am) ? 'D' : (!stricmp(am, "FMT")) ? 'C' // CSV
: (!stricmp(am, "DIR")) ? 'R'
: (!stricmp(am, "SYS")) ? 'I' // INI
// : (!stricmp(am, "DUMMY")) ? 'U'
: (!stricmp(am, "TBL")) ? 'L'
// : (!stricmp(am, "PLG")) ? 'S' // Compatibility
: (!stricmp(am, "MYSQL")) ? 'Y' // mYsql
: (!stricmp(am, "OEM")) ? 'E' : toupper(*am)) {
case 'F':
case 'B':
case 'D': tdp= new(g) DOSDEF; break;
case 'C': tdp= new(g) CSVDEF; break;
case 'I': tdp= new(g) INIDEF; break;
case 'R': tdp= new(g) DIRDEF; break;
#if defined(XML_SUPPORT)
case 'X': tdp= new(g) XMLDEF; break;
#endif // XML_SUPPORT
case 'V': tdp= new(g) VCTDEF; break;
#if defined(ODBC_SUPPORT)
case 'O': tdp= new(g) ODBCDEF; break;
#endif // ODBC_SUPPORT
#if defined(WIN32)
case 'M': tdp= new(g) MACDEF; break;
case 'W': tdp= new(g) WMIDEF; break;
#endif // WIN32
case 'E': tdp= new(g) OEMDEF; break;
case 'L': tdp= new(g) TBLDEF; break;
#if defined(MYSQL_SUPPORT)
case 'Y': tdp= new(g) MYSQLDEF; break;
#endif // MYSQL_SUPPORT
#if defined(PIVOT_SUPPORT)
case 'P': tdp= new(g) PIVOTDEF; break;
#endif // PIVOT_SUPPORT
default:
sprintf(g->Message, MSG(BAD_TABLE_TYPE), am, name);
} // endswitch
// Do make the table/view definition from XDB file information
if (tdp && tdp->Define(g, this, name, am))
tdp= NULL;
return tdp;
} // end of MakeTableDesc
/***********************************************************************/
/* Initialize a Table Description Block construction. */
/***********************************************************************/
PTDB MYCAT::GetTable(PGLOBAL g, PTABLE tablep, MODE mode)
{
PRELDEF tdp;
PTDB tdbp= NULL;
LPCSTR name= tablep->GetName();
if (xtrace)
printf("GetTableDB: name=%s\n", name);
// Look for the description of the requested table
tdp= GetTableDesc(g, name, NULL);
if (tdp) {
if (xtrace)
printf("tdb=%p type=%s\n", tdp, tdp->GetType());
if (tablep->GetQualifier())
SetPath(g, &tdp->Database, tablep->GetQualifier());
tdbp= tdp->GetTable(g, mode);
} // endif tdp
if (tdbp) {
if (xtrace)
printf("tdbp=%p name=%s amtype=%d\n", tdbp, tdbp->GetName(),
tdbp->GetAmType());
tablep->SetTo_Tdb(tdbp);
tdbp->SetTable(tablep);
} // endif tdbp
return (tdbp);
} // end of GetTable
/***********************************************************************/
/* ClearDB: Terminates Database usage. */
/***********************************************************************/
void MYCAT::ClearDB(PGLOBAL g)
{
To_Desc= NULL;
} // end of ClearDB
/* ------------------------ End of MYCAT --------------------------- */

64
storage/connect/mycat.h Normal file
View File

@@ -0,0 +1,64 @@
/* Copyright (C) Olivier Bertrand 2004 - 2011
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/**************** MYCAT H Declares Source Code File (.H) ***************/
/* Name: MYCAT.H Version 2.3 */
/* */
/* This file contains the CONNECT plugin MYCAT class definitions. */
/***********************************************************************/
#ifndef __MYCAT__H
#define __MYCAT__H
#include "block.h"
#include "catalog.h"
/***********************************************************************/
/* MYCAT: class for managing the CONNECT plugin DB items. */
/***********************************************************************/
class MYCAT : public CATALOG {
public:
MYCAT(PHC hc); // Constructor
// Implementation
PHC GetHandler(void) {return Hc;}
void SetHandler(PHC hc) {Hc= hc;}
// Methods
void Reset(void);
void SetDataPath(PGLOBAL g, const char *path)
{SetPath(g, &DataPath, path);}
bool GetBoolCatInfo(LPCSTR name, PSZ what, bool bdef);
bool SetIntCatInfo(LPCSTR name, PSZ what, int ival);
int GetIntCatInfo(LPCSTR name, PSZ what, int idef);
int GetSizeCatInfo(LPCSTR name, PSZ what, PSZ sdef);
int GetCharCatInfo(LPCSTR name, PSZ what, PSZ sdef, char *buf, int size);
char *GetStringCatInfo(PGLOBAL g, PSZ name, PSZ what, PSZ sdef);
int GetColCatInfo(PGLOBAL g, PTABDEF defp);
bool GetIndexInfo(PGLOBAL g, PTABDEF defp);
bool StoreIndex(PGLOBAL g, PTABDEF defp) {return false;} // Temporary
PRELDEF GetTableDesc(PGLOBAL g, LPCSTR name,
LPCSTR am, PRELDEF *prp = NULL);
PTDB GetTable(PGLOBAL g, PTABLE tablep, MODE mode = MODE_READ);
void ClearDB(PGLOBAL g);
protected:
PRELDEF MakeTableDesc(PGLOBAL g, LPCSTR name, LPCSTR am);
void SetPath(PGLOBAL g, LPCSTR *datapath, const char *path);
// Members
ha_connect *Hc; // The Connect handler
}; // end of class MYCAT
#endif __MYCAT__H

547
storage/connect/myconn.cpp Normal file
View File

@@ -0,0 +1,547 @@
/************** MyConn C++ Program Source Code File (.CPP) **************/
/* PROGRAM NAME: MYCONN */
/* ------------- */
/* Version 1.5 */
/* */
/* COPYRIGHT: */
/* ---------- */
/* (C) Copyright to the author Olivier BERTRAND 2007-2012 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
/* Implements a connection to MySQL. */
/* It can optionally use the embedded MySQL library. */
/* */
/* WHAT YOU NEED TO COMPILE THIS PROGRAM: */
/* -------------------------------------- */
/* */
/* REQUIRED FILES: */
/* --------------- */
/* MYCONN.CPP - Source code */
/* MYCONN.H - MYCONN class declaration file */
/* GLOBAL.H - Global declaration file */
/* */
/* REQUIRED LIBRARIES: */
/* ------------------- */
/* Large model C library */
/* */
/* REQUIRED PROGRAMS: */
/* ------------------ */
/* IBM, Borland, GNU or Microsoft C++ Compiler and Linker */
/* */
/************************************************************************/
#include "my_global.h"
#if defined(WIN32)
//#include <windows.h>
#else // !WIN32
#include "osutil.h"
#endif // !WIN32
#include "global.h"
#include "plgdbsem.h"
#include "value.h"
#include "valblk.h"
#define DLL_EXPORT // Items are exported from this DLL
#include "myconn.h"
#if defined(EMBEDDED)
static char *server_args[] = {
"this_program", /* this string is not used */
"--skip-bdb",
"--skip-innodb"
};
static char *server_groups[] = {
"PlugDB_SERVER",
"embedded",
"server",
(char *)NULL
};
#endif // EMBEDDED
/* -------------------------- Class MYSQLC --------------------------- */
/***********************************************************************/
/* Implementation of the MYSQLC class. */
/***********************************************************************/
MYSQLC::MYSQLC(void)
{
m_DB = NULL;
m_Stmt = NULL;
m_Res = NULL;
m_Rows = -1;
m_Row = NULL;
m_Fields = -1;
N = 0;
} // end of MYSQLC constructor
/***********************************************************************/
/* Get the number of lines of the result set. */
/* Currently we send the Select command and return m_Rows */
/* Perhaps should we use Select count(*) ... (?????) */
/* No because here we execute only one query instead of two */
/* (the select count(*) plus the normal query) */
/***********************************************************************/
int MYSQLC::GetResultSize(PGLOBAL g, PSZ sql)
{
if (m_Rows < 0)
if (ExecSQL(g, sql) != RC_OK)
return -1;
return m_Rows;
} // end of GetResultSize
/***********************************************************************/
/* Open a MySQL (remote) connection. */
/***********************************************************************/
int MYSQLC::Open(PGLOBAL g, PSZ host, PSZ db, PSZ user, PSZ pwd, int pt)
{
m_DB = mysql_init(NULL);
if (!m_DB) {
strcpy(g->Message, "mysql_init failed: no memory");
return RC_FX;
} // endif m_DB
// Notice that the client and server use separate group names.
// This is critical, because the server will not accept the
// client's options, and vice versa.
mysql_options(m_DB, MYSQL_READ_DEFAULT_GROUP, "PlugDB_CLIENT");
#if 0
if (pwd && !strcmp(pwd, "*")) {
if (GetPromptAnswer(g, "*Enter password:")) {
m_DB = NULL;
return RC_FX;
} else
pwd = g->Message;
} // endif pwd
#endif // 0
if (!mysql_real_connect(m_DB, host, user, pwd, db, pt, NULL, CLIENT_MULTI_RESULTS)) {
#if defined(_DEBUG)
sprintf(g->Message, "mysql_real_connect failed: (%d) %s",
mysql_errno(m_DB), mysql_error(m_DB));
#else // !_DEBUG
sprintf(g->Message, "(%d) %s", mysql_errno(m_DB), mysql_error(m_DB));
#endif // !_DEBUG
m_DB = NULL;
return RC_FX;
} // endif mysql_real_connect
return RC_OK;
} // end of Open
/***********************************************************************/
/* Returns true if the connection is still alive. */
/***********************************************************************/
bool MYSQLC::Connected(void)
{
int rc;
if (!m_DB)
return FALSE;
else if ((rc = mysql_ping(m_DB)) == CR_SERVER_GONE_ERROR)
return FALSE;
else
return TRUE;
} // end of Connected
/***********************************************************************/
/* Returns the thread ID of the current MySQL connection. */
/***********************************************************************/
ulong MYSQLC::GetThreadID(void)
{
return (m_DB) ? mysql_thread_id(m_DB) : 0;
} // end of GetThreadID
/***********************************************************************/
/* Returns a string that represents the server version number. */
/***********************************************************************/
const char *MYSQLC::ServerInfo(void)
{
return (m_DB) ? mysql_get_server_info(m_DB) : NULL;
} // end of ServerInfo
/***********************************************************************/
/* Returns the version number of the server as a number that */
/* represents the MySQL server version in this format: */
/* major_version*10000 + minor_version *100 + sub_version */
/***********************************************************************/
ulong MYSQLC::ServerVersion(void)
{
return (m_DB) ? mysql_get_server_version(m_DB) : 0;
} // end of ServerVersion
/**************************************************************************/
/* KillQuery: Send MySQL a Kill Query command. */
/**************************************************************************/
int MYSQLC::KillQuery(ulong id)
{
char kill[20];
sprintf(kill, "KILL QUERY %u", id);
return (m_DB) ? mysql_query(m_DB, kill) : 1;
} // end of KillQuery
/***********************************************************************/
/* Prepare the SQL statement used to insert into a MySQL table. */
/***********************************************************************/
int MYSQLC::PrepareSQL(PGLOBAL g, const char *stmt)
{
if (!m_DB) {
strcpy(g->Message, "MySQL not connected");
return -4;
} else if (m_Stmt)
return -1; // should not append
#if defined(ALPHA)
if (!(m_Stmt = mysql_prepare(m_DB, stmt, strlen(stmt)))) {
sprintf(g->Message, "mysql_prepare failed: %s [%s]",
mysql_error(m_DB), stmt);
return -1;
} // endif m_Stmt
// Return the parameter count from the statement
return mysql_param_count(m_Stmt);
#else // !ALPHA
if (!(m_Stmt = mysql_stmt_init(m_DB))) {
strcpy(g->Message, "mysql_stmt_init(), out of memory");
return -2;
} // endif m_Stmt
if (mysql_stmt_prepare(m_Stmt, stmt, strlen(stmt))) {
sprintf(g->Message, "mysql_stmt_prepare() failed: (%d) %s",
mysql_stmt_errno(m_Stmt), mysql_stmt_error(m_Stmt));
return -3;
} // endif prepare
// Return the parameter count from the statement
return mysql_stmt_param_count(m_Stmt);
#endif // !ALPHA
} // end of PrepareSQL
/***********************************************************************/
/* Exec the Select SQL command and get back the result size in rows. */
/***********************************************************************/
int MYSQLC::ExecSQL(PGLOBAL g, const char *query, int *w)
{
int rc = RC_OK;
if (!m_DB) {
strcpy(g->Message, "MySQL not connected");
return RC_FX;
} // endif m_DB
if (w)
*w = 0;
if (m_Rows >= 0)
return RC_OK; // Already done
if (mysql_query(m_DB, query) != 0) {
char *msg = (char*)PlugSubAlloc(g, NULL, 512 + strlen(query));
sprintf(msg, "(%d) %s [%s]", mysql_errno(m_DB),
mysql_error(m_DB), query);
strncpy(g->Message, msg, sizeof(g->Message) - 1);
g->Message[sizeof(g->Message) - 1] = 0;
rc = RC_FX;
} else if (mysql_field_count(m_DB) > 0) {
if (!(m_Res = mysql_store_result(m_DB))) {
char *msg = (char*)PlugSubAlloc(g, NULL, 512 + strlen(query));
sprintf(msg, "mysql_store_result failed: %s", mysql_error(m_DB));
strncpy(g->Message, msg, sizeof(g->Message) - 1);
g->Message[sizeof(g->Message) - 1] = 0;
rc = RC_FX;
} else {
m_Fields = mysql_num_fields(m_Res);
m_Rows = (int)mysql_num_rows(m_Res);
} // endif m_Res
} else {
m_Rows = (int)mysql_affected_rows(m_DB);
sprintf(g->Message, "Affected rows: %d\n", m_Rows);
rc = RC_NF;
} // endif field count
if (w)
*w = mysql_warning_count(m_DB);
return rc;
} // end of ExecSQL
/***********************************************************************/
/* Bind the parameter buffers. */
/***********************************************************************/
int MYSQLC::BindParams(PGLOBAL g, MYSQL_BIND *bind)
{
if (!m_DB) {
strcpy(g->Message, "MySQL not connected");
return RC_FX;
} else
assert(m_Stmt);
#if defined(ALPHA)
if (mysql_bind_param(m_Stmt, bind)) {
sprintf(g->Message, "mysql_bind_param() failed: %s",
mysql_stmt_error(m_Stmt));
#else // !ALPHA
if (mysql_stmt_bind_param(m_Stmt, bind)) {
sprintf(g->Message, "mysql_stmt_bind_param() failed: %s",
mysql_stmt_error(m_Stmt));
#endif // !ALPHA
return RC_FX;
} // endif bind
return RC_OK;
} // end of BindParams
/***********************************************************************/
/* Execute a prepared statement. */
/***********************************************************************/
int MYSQLC::ExecStmt(PGLOBAL g)
{
if (!m_DB) {
strcpy(g->Message, "MySQL not connected");
return RC_FX;
} // endif m_DB
#if defined(ALPHA)
if (mysql_execute(m_Stmt)) {
sprintf(g->Message, "mysql_execute() failed: %s",
mysql_stmt_error(m_Stmt));
return RC_FX;
} // endif execute
#else // !ALPHA
if (mysql_stmt_execute(m_Stmt)) {
sprintf(g->Message, "mysql_stmt_execute() failed: %s",
mysql_stmt_error(m_Stmt));
return RC_FX;
} // endif execute
#endif // !ALPHA
// Check the total number of affected rows
if (mysql_stmt_affected_rows(m_Stmt) != 1) {
sprintf(g->Message, "Invalid affected rows by MySQL");
return RC_FX;
} // endif affected_rows
return RC_OK;
} // end of ExecStmt
/***********************************************************************/
/* Fetch one result line from the query result set. */
/***********************************************************************/
int MYSQLC::Fetch(PGLOBAL g, int pos)
{
if (!m_DB) {
strcpy(g->Message, "MySQL not connected");
return RC_FX;
} // endif m_DB
if (!m_Res) {
// Result set was not initialized
strcpy(g->Message, MSG(FETCH_NO_RES));
return RC_FX;
} else
N++;
if (pos >= 0)
mysql_data_seek(m_Res, (my_ulonglong)pos);
m_Row = mysql_fetch_row(m_Res);
return (m_Row) ? RC_OK : RC_EF;
} // end of Fetch
/***********************************************************************/
/* Get one field of the current row. */
/***********************************************************************/
char *MYSQLC::GetCharField(int i)
{
if (m_Res && m_Row) {
#if defined(_DEBUG)
MYSQL_FIELD *fld = mysql_fetch_field_direct(m_Res, i);
#endif // _DEBUG
MYSQL_ROW row = m_Row + i;
return (row) ? (char*)*row : (char*)"<null>";
} else
return NULL;
} // end of GetCharField
/***********************************************************************/
/* Get the max length of the field. */
/***********************************************************************/
int MYSQLC::GetFieldLength(int i)
{
if (m_Res) {
MYSQL_FIELD *fld = mysql_fetch_field_direct(m_Res, i);
return fld->max_length;
} else
return 0;
} // end of GetFieldLength
/***********************************************************************/
/* Make a PlugDB result structure from the MySQL result. */
/***********************************************************************/
PQRYRES MYSQLC::GetResult(PGLOBAL g, bool pdb)
{
char *fmt;
int n;
PCOLRES *pcrp, crp;
PQRYRES qrp;
MYSQL_FIELD *fld;
MYSQL_ROW row;
if (!m_Res || !m_Fields) {
sprintf(g->Message, "%s result", (m_Res) ? "Void" : "No");
return NULL;
} // endif m_Res
/*********************************************************************/
/* Put the result in storage for future retrieval. */
/*********************************************************************/
qrp = (PQRYRES)PlugSubAlloc(g, NULL, sizeof(QRYRES));
pcrp = &qrp->Colresp;
qrp->Continued = FALSE;
qrp->Truncated = FALSE;
qrp->Info = FALSE;
qrp->Suball = TRUE;
qrp->BadLines = 0;
qrp->Maxsize = m_Rows;
qrp->Maxres = m_Rows;
qrp->Nbcol = 0;
qrp->Nblin = 0;
qrp->Cursor = 0;
for (fld = mysql_fetch_field(m_Res); fld;
fld = mysql_fetch_field(m_Res)) {
*pcrp = (PCOLRES)PlugSubAlloc(g, NULL, sizeof(COLRES));
crp = *pcrp;
pcrp = &crp->Next;
crp->Ncol = ++qrp->Nbcol;
crp->Name = (char*)PlugSubAlloc(g, NULL, fld->name_length + 1);
strcpy(crp->Name, fld->name);
if ((crp->Type = MYSQLtoPLG(fld->type)) == TYPE_ERROR) {
sprintf(g->Message, "Type %d not supported for column %s",
fld->type, crp->Name);
return NULL;
} else if (crp->Type == TYPE_DATE && !pdb)
// For direct MySQL connection, display the MySQL date string
crp->Type = TYPE_STRING;
crp->Prec = fld->decimals;
crp->Length = fld->max_length;
crp->Clen = GetTypeSize(crp->Type, crp->Length);
crp->DBtype = GetDBType((int)crp->Type);
if (!(crp->Kdata = AllocValBlock(g, NULL, crp->Type, m_Rows,
crp->Clen, 0, FALSE, TRUE))) {
sprintf(g->Message, MSG(INV_RESULT_TYPE),
GetFormatType(crp->Type));
return NULL;
} else if (crp->Type == TYPE_DATE) {
fmt = MyDateFmt(fld->type);
crp->Kdata->SetFormat(g, fmt, strlen(fmt));
} // endif's
if (fld->flags & NOT_NULL_FLAG)
crp->Nulls = NULL;
else {
crp->Nulls = (char*)PlugSubAlloc(g, NULL, m_Rows);
memset(crp->Nulls, ' ', m_Rows);
} // endelse fld->flags
} // endfor fld
*pcrp = NULL;
assert(qrp->Nbcol == m_Fields);
/*********************************************************************/
/* Now fill the allocated result structure. */
/*********************************************************************/
for (n = 0; n < m_Rows; n++) {
if (!(m_Row = mysql_fetch_row(m_Res))) {
sprintf(g->Message, "Missing row %d from result", n + 1);
return NULL;
} // endif m_Row
for (crp = qrp->Colresp; crp; crp = crp->Next) {
if (row = m_Row + (crp->Ncol - 1))
if (*row)
crp->Kdata->SetValue((PSZ)*row, n);
else {
if (!*row && crp->Nulls)
crp->Nulls[n] = '*'; // Null value
crp->Kdata->Reset(n);
} // endelse *row
} // endfor crp
} // endfor n
qrp->Nblin = n;
return qrp;
} // end of GetResult
/***********************************************************************/
/* Free the current result. */
/***********************************************************************/
void MYSQLC::FreeResult(void)
{
if (m_Res) {
mysql_free_result(m_Res);
m_Res = NULL;
} // endif m_Res
// Reset the connection
m_Row = NULL;
m_Rows = -1;
m_Fields = -1;
N = 0;
} // end of FreeResult
/***********************************************************************/
/* Place the cursor at the beginning of the result set. */
/***********************************************************************/
void MYSQLC::Rewind(void)
{
if (m_Res)
mysql_data_seek(m_Res, 0);
} // end of Rewind
/***********************************************************************/
/* Close the connection. */
/***********************************************************************/
void MYSQLC::Close(void)
{
FreeResult();
mysql_close(m_DB);
m_DB = NULL;
} // end of Close
/***********************************************************************/
/* Discard additional results from a stored procedure. */
/***********************************************************************/
void MYSQLC::DiscardResults(void)
{
MYSQL_RES *res;
while(!mysql_next_result(m_DB)) {
res = mysql_store_result(m_DB);
mysql_free_result(res);
} // endwhile next result
} // end of DiscardResults

91
storage/connect/myconn.h Normal file
View File

@@ -0,0 +1,91 @@
/***********************************************************************/
/* MYCONN.H Olivier Bertrand 2007-2012 */
/* */
/* This is the declaration file for the MySQL connection class and */
/* a few utility functions used to communicate with MySQL. */
/* */
/* DO NOT define DLL_EXPORT in your application so these items are */
/* declared are imported from the Myconn DLL. */
/***********************************************************************/
#if defined(WIN32)
#include <winsock.h>
#else // !WIN32
#include <sys/socket.h>
#endif // !WIN32
#include <mysql.h>
#include <errmsg.h>
#if defined(WIN32) && defined(MYCONN_EXPORTS)
#if defined(DLL_EXPORT)
#define DllItem _declspec(dllexport)
#else // !DLL_EXPORT
#define DllItem _declspec(dllimport)
#endif // !DLL_EXPORT
#else // !WIN32 || !MYCONN_EXPORTS
#define DllItem
#endif // !WIN32
//#define TYPE_AM_MYSQL (AMT)192
#define MYSQL_ENABLED 0x00000001
#define MYSQL_LOGON 0x00000002
typedef class MYSQLC *PMYC;
/***********************************************************************/
/* Exported/Imported functions. */
/***********************************************************************/
DllItem int MYSQLtoPLG(char *);
DllItem int MYSQLtoPLG(int);
DllItem enum enum_field_types PLGtoMYSQL(int, bool gdf = FALSE);
DllItem char *MyDateFmt(int);
DllItem char *MyDateFmt(char *);
/* -------------------------- MYCONN class --------------------------- */
/***********************************************************************/
/* MYSQLC exported/imported class. A MySQL connection. */
/***********************************************************************/
class DllItem MYSQLC {
friend class TDBMYSQL;
// Construction
public:
MYSQLC(void);
// Implementation
int GetRows(void) {return m_Rows;}
bool Connected(void);
// Methods
// int GetCurPos(void) {return (m_Res) ? N : 0;}
// int GetProgCur(void) {return N;}
int GetResultSize(PGLOBAL g, PSZ sql);
int Open(PGLOBAL g, PSZ host, PSZ db, PSZ user = "root",
PSZ pwd = "*", int pt = 0);
ulong GetThreadID(void);
ulong ServerVersion(void);
const char *ServerInfo(void);
int KillQuery(ulong id);
int ExecSQL(PGLOBAL g, const char *query, int *w = NULL);
int PrepareSQL(PGLOBAL g, const char *query);
int ExecStmt(PGLOBAL g);
int BindParams(PGLOBAL g, MYSQL_BIND *bind);
PQRYRES GetResult(PGLOBAL g, bool pdb = FALSE);
int Fetch(PGLOBAL g, int pos);
char *GetCharField(int i);
int GetFieldLength(int i);
void Rewind(void);
void FreeResult(void);
void Close(void);
void DiscardResults(void);
protected:
// Members
MYSQL *m_DB; // The return from MySQL connection
MYSQL_STMT *m_Stmt; // Prepared statement handle
MYSQL_RES *m_Res; // Points to MySQL Result
MYSQL_ROW m_Row; // Point to current row
int m_Rows; // The number of rows of the result
int N;
int m_Fields; // The number of result fields
}; // end of class MYSQLC

185
storage/connect/myutil.cpp Normal file
View File

@@ -0,0 +1,185 @@
/************** MyUtil C++ Program Source Code File (.CPP) **************/
/* PROGRAM NAME: MYUTIL */
/* ------------- */
/* Version 1.0 */
/* */
/* Author Olivier BERTRAND 2013 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
/* It contains utility functions to convert data types. */
/* It can optionally use the embedded MySQL library. */
/* */
/************************************************************************/
#include "my_global.h"
#include <mysql.h>
#if defined(WIN32)
//#include <windows.h>
#else // !WIN32
#include "osutil.h"
#endif // !WIN32
#include "global.h"
#include "plgdbsem.h"
//#include "value.h"
//#include "valblk.h"
#define DLL_EXPORT // Items are exported from this DLL
/************************************************************************/
/* Convert from MySQL type name to PlugDB type number */
/************************************************************************/
int MYSQLtoPLG(char *typname)
{
int type;
if (!stricmp(typname, "int") || !stricmp(typname, "mediumint") ||
!stricmp(typname, "integer"))
type = TYPE_INT;
else if (!stricmp(typname, "tinyint") || !stricmp(typname, "smallint"))
type = TYPE_SHORT;
else if (!stricmp(typname, "char") || !stricmp(typname, "varchar") ||
!stricmp(typname, "text") || !stricmp(typname, "blob"))
type = TYPE_STRING;
else if (!stricmp(typname, "double") || !stricmp(typname, "float") ||
!stricmp(typname, "real") || !stricmp(typname, "bigint") ||
!stricmp(typname, "decimal") || !stricmp(typname, "numeric"))
type = TYPE_FLOAT;
else if (!stricmp(typname, "date") || !stricmp(typname, "datetime") ||
!stricmp(typname, "time") || !stricmp(typname, "timestamp") ||
!stricmp(typname, "year"))
type = TYPE_DATE;
else
type = TYPE_ERROR;
return type;
} // end of MYSQLtoPLG
/************************************************************************/
/* Convert from PlugDB type to MySQL type number */
/************************************************************************/
enum enum_field_types PLGtoMYSQL(int type, bool gdf)
{
enum enum_field_types mytype;
switch (type) {
case TYPE_INT:
mytype = MYSQL_TYPE_LONG;
break;
case TYPE_SHORT:
mytype = MYSQL_TYPE_SHORT;
break;
case TYPE_FLOAT:
mytype = MYSQL_TYPE_DOUBLE;
break;
case TYPE_DATE:
mytype = (gdf) ? MYSQL_TYPE_DATE : MYSQL_TYPE_DATETIME;
break;
case TYPE_STRING:
mytype = MYSQL_TYPE_VARCHAR;
break;
default:
mytype = MYSQL_TYPE_NULL;
} // endswitch mytype
return mytype;
} // end of PLGtoMYSQL
/************************************************************************/
/* Convert from MySQL type to PlugDB type number */
/************************************************************************/
int MYSQLtoPLG(int mytype)
{
int type;
switch (mytype) {
case MYSQL_TYPE_TINY:
case MYSQL_TYPE_SHORT:
type = TYPE_SHORT;
break;
case MYSQL_TYPE_LONG:
case MYSQL_TYPE_INT24:
type = TYPE_INT;
break;
case MYSQL_TYPE_LONGLONG:
case MYSQL_TYPE_DECIMAL:
#if !defined(ALPHA)
case MYSQL_TYPE_NEWDECIMAL:
#endif // !ALPHA)
case MYSQL_TYPE_FLOAT:
case MYSQL_TYPE_DOUBLE:
type = TYPE_FLOAT;
break;
case MYSQL_TYPE_TIMESTAMP:
case MYSQL_TYPE_DATE:
case MYSQL_TYPE_DATETIME:
case MYSQL_TYPE_YEAR:
case MYSQL_TYPE_TIME:
type = TYPE_DATE;
break;
case MYSQL_TYPE_STRING:
case MYSQL_TYPE_VAR_STRING:
#if !defined(ALPHA)
case MYSQL_TYPE_VARCHAR:
#endif // !ALPHA)
case MYSQL_TYPE_BLOB:
case MYSQL_TYPE_TINY_BLOB:
case MYSQL_TYPE_MEDIUM_BLOB:
case MYSQL_TYPE_LONG_BLOB:
type = TYPE_STRING;
break;
default:
type = TYPE_ERROR;
} // endswitch mytype
return type;
} // end of MYSQLtoPLG
/************************************************************************/
/* Returns the format corresponding to a MySQL date type. */
/************************************************************************/
char *MyDateFmt(int mytype)
{
char *fmt;
switch (mytype) {
case MYSQL_TYPE_TIMESTAMP:
case MYSQL_TYPE_DATETIME:
fmt = "YYYY-MM-DD hh:mm:ss";
break;
case MYSQL_TYPE_DATE:
fmt = "YYYY-MM-DD";
break;
case MYSQL_TYPE_YEAR:
fmt = "YYYY";
break;
case MYSQL_TYPE_TIME:
fmt = "hh:mm:ss";
break;
default:
fmt = NULL;
} // endswitch mytype
return fmt;
} // end of MyDateFmt
/************************************************************************/
/* Returns the format corresponding to a MySQL date type. */
/************************************************************************/
char *MyDateFmt(char *typname)
{
char *fmt;
if (!stricmp(typname, "datetime") || !stricmp(typname, "timestamp"))
fmt = "YYYY-MM-DD hh:mm:ss";
else if (!stricmp(typname, "date"))
fmt = "YYYY-MM-DD";
else if (!stricmp(typname, "year"))
fmt = "YYYY";
else if (!stricmp(typname, "time"))
fmt = "hh:mm:ss";
else
fmt = NULL;
return fmt;
} // end of MyDateFmt

1856
storage/connect/odbconn.cpp Normal file

File diff suppressed because it is too large Load Diff

184
storage/connect/odbconn.h Normal file
View File

@@ -0,0 +1,184 @@
/***********************************************************************/
/* ODBConn.h : header file for the ODBC connection classes. */
/***********************************************************************/
//nclude <windows.h> /* Windows include file */
//nclude <windowsx.h> /* Message crackers */
/***********************************************************************/
/* Included C-definition files required by the interface. */
/***********************************************************************/
#include "block.h"
/***********************************************************************/
/* ODBC interface. */
/***********************************************************************/
#include <sql.h>
#include <sqlext.h>
/***********************************************************************/
/* Constants and defines. */
/***********************************************************************/
// Miscellaneous sizing info
#define MAX_NUM_OF_MSG 10 // Max number of error messages
//efine MAX_CURRENCY 30 // Max size of Currency($) string
#define MAX_TNAME_LEN 32 // Max size of table names
//efine MAX_FNAME_LEN 256 // Max size of field names
#define MAX_STRING_INFO 256 // Max size of string from SQLGetInfo
//efine MAX_DNAME_LEN 256 // Max size of Recordset names
#define MAX_CONNECT_LEN 512 // Max size of Connect string
//efine MAX_CURSOR_NAME 18 // Max size of a cursor name
#define DEFAULT_FIELD_TYPE SQL_TYPE_NULL // pick "C" data type to match SQL data type
#if !defined(WIN32)
typedef unsigned char *PUCHAR;
#endif // !WIN32
// Timeout and net wait defaults
#define DEFAULT_LOGIN_TIMEOUT 15 // seconds to before fail on connect
#define DEFAULT_QUERY_TIMEOUT 15 // seconds to before fail waiting for results
// Field Flags, used to indicate status of fields
//efine SQL_FIELD_FLAG_DIRTY 0x1
//efine SQL_FIELD_FLAG_NULL 0x2
// Update options flags
#define SQL_SETPOSUPDATES 0x0001
#define SQL_POSITIONEDSQL 0x0002
//efine SQL_GDBOUND 0x0004
enum CATINFO {CAT_TAB = 1, /* SQLTables */
CAT_COL = 2, /* SQLColumns */
CAT_KEY = 3, /* SQLPrimaryKeys */
CAT_STAT = 4, /* SQLStatistics */
CAT_SPC = 5}; /* SQLSpecialColumns */
/***********************************************************************/
/* This structure is used to control the catalog functions. */
/***********************************************************************/
typedef struct tagCATPARM {
CATINFO Id; // Id to indicate function
PQRYRES Qrp; // Result set pointer
PUCHAR Tab; // Table name or pattern
PUCHAR Pat; // Table type or column pattern
SQLLEN* *Vlen; // To array of indicator values
UWORD *Status; // To status block
// For SQLStatistics
UWORD Unique; // Index type
UWORD Accuracy; // For Cardinality and Pages
// For SQLSpecialColumns
UWORD ColType;
UWORD Scope;
UWORD Nullable;
} CATPARM;
// ODBC connection to a data source
class TDBODBC;
class ODBCCOL;
class ODBConn;
/***********************************************************************/
/* Class DBX (ODBC exception). */
/***********************************************************************/
class DBX : public BLOCK {
friend class ODBConn;
// Construction (by ThrowDBX only) -- destruction
protected:
DBX(RETCODE rc);
public:
//virtual ~DBX() {}
//void operator delete(void*, PGLOBAL, void*) {};
// Implementation (use ThrowDBX to create)
RETCODE GetRC(void) {return m_RC;}
PSZ GetErrorMessage(int i)
{return (i >=0 && i < MAX_NUM_OF_MSG) ? m_ErrMsg[i]
: "No ODBC error";}
protected:
void BuildErrorMessage(ODBConn* pdb, HSTMT hstmt = SQL_NULL_HSTMT);
// Attributes
RETCODE m_RC;
PSZ m_ErrMsg[MAX_NUM_OF_MSG];
}; // end of DBX class definition
/***********************************************************************/
/* ODBConn class. */
/***********************************************************************/
class ODBConn : public BLOCK {
friend class DBX;
friend PQRYRES GetColumnInfo(PGLOBAL, char*&, char *, int, PVBLK&);
private:
ODBConn(); // Standard (unused) constructor
public:
ODBConn(PGLOBAL g, TDBODBC *tdbp);
enum DOP { // Db Open oPtions
traceSQL = 0x0001, // Trace SQL calls
openReadOnly = 0x0002, // Open database read only
useCursorLib = 0x0004, // Use ODBC cursor lib
noOdbcDialog = 0x0008, // Don't display ODBC Connect dialog
forceOdbcDialog = 0x0010}; // Always display ODBC connect dialog
int Open(PSZ ConnectString, DWORD Options = 0);
void Close(void);
// Attributes
public:
char GetQuoteChar(void) {return m_IDQuoteChar;}
// Database successfully opened?
bool IsOpen(void) {return m_hdbc != SQL_NULL_HDBC;}
PSZ GetStringInfo(ushort infotype);
int GetMaxValue(ushort infotype);
PSZ GetConnect(void) {return m_Connect;}
public:
// Operations
void SetLoginTimeout(DWORD sec) {m_LoginTimeout = sec;}
void SetQueryTimeout(DWORD sec) {m_QueryTimeout = sec;}
int GetResultSize(char *sql, ODBCCOL *colp);
int ExecDirectSQL(char *sql, ODBCCOL *tocols);
int Fetch(void);
int PrepareSQL(char *sql);
bool ExecuteSQL(void);
bool BindParam(ODBCCOL *colp);
int GetCatInfo(CATPARM *cap);
public:
// Set special options
void OnSetOptions(HSTMT hstmt);
// Implementation
public:
// virtual ~ODBConn();
// ODBC operations
protected:
bool Check(RETCODE rc);
void ThrowDBX(RETCODE rc, HSTMT hstmt = SQL_NULL_HSTMT);
void ThrowDBX(PSZ msg);
void AllocConnect(DWORD dwOptions);
bool Connect(DWORD Options);
void VerifyConnect(void);
void GetConnectInfo(void);
void Free(void);
protected:
// Static members
static HENV m_henv;
static int m_nAlloc; // per-Appl reference to HENV above
// Members
PGLOBAL m_G;
TDBODBC *m_Tdb;
HDBC m_hdbc;
HSTMT m_hstmt;
DWORD m_LoginTimeout;
DWORD m_QueryTimeout;
DWORD m_UpdateOptions;
DWORD m_RowsetSize;
int m_Catver;
PSZ m_Connect;
bool m_Updatable;
char m_IDQuoteChar;
}; // end of ODBConn class definition

200
storage/connect/os2def.h Normal file
View File

@@ -0,0 +1,200 @@
/****************************** Module Header ******************************/
/* Module Name: OS2DEF.H */
/* OS/2 Common Definitions file adapted for UNIX system. */
/***************************************************************************/
#ifndef __OS2DEFS__H__
#define __OS2DEFS__H__
#include "my_global.h"
#if 0
#ifndef FALSE
#define FALSE 0
#define TRUE 1
#endif
#define CHAR char /* ch */
#define SHORT short /* s */
#if defined(BIT64)
typedef int LONG; /* i */
#else // BIT32
typedef long LONG; /* l */
#endif // BIT32
#define INT int /* i */
#define VOID void
#undef HANDLE
typedef void* LPVOID;
typedef unsigned short *LPWSTR;
typedef const unsigned short *LPCWSTR;
#if defined(UNIX) || defined(UNIV_LINUX) || defined(WIN32)
typedef int bool; /* f */
#elif !defined(WIN)
typedef unsigned short bool; /* f */
#else
typedef unsigned short WBOOL; /* f */
#define bool WBOOL
#endif
typedef unsigned char UCHAR; /* uch */
typedef unsigned short USHORT; /* us */
#if defined(BIT64)
typedef unsigned int ULONG; /* ul */
#else // BIT32
typedef unsigned long ULONG; /* ul */
#endif // BIT32
typedef unsigned int uint; /* ui */
typedef unsigned char BYTE; /* b */
typedef char *PSZ;
typedef char *PCH;
typedef const char *LPCSTR;
typedef const char *LPCTSTR;
typedef char *LPSTR;
typedef char *LPTSTR;
typedef CHAR *PCHAR;
typedef SHORT *PSHORT;
typedef ULONG DWORD;
typedef USHORT WORD;
#if defined(WIN)
typedef int *WPLONG;
typedef BYTE *WPBYTE;
typedef INT *WPINT;
#define PINT WPLONG
#define PBYTE WPBYTE
#define PINT WPINT
#else
//typedef int *PINT;
typedef BYTE *PBYTE;
typedef INT *PINT;
#endif
typedef UCHAR *PUCHAR;
typedef USHORT *PUSHORT;
typedef ULONG *PULONG;
typedef uint *PUINT;
typedef VOID *PVOID;
typedef PVOID *PPVOID;
typedef bool *PBOOL;
#if defined(UNIX) || defined(UNIV_LINUX)
//#if !defined(MYSQL_DYNAMIC_PLUGIN)
#ifndef min
#define max(x,y) (((x)>(y))?(x):(y))
#define min(x,y) (((x)<(y))?(x):(y))
#endif // !MYSQL_DYNAMIC_PLUGIN
#define FAR
#define cdecl
#define _MAX_PATH 260
#define _MAX_DRIVE 3
#define _MAX_DIR 256
#define _MAX_FNAME 256
#define _MAX_EXT 256
#define INVALID_HANDLE_VALUE (-1)
//#define FILE file
//#if defined(LINUX)
//typedef void *HANDLE;
typedef int HANDLE;
//#else
#if !defined(MYSQL_DYNAMIC_PLUGIN)
//typedef int HANDLE;
#endif
//#endif // !LINUX
typedef long long __int64;
//int getcwd(char *, int);
#define stricmp strcasecmp
#define strnicmp strncasecmp
#define _stricmp stricmp
#define _strnicmp strnicmp
#define _open open
#define MAX_PATH 256
#ifdef LINUX
//#define _fileno(p) __sfileno(p) to be clarified
#endif // LINUX
#define __stdcall
#else // !UNIX
typedef LPVOID HANDLE;
#if defined(__cplusplus)
#if !defined(__MINMAX_DEFINED)
#define __MINMAX_DEFINED
#ifndef max
#define max(x,y) (((x)>(y))?(x):(y))
#endif
#ifndef min
#define min(x,y) (((x)<(y))?(x):(y))
#endif
#endif
#endif /* __cplusplus */
#if defined(WIN)
#define FAR _far
#define NEAR _near
#define PASCAL _pascal
#elif defined(WIN32)
#define FAR
#define NEAR
#else
#define PASCAL pascal
#define FAR far
#define NEAR near
#endif
#endif // !UNIX
typedef unsigned short SEL; /* sel */
//typedef HANDLE HWND;
#define HINSTANCE HANDLE;
#if defined(OS32)
typedef SEL *PSEL;
/*** Useful Helper Macros */
/* Create untyped far pointer from selector and offset */
#define MAKEP( sel,off ) (( void * )( void * _Seg16 )( (sel) << 16 | (off) ))
#define MAKE16P( sel,off ) (( void * _Seg16 )( (sel) << 16 | (off) ))
/* Extract selector or offset from far pointer */
#define SELECTOROF(ptr) ((((ULONG)(ptr))>>13)|7)
#define OFFSETOF(p) (((PUSHORT)&(p))[0])
#else
typedef SEL FAR *PSEL;
/*** Useful Helper Macros */
/* Create untyped far pointer from selector and offset */
#define MAKEP(sel, off) ((PVOID)MAKEULONG(off, sel))
/* Extract selector or offset from far pointer */
#if !defined(ODBC)
#define SELECTOROF(p) (((PUSHORT)&(p))[1])
#define OFFSETOF(p) (((PUSHORT)&(p))[0])
#endif
/* Combine l & h to form a 32 bit quantity. */
#define MAKEULONG(l, h) ((ULONG)(((USHORT)(l)) | ((ULONG)((USHORT)(h))) << 16))
#endif
#if defined(UNIX) || defined(UNIV_LINUX)
#define FORMAT_MESSAGE_ALLOCATE_BUFFER 1
#define FORMAT_MESSAGE_FROM_SYSTEM 2
#define FORMAT_MESSAGE_IGNORE_INSERTS 4
typedef const LPVOID LPCVOID;
#ifdef __cplusplus
extern "C" {
#endif
DWORD FormatMessage(
DWORD dwFlags,
LPCVOID lpSource,
DWORD dwMessageId,
DWORD dwLanguageId,
LPSTR lpBuffer,
DWORD nSize, ...
);
unsigned long _filelength(int);
void Sleep(DWORD);
#ifdef __cplusplus
}
#endif
#endif // UNIX
#endif // 0
#endif // ! __OS2DEFS__H__
/**************************** end of file **********************************/

232
storage/connect/osutil.c Normal file
View File

@@ -0,0 +1,232 @@
#include "my_global.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "osutil.h"
#ifdef WIN32
my_bool CloseFileHandle(HANDLE h)
{
return !CloseHandle(h);
} /* end of CloseFileHandle */
#else /* UNIX */
/* code to handle Linux and Solaris */
#include <unistd.h>
#include <sys/stat.h>
//#include <ctype.h>
#include <fcntl.h>
#define DWORD int
extern FILE *debug;
/***********************************************************************/
/* Define some functions not existing in the UNIX library. */
/***********************************************************************/
PSZ strupr(PSZ p)
{
register int i;
for (i = 0; p[i]; i++)
p[i] = toupper(p[i]);
return (p);
} /* end of strupr */
PSZ strlwr(PSZ p)
{
register int i;
for (i = 0; p[i]; i++)
p[i] = tolower(p[i]);
return (p);
} /* end of strlwr */
#if defined(NOT_USED) /*&& !defined(sun) && !defined(LINUX) && !defined(AIX)*/
/***********************************************************************/
/* Define stricmp function not existing in some UNIX libraries. */
/***********************************************************************/
int stricmp(char *str1, char *str2)
{
register int i;
int n;
char c;
char *sup1 = malloc(strlen(str1) + 1);
char *sup2 = malloc(strlen(str2) + 1);
for (i = 0; c = str1[i]; i++)
sup1[i] = toupper(c);
sup1[i] = 0;
for (i = 0; c = str2[i]; i++)
sup2[i] = toupper(c);
sup2[i] = 0;
n = strcmp(sup1, sup2);
free(sup1);
free(sup2);
return (n);
} /* end of stricmp */
#endif /* sun */
/***********************************************************************/
/* Define the splitpath function not existing in the UNIX library. */
/***********************************************************************/
void _splitpath(LPCSTR name, LPSTR drive, LPSTR dir, LPSTR fn, LPSTR ft)
{
LPCSTR p2, p = name;
#ifdef DEBTRACE
fprintf(debug,"SplitPath: name=%s [%s (%d)]\n",
XSTR(name), XSTR(__FILE__), __LINE__);
#endif
if (drive) *drive = '\0';
if (dir) *dir = '\0';
if (fn) *fn = '\0';
if (ft) *ft = '\0';
if ((p2 = strrchr(p, '/'))) {
p2++;
if (dir) strncat(dir, p, p2 - p);
p = p2;
} /* endif p2 */
if ((p2 = strrchr(p, '.'))) {
if (fn) strncat(fn, p, p2 - p);
if (ft) strcpy(ft, p2);
} else
if (fn) strcpy(fn, p);
#ifdef DEBTRACE
fprintf(debug,"SplitPath: name=%s drive=%s dir=%s filename=%s type=%s [%s(%d)]\n",
XSTR(name), XSTR(drive), XSTR(dir), XSTR(fn), XSTR(ft), __FILE__, __LINE__);
#endif
} /* end of _splitpath */
/***********************************************************************/
/* Define the makepath function not existing in the UNIX library. */
/***********************************************************************/
void _makepath(LPSTR name, LPCSTR drive, LPCSTR dir, LPCSTR fn, LPCSTR ft)
{
int n;
if (!name)
return;
else
*name = '\0';
if (dir && (n = strlen(dir)) > 0) {
strcpy(name, dir);
if (name[n-1] != '/')
strcat(name, "/");
} /* endif dir */
if (fn)
strcat(name, fn);
if (ft && strlen(ft)) {
if (*ft != '.')
strcat(name, ".");
strcat(name, ft);
} /* endif ft */
} /* end of _makepath */
my_bool CloseFileHandle(HANDLE h)
{
return (close(h)) ? TRUE : FALSE;
} /* end of CloseFileHandle */
void Sleep(DWORD time)
{
//FIXME: TODO
} /* end of Sleep */
int GetLastError()
{
return errno;
} /* end of GetLastError */
unsigned long _filelength(int fd)
{
struct stat st;
if (fd == -1)
return 0;
if (fstat(fd, &st) != 0)
return 0;
return st.st_size;
} /* end of _filelength */
char *_fullpath(char *absPath, const char *relPath, size_t maxLength)
{
// Fixme
char *p;
if( *relPath == '\\' || *relPath == '/' ) {
strncpy(absPath, relPath, maxLength);
} else if(*relPath == '~') {
// get the path to the home directory
// Fixme
strncpy(absPath, relPath, maxLength);
} else {
char buff[2*_MAX_PATH];
getcwd(buff, _MAX_PATH);
strcat(buff,"/");
strcat(buff, relPath);
strncpy(absPath, buff, maxLength);
} /* endif's relPath */
p = absPath;
for(; *p; p++)
if (*p == '\\')
*p = '/';
return absPath;
} /* end of _fullpath */
bool MessageBeep(uint i)
{
// Fixme
return TRUE;
} /* end of MessageBeep */
LPSTR _strerror(int errn)
{
static char buff[256];
sprintf(buff,"error: %d", errn);
return buff;
} /* end of _strerror */
int _isatty(int fileNo)
{
return isatty(fileNo);
} /* end of _isatty */
/* This function is ridiculous and should be revisited */
DWORD FormatMessage(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId,
DWORD dwLanguageId, LPSTR lpBuffer, DWORD nSize, ...)
{
char buff[32];
int n;
//if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER)
// return 0; /* means error */
n = sprintf(buff, "Error code: %d", dwMessageId);
strncpy(lpBuffer, buff, nSize);
return min(n, nSize);
} /* end of FormatMessage */
#endif // UNIX

121
storage/connect/osutil.h Normal file
View File

@@ -0,0 +1,121 @@
#ifndef __OSUTIL_H__
#define __OSUTIL_H__
#if defined(UNIX) || defined(UNIV_LINUX)
#include "my_global.h"
#include <errno.h>
#include <stddef.h>
typedef const void *LPCVOID;
typedef const char *LPCTSTR;
typedef const char *LPCSTR;
typedef unsigned char BYTE;
typedef char *LPSTR;
typedef char *LPTSTR;
typedef char *PSZ;
typedef int INT;
//typedef int DWORD;
#undef HANDLE
typedef int HANDLE;
#ifdef __cplusplus
//typedef int bool;
#else
#define bool my_bool
#endif
#define _MAX_PATH PATH_MAX
#define stricmp strcasecmp
#define strnicmp strncasecmp
#define MB_OK 0x00000000
#if defined(__cplusplus)
#if !defined(__MINMAX_DEFINED)
#define __MINMAX_DEFINED
#ifndef max
#define max(x,y) (((x)>(y))?(x):(y))
#endif
#ifndef min
#define min(x,y) (((x)<(y))?(x):(y))
#endif
#endif
#endif /* __cplusplus */
#ifdef __cplusplus
extern "C" {
#endif
int GetLastError();
void _splitpath(const char*, char*, char*, char*, char*);
void _makepath(char*, const char*, const char*, const char*, const char*);
char *_fullpath(char *absPath, const char *relPath, size_t maxLength);
bool MessageBeep(uint);
unsigned long _filelength(int fd);
int GetPrivateProfileString(
LPCTSTR lpAppName, // section name
LPCTSTR lpKeyName, // key name
LPCTSTR lpDefault, // default string
LPTSTR lpReturnedString, // destination buffer
int nSize, // size of destination buffer
LPCTSTR lpFileName // initialization file name
);
uint GetPrivateProfileInt(
LPCTSTR lpAppName, // section name
LPCTSTR lpKeyName, // key name
INT nDefault, // return value if key name not found
LPCTSTR lpFileName // initialization file name
);
bool WritePrivateProfileString(
LPCTSTR lpAppName, // section name
LPCTSTR lpKeyName, // key name
LPCTSTR lpString, // string to add
LPCTSTR lpFileName // initialization file
);
int GetPrivateProfileSection(
LPCTSTR lpAppName, // section name
LPTSTR lpReturnedString, // return buffer
int nSize, // size of return buffer
LPCTSTR lpFileName // initialization file name
);
bool WritePrivateProfileSection(
LPCTSTR lpAppName, // section name
LPCTSTR lpString, // data
LPCTSTR lpFileName // file name
);
PSZ strupr(PSZ s);
PSZ strlwr(PSZ s);
typedef size_t FILEPOS;
//pedef int FILEHANDLE; // UNIX
#ifndef _MAX_PATH
#define MAX_PATH 256
#endif
#ifdef __cplusplus
}
#endif
#else /* WINDOWS */
#include <windows.h>
typedef __int64 FILEPOS;
//pedef HANDLE FILEHANDLE; // Win32
#endif /* WINDOWS */
#define XSTR(x) ((x)?(x):"<null>")
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif /* __OSUTIL_H__ */

218
storage/connect/plgcnx.h Normal file
View File

@@ -0,0 +1,218 @@
/**************************************************************************/
/* PLGCNX.H */
/* Copyright to the author: Olivier Bertrand 2000-2012 */
/* */
/* This is the connection DLL's declares. */
/**************************************************************************/
#if !defined(_PLGCNX_H)
#define _PLGCNX_H
#define MAXMSGLEN 65512 /* Default max length of cnx message */
#define MAXERRMSG 512 /* Max length of error messages */
#define MAXMESSAGE 256 /* Max length of returned messages */
#define MAXDBNAME 128 /* Max length of DB related names */
/**************************************************************************/
/* API Function return codes. */
/**************************************************************************/
enum FNRC {RC_LICENSE = 7, /* PLGConnect prompt for license key */
RC_PASSWD = 6, /* PLGConnect prompt for User/Pwd */
RC_SUCWINFO = 5, /* Succes With Info return code */
RC_SOCKET = 4, /* RC from PLGConnect to socket DLL */
RC_PROMPT = 3, /* Intermediate prompt return */
RC_CANCEL = 2, /* Command was cancelled by user */
RC_PROGRESS = 1, /* Intermediate progress info */
RC_SUCCESS = 0, /* Successful function (must be 0) */
RC_MEMORY = -1, /* Storage allocation error */
RC_TRUNCATED = -2, /* Result has been truncated */
RC_TIMEOUT = -3, /* Connection timeout occured */
RC_TOOBIG = -4, /* Data is too big for connection */
RC_KEY = -5, /* Null ptr to key in Connect */
/* or bad key in other functions */
RC_MAXCONN = -6, /* Too many conn's for one process */
RC_MAXCLIENT = -7, /* Too many clients for one system */
RC_SYNCHRO = -8, /* Synchronization error */
RC_SERVER = -9, /* Error related to the server */
RC_MAXCOL = -10, /* Result has too many columns */
RC_LAST = -10}; /* Other error codes are < this and */
/* are system errors. */
/**************************************************************************/
/* Standard function return codes. */
/**************************************************************************/
#if !defined(RC_OK_DEFINED)
#define RC_OK_DEFINED
enum RCODE {RC_OK = 0, /* No error return code */
RC_NF = 1, /* Not found return code */
RC_EF = 2, /* End of file return code */
RC_FX = 3, /* Error return code */
RC_INFO = 4}; /* Success with info */
#endif // !RC_OK_DEFINED
/**************************************************************************/
/* Data types. */
/**************************************************************************/
enum XDBTYPE {DB_ERROR = 0, /* Unknown or wrong type */
DB_STRING = 1, /* Null terminated string */
DB_CHAR = 2, /* Character array */
DB_SHORT = 3, /* Used by some catalog functions */
DB_INT = 4, /* Long integer array */
DB_DOUBLE = 5, /* Double float array */
DB_DATE = 6}; /* Datetime value array */
/**************************************************************************/
/* Index of info values within the info int integer array. */
/**************************************************************************/
enum INFO {INDX_RC, /* Index of PlugDB return code field */
INDX_TIME, /* Index of elapsed time in millisec */
INDX_CHG, /* Index of Language or DB changed */
INDX_RSAV, /* Index of Result Set availability */
INDX_TYPE, /* Index of returned data type field */
INDX_LINE, /* Index of number of lines field */
INDX_LEN, /* Index of line length field */
INDX_SIZE, /* Index of returned data size field */
INDX_MAX}; /* Size of info array */
/**************************************************************************/
/* Internal message types. */
/**************************************************************************/
enum MSGTYP {MST_OPEN = 10, /* Code for old connecting message */
MST_COMMAND = 11, /* Code for send command message */
MST_RESULT = 12, /* Code for get result message */
MST_CLOSE = 13, /* Code for disconnecting message */
MST_PROGRESS = 14, /* Code for progress message */
MST_CANCEL = 15, /* Code for cancel message */
MST_PROCESSED = 16, /* Code for already processed msg */
MST_ERROR = 17, /* Code for get error message */
MST_CHAR = 18, /* Code for get char value message */
MST_LONG = 19, /* Code for get int value message */
MST_COLUMN = 20, /* Code for get col value message */
MST_MESSAGE = 21, /* Code for get message message */
MST_HEADER = 22, /* Code for get header message */
MST_SOCKET = 23, /* Code for socket error message */
MST_SHUTDOWN = 24, /* Code for shutdown message */
MST_SOCKPROG = 25, /* Code for socket progress message */
MST_POST = 26, /* Code for post command message */
MST_NEW_OPEN = 27, /* Code for new connecting message */
MST_PROG_NUM = 5}; /* Num of integers in progress msg */
/**************************************************************************/
/* Vendors. */
/**************************************************************************/
enum VENDOR {VDR_UNKNOWN = -2, /* Not known or not connected */
VDR_PlugDB = -1, /* PlugDB */
VDR_OTHER = 0}; /* OEM */
/**************************************************************************/
/* Attribute keys of Result Description structure (arranged by type). */
/**************************************************************************/
enum CKEYS {K_ProgMsg, K_Lang, K_ActiveDB, K_Cmax};
enum LKEYS {K_NBcol, K_NBlin, K_CurPos, K_RC, K_Result, K_Elapsed,
K_Continued, K_Maxsize, K_Lmax, K_Maxcol,
K_Maxres, K_Maxlin, K_NBparm};
enum NKEYS {K_Type, K_Length, K_Prec, K_DataLen, K_Nmax};
/**************************************************************************/
/* Result description structures. */
/**************************************************************************/
typedef struct _MsgTagAttr {
bool fSupplied;
char Attr[MAXMESSAGE];
} MTAG, *PMTAG;
typedef struct _CharTagAttr {
bool fSupplied;
char Attr[MAXDBNAME];
} CTAG, *PCTAG;
typedef struct _LongTagAttr {
bool fSupplied;
int Attr;
} LTAG, *PLTAG;
typedef struct _ColVar {
LTAG Lat[K_Nmax];
CTAG Cat;
} COLVAR, *LPCOLVAR;
typedef struct _ResDesc {
int Maxcol; /* Max number of columns */
int Colnum; /* Number of columns */
MTAG Mat; /* Message */
CTAG Cat[K_Cmax]; /* Character attributes */
LTAG Lat[K_Lmax]; /* Long int attributes */
COLVAR Col[1]; /* Column attributes */
} RDESC, *PRDESC;
/**************************************************************************/
/* Exported PlugDB client functions in Plgcnx DLL. */
/**************************************************************************/
#if !defined(CNXFUNC)
#if defined(UNIX) || defined(UNIV_LINUX)
#undef __stdcall
#define __stdcall
#endif
#if defined(NOLIB) /* Dynamic link of plgcnx.dll */
#define CNXFUNC(f) (__stdcall *f)
#else /* LIB */ /* Static link with plgcnx.lib */
#define CNXFUNC(f) __stdcall f
#endif
#endif
#if !defined(CNXKEY)
#define CNXKEY uint
#endif
#if !defined(XTRN)
#define XTRN
#endif
#ifdef NOT_USED
//#if !defined(NO_FUNC)
#ifdef __cplusplus
extern "C" {
#endif
XTRN int CNXFUNC(PLGConnect) (CNXKEY *, const char *, bool);
XTRN int CNXFUNC(PLGSendCommand) (CNXKEY, const char *, void *, int, int *);
XTRN int CNXFUNC(PLGGetResult) (CNXKEY, void *, int, int *, bool);
XTRN int CNXFUNC(PLGDisconnect) (CNXKEY);
XTRN int CNXFUNC(PLGGetErrorMsg) (CNXKEY, char *, int, int *);
XTRN bool CNXFUNC(PLGGetCharValue)(CNXKEY, char *, int, int);
XTRN bool CNXFUNC(PLGGetIntValue)(CNXKEY, int *, int);
XTRN bool CNXFUNC(PLGGetColValue) (CNXKEY, int *, int, int);
XTRN bool CNXFUNC(PLGGetMessage) (CNXKEY, char *, int);
XTRN bool CNXFUNC(PLGGetHeader) (CNXKEY, char *, int, int);
#ifdef __cplusplus
}
#endif
//#endif /* !NO_FUNC */
/**************************************************************************/
/* Convenience function Definitions */
/**************************************************************************/
#define PLGPostCommand(T,C) PLGSendCommand(T,C,NULL,0,NULL)
#if defined(FNCMAC)
#define PLGGetProgMsg(T,C,S) PLGGetCharValue(T,C,S,K_ProgMsg)
#define PLGGetLangID(T,C,S) PLGGetCharValue(T,C,S,K_Lang)
#define PLGGetActiveDB(T,C,S) PLGGetCharValue(T,C,S,K_ActiveDB)
#define PLGGetCursorPos(T,L) PLGGetIntValue(T,L,K_CurPos)
#define PLGGetResultType(T,L) PLGGetIntValue(T,L,K_Result)
#define PLGGetNBcol(T,L) PLGGetIntValue(T,L,K_NBcol)
#define PLGGetNBlin(T,L) PLGGetIntValue(T,L,K_NBlin)
#define PLGGetRetCode(T,L) PLGGetIntValue(T,L,K_RC)
#define PLGGetElapsed(T,L) PLGGetIntValue(T,L,K_Elapsed)
#define PLGGetContinued(T,L) PLGGetIntValue(T,L,K_Continued)
#define PLGGetMaxSize(T,L) PLGGetIntValue(T,L,K_Maxsize)
#define PLGGetLength(T,L,C) PLGGetColValue(T,L,K_Length,C)
#define PLGGetDataSize(T,L,C) PLGGetColValue(T,L,K_DataLen,C)
#define PLGGetDecimal(T,L,C) PLGGetColValue(T,L,K_Prec,C)
#define PLGGetType(T,L,C) PLGGetColValue(T,L,K_Type,C)
#endif /* FNCMAC */
#endif // NOT_USED
#endif /* !_PLGCNX_H */
/* ------------------------- End of Plgcnx.h ---------------------------- */

510
storage/connect/plgdbsem.h Normal file
View File

@@ -0,0 +1,510 @@
/************** PlgDBSem H Declares Source Code File (.H) **************/
/* Name: PLGDBSEM.H Version 3.5 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 1998-2012 */
/* */
/* This file contains the PlugDB++ application type definitions. */
/***********************************************************************/
/***********************************************************************/
/* Include required application header files */
/***********************************************************************/
#include "checklvl.h"
/***********************************************************************/
/* DB Constant definitions. */
/***********************************************************************/
#if defined(FRENCH)
#define DEFAULT_LOCALE "French"
#else // !FRENCH
#define DEFAULT_LOCALE "English"
#endif // !FRENCH
#define DOS_MAX_PATH 144 /* Must be the same across systems */
#define DOS_BUFF_LEN 100 /* Number of lines in binary file buffer */
#undef DOMAIN /* For Unix version */
enum BLKTYP {TYPE_TABLE = 50, /* Table Name/Correl Block */
TYPE_COLUMN = 51, /* Column Name/Correl Block */
// TYPE_OPVAL = 52, /* Operator value (OPVAL) */
TYPE_TDB = 53, /* Table Description Block */
TYPE_COLBLK = 54, /* Column Description Block */
TYPE_PSZ = 64, /* Pointer to String ended by 0 */
TYPE_SQL = 65, /* Pointer to SQL block */
TYPE_XOBJECT = 69, /* Extended DB object */
TYPE_COLCRT = 71, /* Column creation block */
TYPE_CONST = 72, /* Constant */
// TYPE_INDEXDEF = 73, /* Index definition block */
// TYPE_OPER = 74, /* Operator block (OPER) */
/*-------------------- type tokenized string --------------------------*/
TYPE_DATE = 8, /* Timestamp */
/*-------------------- additional values used by LNA ------------------*/
TYPE_COLIST = 14, /* Column list */
TYPE_COL = 41, /* Column */
/*-------------------- types used by scalar functions -----------------*/
TYPE_NUM = 12,
TYPE_UNDEF = 13,
/*-------------------- file blocks used when closing ------------------*/
TYPE_FB_FILE = 22, /* File block (stream) */
TYPE_FB_MAP = 23, /* Mapped file block (storage) */
TYPE_FB_HANDLE = 24, /* File block (handle) */
TYPE_FB_XML = 21, /* DOM XML file block */
TYPE_FB_XML2 = 27}; /* libxml2 XML file block */
enum AMT {TYPE_AM_ERROR = 0, /* Type not defined */
TYPE_AM_ROWID = 1, /* ROWID type (special column) */
TYPE_AM_FILID = 2, /* FILEID type (special column) */
TYPE_AM_TAB = 3, /* Table (any type) */
TYPE_AM_VIEW = 4, /* VIEW (any type) */
TYPE_AM_SRVID = 5, /* SERVID type (special column) */
TYPE_AM_TABID = 6, /* TABID type (special column) */
TYPE_AM_CNSID = 7, /* CONSTID type (special column) */
TYPE_AM_COUNT = 10, /* CPT AM type no (count table) */
TYPE_AM_DCD = 20, /* Decode access method type no */
TYPE_AM_CMS = 30, /* CMS access method type no */
TYPE_AM_MAP = 32, /* MAP access method type no */
TYPE_AM_FMT = 33, /* DOS files with formatted recs */
TYPE_AM_CSV = 34, /* DOS files with CSV records */
TYPE_AM_MCV = 35, /* MAP files with CSV records */
TYPE_AM_DOS = 36, /* DOS am with Lrecl = V */
TYPE_AM_FIX = 38, /* DOS am with Lrecl = F */
TYPE_AM_BIN = 39, /* DOS am with Lrecl = B */
TYPE_AM_VCT = 40, /* VCT access method type no */
TYPE_AM_VMP = 43, /* VMP access method type no */
TYPE_AM_QRY = 50, /* QRY access method type no */
TYPE_AM_QRS = 51, /* QRYRES access method type no */
TYPE_AM_SQL = 60, /* SQL VIEW access method type */
TYPE_AM_PLG = 70, /* PLG access method type no */
TYPE_AM_PLM = 71, /* PDM access method type no */
TYPE_AM_DOM = 80, /* DOM access method type no */
TYPE_AM_DIR = 90, /* DIR access method type no */
TYPE_AM_ODBC = 100, /* ODBC access method type no */
TYPE_AM_OEM = 110, /* OEM access method type no */
TYPE_AM_TBL = 115, /* TBL access method type no */
TYPE_AM_PIVOT = 120, /* PIVOT access method type no */
TYPE_AM_SRC = 121, /* PIVOT multiple column type no */
TYPE_AM_FNC = 122, /* PIVOT source column type no */
TYPE_AM_XTB = 130, /* SYS table access method type */
TYPE_AM_MAC = 137, /* MAC table access method type */
TYPE_AM_WMI = 139, /* WMI table access method type */
TYPE_AM_XCL = 140, /* SYS column access method type */
TYPE_AM_INI = 150, /* INI files access method */
TYPE_AM_TFC = 155, /* TFC (Circa) (Fuzzy compare) */
TYPE_AM_DBF = 160, /* DBF Dbase files am type no */
TYPE_AM_JCT = 170, /* Junction tables am type no */
TYPE_AM_DMY = 172, /* DMY Dummy tables am type no */
TYPE_AM_SET = 180, /* SET Set tables am type no */
TYPE_AM_MYSQL = 192, /* MYSQL access method type no */
TYPE_AM_OUT = 200}; /* Output relations (storage) */
enum RECFM {RECFM_NAF = -2, /* Not a file */
RECFM_OEM = -1, /* OEM file access method */
RECFM_VAR = 0, /* Varying length DOS files */
RECFM_FIX = 1, /* Fixed length DOS files */
RECFM_BIN = 2, /* Binary DOS files (also fixed) */
RECFM_VCT = 3, /* VCT formatted files */
RECFM_ODBC = 4, /* Table accessed via ODBC */
RECFM_PLG = 5, /* Table accessed via PLGconn */
RECFM_DBF = 6}; /* DBase formatted file */
#if 0
enum MISC {DB_TABNO = 1, /* DB routines in Utility Table */
MAX_MULT_KEY = 10, /* Max multiple key number */
NAM_LEN = 128, /* Length of col and tab names */
ARRAY_SIZE = 50, /* Default array block size */
MAXRES = 500, /* Default maximum result lines */
MAXLIN = 10000, /* Default maximum data lines */
MAXBMP = 32}; /* Default XDB2 max bitmap size */
enum ALGMOD {AMOD_AUTO = 0, /* PLG chooses best algorithm */
AMOD_SQL = 1, /* Use SQL algorithm */
AMOD_QRY = 2}; /* Use QUERY algorithm */
#else // !0
#define NAM_LEN 128
#endif // !0
enum MODE {MODE_ANY = 0, /* Unspecified mode */
MODE_READ = 10, /* Input/Output mode */
MODE_WRITE = 20, /* Input/Output mode */
MODE_UPDATE = 30, /* Input/Output mode */
MODE_INSERT = 40, /* Input/Output mode */
MODE_DELETE = 50}; /* Input/Output mode */
#if !defined(RC_OK_DEFINED)
#define RC_OK_DEFINED
enum RCODE {RC_OK = 0, /* No error return code */
RC_NF = 1, /* Not found return code */
RC_EF = 2, /* End of file return code */
RC_FX = 3, /* Error return code */
RC_INFO = 4}; /* Success with info */
#endif // !RC_OK_DEFINED
enum OPVAL {OP_EQ = 1, /* Filtering operator = */
OP_NE = 2, /* Filtering operator != */
OP_GT = 3, /* Filtering operator > */
OP_GE = 4, /* Filtering operator >= */
OP_LT = 5, /* Filtering operator < */
OP_LE = 6, /* Filtering operator <= */
OP_IN = 7, /* Filtering operator IN */
OP_NULL = 8, /* Filtering operator IS NULL */
OP_EXIST = 9, /* Filtering operator EXISTS */
OP_LIKE = 10, /* Filtering operator LIKE */
OP_LOJ = -1, /* Filter op LEFT OUTER JOIN */
OP_ROJ = -2, /* Filter op RIGHT OUTER JOIN */
OP_DTJ = -3, /* Filter op DISTINCT JOIN */
OP_XX = 11, /* Filtering operator unknown */
OP_AND = 12, /* Filtering operator AND */
OP_OR = 13, /* Filtering operator OR */
OP_CNC = 14, /* Expression Concat operator */
OP_NOT = 15, /* Filtering operator NOT */
OP_SEP = 20, /* Filtering separator */
OP_ADD = 16, /* Expression Add operator */
OP_SUB = 17, /* Expression Substract operator */
OP_MULT = 18, /* Expression Multiply operator */
OP_DIV = 19, /* Expression Divide operator */
OP_NOP = 21, /* Scalar function is nopped */
OP_NUM = 22, /* Scalar function Op Num */
OP_ABS = 23, /* Scalar function Op Abs */
OP_MAX = 24, /* Scalar function Op Max */
OP_MIN = 25, /* Scalar function Op Min */
OP_CEIL = 26, /* Scalar function Op Ceil */
OP_FLOOR = 27, /* Scalar function Op Floor */
OP_MOD = 28, /* Scalar function Op Mod */
OP_ROUND = 29, /* Scalar function Op Round */
OP_SIGN = 30, /* Scalar function Op Sign */
OP_LEN = 31, /* Scalar function Op Len */
OP_INSTR = 32, /* Scalar function Op Instr */
OP_LEFT = 33, /* Scalar function Op Left */
OP_RIGHT = 34, /* Scalar function Op Right */
OP_ASCII = 35, /* Scalar function Op Ascii */
OP_EXP = 36, /* Scalar function Op Exp */
OP_LN = 37, /* Scalar function Op Ln */
OP_LOG = 38, /* Scalar function Op Log */
OP_POWER = 39, /* Scalar function Op Power */
OP_SQRT = 40, /* Scalar function Op Sqrt */
OP_COS = 41, /* Scalar function Op Cos */
OP_COSH = 42, /* Scalar function Op Cosh */
OP_SIN = 43, /* Scalar function Op Sin */
OP_SINH = 44, /* Scalar function Op Sinh */
OP_TAN = 45, /* Scalar function Op Tan */
OP_TANH = 46, /* Scalar function Op Tanh */
OP_USER = 47, /* Scalar function Op User */
OP_CHAR = 48, /* Scalar function Op Char */
OP_UPPER = 49, /* Scalar function Op Upper */
OP_LOWER = 50, /* Scalar function Op Lower */
OP_RPAD = 51, /* Scalar function Op Rpad */
OP_LPAD = 52, /* Scalar function Op Lpad */
OP_LTRIM = 53, /* Scalar function Op Ltrim */
OP_RTRIM = 54, /* Scalar function Op Rtrim */
OP_REPL = 55, /* Scalar function Op Replace */
OP_SUBST = 56, /* Scalar function Op Substr */
OP_LJUST = 57, /* Scalar function Op Ljustify */
OP_RJUST = 58, /* Scalar function Op Rjustify */
OP_CJUST = 59, /* Scalar function Op Cjustify */
OP_ENCODE = 60, /* Scalar function Op Encode */
OP_DECODE = 61, /* Scalar function Op Decode */
OP_SEQU = 62, /* Scalar function Op Sequence */
OP_IF = 63, /* Scalar function Op If */
OP_STRING = 64, /* Scalar function Op String */
OP_TOKEN = 65, /* Scalar function Op Token */
OP_SNDX = 66, /* Scalar function Op Soundex */
OP_DATE = 67, /* Scalar function Op Date */
OP_MDAY = 68, /* Scalar function Op Month Day */
OP_MONTH = 69, /* Scalar function Op Month of */
OP_YEAR = 70, /* Scalar function Op Year of */
OP_WDAY = 71, /* Scalar function Op Week Day */
OP_YDAY = 72, /* Scalar function Op Year Day */
OP_DBTWN = 73, /* Scalar function Op Days betwn */
OP_MBTWN = 74, /* Scalar function Op Months btw */
OP_YBTWN = 75, /* Scalar function Op Years btwn */
OP_ADDAY = 76, /* Scalar function Op Add Days */
OP_ADDMTH = 77, /* Scalar function Op Add Months */
OP_ADDYR = 78, /* Scalar function Op Add Years */
OP_NXTDAY = 79, /* Scalar function Op Next Day */
OP_SYSDT = 80, /* Scalar function Op SysDate */
OP_DELTA = 81, /* Scalar function Op Delta */
OP_LAST = 82, /* Scalar function Op Last */
OP_IFF = 83, /* Scalar function Op Iff */
OP_MAVG = 84, /* Scalar function Op Moving Avg */
OP_VWAP = 85, /* Scalar function Op VWAP */
OP_TIME = 86, /* Scalar function Op TIME */
OP_SETLEN = 87, /* Scalar function Op Set Length */
OP_TRANSL = 88, /* Scalar function Op Translate */
OP_BITAND = 89, /* Expression BitAnd operator */
OP_BITOR = 90, /* Expression BitOr operator */
OP_BITXOR = 91, /* Expression XOR operator */
OP_BITNOT = 92, /* Expression Complement operator*/
OP_CNTIN = 93, /* Scalar function Count In */
OP_FDISK = 94, /* Scalar function Disk of fileid*/
OP_FPATH = 95, /* Scalar function Path of fileid*/
OP_FNAME = 96, /* Scalar function Name of fileid*/
OP_FTYPE = 97, /* Scalar function Type of fileid*/
OP_XDATE = 98, /* Scalar function Op Fmt Date */
OP_SWITCH = 99, /* Scalar function Op Switch */
OP_EXIT = 100, /* Scalar function Op Exit */
OP_LIT = 101, /* Scalar function Op Literal */
OP_LOCALE = 102, /* Scalar function Op Locale */
OP_FRNCH = 103, /* Scalar function Op French */
OP_ENGLSH = 104, /* Scalar function Op English */
OP_RAND = 105, /* Scalar function Op Rand(om) */
OP_FIRST = 106, /* Index operator Find First */
OP_NEXT = 107, /* Index operator Find Next */
OP_SAME = 108, /* Index operator Find Next Same */
OP_FSTDIF = 109, /* Index operator Find First dif */
OP_NXTDIF = 110, /* Index operator Find Next dif */
OP_VAL = 111, /* Scalar function Op Valist */
OP_QUART = 112, /* Scalar function Op QUARTER */
OP_CURDT = 113, /* Scalar function Op CurDate */
OP_NWEEK = 114, /* Scalar function Op Week number*/
OP_ROW = 115, /* Scalar function Op Row */
OP_SYSTEM = 200, /* Scalar function Op System */
OP_REMOVE = 201, /* Scalar function Op Remove */
OP_RENAME = 202, /* Scalar function Op Rename */
OP_FCOMP = 203}; /* Scalar function Op Compare */
enum TUSE {USE_NO = 0, /* Table is not yet linearized */
USE_LIN = 1, /* Table is linearized */
USE_READY = 2, /* Column buffers are allocated */
USE_OPEN = 3, /* Table is open */
USE_CNT = 4, /* Specific to LNA */
USE_NOKEY = 5}; /* Specific to SqlToHql */
/***********************************************************************/
/* Following definitions are used to indicate the status of a column. */
/***********************************************************************/
enum STATUS {BUF_NO = 0x00, /* Column buffer not allocated */
BUF_EMPTY = 0x01, /* Column buffer is empty */
BUF_READY = 0x02, /* Column buffer is ready */
BUF_READ = 0x04, /* Column buffer has read value */
BUF_MAPPED = 0x08}; /* Used by the VMPFAM class */
/***********************************************************************/
/* Following definitions are used to indicate how a column is used. */
/* Corresponding bits are ON if the column is used in: */
/***********************************************************************/
enum COLUSE {U_P = 0x01, /* the projection list. */
U_J_EXT = 0x02, /* a join filter. */
U_J_INT = 0x04, /* a join after linearisation. */
/*-- Such a column have a constant value throughout a subquery eval. --*/
U_CORREL = 0x08, /* a correlated sub-query */
/*-------------------- additional values used by CONNECT --------------*/
U_VAR = 0x10, /* a VARCHAR column */
U_VIRTUAL = 0x20, /* a VIRTUAL column */
U_NULLS = 0x40, /* The column may have nulls */
U_IS_NULL = 0x80}; /* The column has a null value */
/***********************************************************************/
/* DB description class and block pointer definitions. */
/***********************************************************************/
typedef class XTAB *PTABLE;
typedef class COLUMN *PCOLUMN;
typedef class XOBJECT *PXOB;
typedef class COLBLK *PCOL;
typedef class TBX *PTBX;
typedef class TDB *PTDB;
typedef void *PSQL; // Not used
typedef class TDBASE *PTDBASE;
typedef class TDBDOS *PTDBDOS;
typedef class TDBFIX *PTDBFIX;
typedef class TDBFMT *PTDBFMT;
typedef class TDBCSV *PTDBCSV;
typedef class TDBDOM *PTDBDOM;
typedef class TDBDIR *PTDBDIR;
typedef class DOSCOL *PDOSCOL;
typedef class CSVCOL *PCSVCOL;
typedef class MAPCOL *PMAPCOL;
typedef class TDBMFT *PTDBMFT;
typedef class TDBMCV *PTDBMCV;
typedef class MCVCOL *PMCVCOL;
typedef class RESCOL *PRESCOL;
typedef class XXBASE *PKXBASE;
typedef class KXYCOL *PXCOL;
typedef class CATALOG *PCATLG;
typedef class RELDEF *PRELDEF;
typedef class TABDEF *PTABDEF;
typedef class DOSDEF *PDOSDEF;
typedef class CSVDEF *PCSVDEF;
typedef class VCTDEF *PVCTDEF;
typedef class PIVOTDEF *PPIVOTDEF;
typedef class DOMDEF *PDOMDEF;
typedef class DIRDEF *PDIRDEF;
typedef class OEMDEF *POEMDEF;
typedef class COLCRT *PCOLCRT;
typedef class COLDEF *PCOLDEF;
typedef class CONSTANT *PCONST;
typedef class VALUE *PVAL;
typedef class VALBLK *PVBLK;
typedef struct _fblock *PFBLOCK;
typedef struct _mblock *PMBLOCK;
typedef struct _cblock *PCBLOCK;
typedef struct _tabs *PTABS;
typedef struct _qryres *PQRYRES;
typedef struct _colres *PCOLRES;
typedef struct _datpar *PDTP;
typedef struct indx_used *PXUSED;
/***********************************************************************/
/* Utility blocks for file and storage. */
/***********************************************************************/
typedef struct _fblock { /* Opened (mapped) file block */
struct _fblock *Next;
LPCSTR Fname; /* Point on file name */
size_t Length; /* File length (<4GB) */
short Count; /* Nb of times map is used */
short Type; /* TYPE_FB_FILE or TYPE_FB_MAP */
MODE Mode; /* Open mode */
char *Memory; /* Pointer to file mapping view */
void *File; /* FILE pointer */
HANDLE Handle; /* File handle */
} FBLOCK;
typedef struct _mblock { /* Memory block */
PMBLOCK Next;
bool Inlist; /* True if in mblock list */
size_t Size; /* Size of allocation */
bool Sub; /* True if suballocated */
void *Memp; /* Memory pointer */
} MBLOCK;
/***********************************************************************/
/* The QUERY application User Block. */
/***********************************************************************/
typedef struct { /* User application block */
//void *Act2; /* RePoint to activity block */
//short LineLen; /* Current output line len */
NAME Name; /* User application name */
//NAME Password; /* User application password */
//PSZ UserFile; /* User application filename */
char Server[17]; /* Server name */
char DBName[17]; /* Current database name */
//char Host[65]; /* Caller's host name */
//char User[17]; /* Caller's user name */
//uint Granted; /* Grant bitmap */
PCATLG Catalog; /* To CATALOG class */
PQRYRES Result; /* To query result blocks */
PFBLOCK Openlist; /* To file/map open list */
PMBLOCK Memlist; /* To memory block list */
PXUSED Xlist; /* To used index list */
//int Maxres; /* Result Max nb of lines */
//int Maxtmp; /* Intermediate tables Maxres */
//int Maxlin; /* Query Max nb of data lines */
//int Maxbmp; /* Maximum XDB2 bitmap size */
int Check; /* General level of checking */
int Numlines; /* Number of lines involved */
//ALGMOD AlgChoice; /* Choice of algorithm mode */
//AREADEF DescArea; /* Table desc. area size */
USETEMP UseTemp; /* Use temporary file */
//int Curtype; /* 0: static else: dynamic */
int Vtdbno; /* Used for TDB number setting */
bool Remote; /* true: if remotely called */
//bool NotFinal; /* true: for intermediate table */
bool Proginfo; /* true: return progress info */
bool Subcor; /* Used for Progress info */
size_t ProgMax; /* Used for Progress info */
size_t ProgCur; /* Used for Progress info */
size_t ProgSav; /* Used for Progress info */
LPCSTR Step; /* Execution step name */
//char Work[_MAX_PATH]; /* Local work path */
} DBUSERBLK, *PDBUSER;
/***********************************************************************/
/* Column output format. */
/***********************************************************************/
typedef struct _format { /* Format descriptor block */
char Type[2]; /* C:char, F:double, N:int, Dx: date */
ushort Length; /* Output length */
short Prec; /* Output precision */
} FORMAT, *PFORMAT;
/***********************************************************************/
/* Definition of blocks used in type and copy routines. */
/***********************************************************************/
typedef struct _tabptr { /* start=P1 */
struct _tabptr *Next;
int Num; /* alignement */
void *Old[50];
void *New[50]; /* old and new values of copied ptrs */
} TABPTR, *PTABPTR;
typedef struct _tabadr { /* start=P3 */
struct _tabadr *Next;
int Num;
void *Adx[50]; /* addr of pointers to be reset */
} TABADR, *PTABADR;
typedef struct _tabs {
PGLOBAL G;
PTABPTR P1;
PTABADR P3;
} TABS;
/***********************************************************************/
/* Result of last SQL noconv query. */
/***********************************************************************/
typedef struct _qryres {
PCOLRES Colresp; /* Points to columns of result */
bool Continued; /* true when more rows to fetch */
bool Truncated; /* true when truncated by maxres */
bool Suball; /* true when entirely suballocated */
bool Info; /* true when info msg generated */
int Maxsize; /* Max query number of lines */
int Maxres; /* Allocation size */
int Nblin; /* Number of rows in result set */
int Nbcol; /* Number of columns in result set */
int Cursor; /* Starting position to get data */
int BadLines; /* Skipped bad lines in table file */
} QRYRES, *PQRYRES;
typedef struct _colres {
PCOLRES Next; /* To next result column */
PCOL Colp; /* To matching column block */
PSZ Name; /* Column header */
PVBLK Kdata; /* Column block of values */
char *Nulls; /* Column null value array */
int Type; /* Internal type */
int DBtype; /* Data type */
int Datasize; /* Overall data size */
int Ncol; /* Column number */
int Clen; /* Data individual internal size */
int Length; /* Data individual print length */
int Prec; /* Precision */
} COLRES;
#if defined(WIN32) && !defined(NOEX)
#define DllExport __declspec( dllexport )
#else // !WIN32
#define DllExport
#endif // !WIN32
/***********************************************************************/
/* Utility routines. */
/***********************************************************************/
PPARM Vcolist(PGLOBAL, PTDB, PSZ, bool);
void PlugPutOut(PGLOBAL, FILE *, short, void *, uint);
void PlugLineDB(PGLOBAL, PSZ, short, void *, uint);
char *PlgGetDataPath(PGLOBAL g);
void *PlgDBalloc(PGLOBAL, void *, MBLOCK&);
void *PlgDBrealloc(PGLOBAL, void *, MBLOCK&, size_t);
void AddPointer(PTABS, void *);
PDTP MakeDateFormat(PGLOBAL, PSZ, bool, bool, int);
int ExtractDate(char *, PDTP, int, int val[6]);
/***********************************************************************/
/* Exported utility routines. */
/***********************************************************************/
DllExport FILE *PlugOpenFile(PGLOBAL, LPCSTR, LPCSTR);
DllExport int PlugCloseFile(PGLOBAL, PFBLOCK, bool all = false);
DllExport void PlugCleanup(PGLOBAL, bool);
DllExport bool GetPromptAnswer(PGLOBAL, char *);
DllExport char *GetAmName(PGLOBAL g, AMT am, void *memp = NULL);
DllExport PDBUSER PlgMakeUser(PGLOBAL g);
DllExport PDBUSER PlgGetUser(PGLOBAL g);
DllExport PCATLG PlgGetCatalog(PGLOBAL g, bool jump = true);
DllExport bool PlgSetXdbPath(PGLOBAL g, PSZ, PSZ, char *, int, char *, int);
DllExport void PlgDBfree(MBLOCK&);
DllExport PSZ GetIniString(PGLOBAL, void *, LPCSTR, LPCSTR, LPCSTR, LPCSTR);
DllExport int GetIniSize(char *, char *, char *, char *);
DllExport bool WritePrivateProfileInt(LPCSTR, LPCSTR, int, LPCSTR);
DllExport void NewPointer(PTABS, void *, void *);

1475
storage/connect/plgdbutl.cpp Normal file

File diff suppressed because it is too large Load Diff

230
storage/connect/plgodbc.h Normal file
View File

@@ -0,0 +1,230 @@
/***********************************************************************/
/* PLGODBC.H - This is the ODBC PlugDB driver include file. */
/***********************************************************************/
//efine WINVER 0x0300 // prevent Windows 3.1 feature usage
#include <windows.h> /* Windows include file */
#include <windowsx.h> /* Message crackers */
#include <commctrl.h>
/***********************************************************************/
/* Included C-definition files required by the interface. */
/***********************************************************************/
#include <string.h> /* String manipulation declares */
#include <stdlib.h> /* C standard library */
#include <ctype.h> /* C language specific types */
#include <stdio.h> /* FOPEN_MAX declaration */
#include <time.h> /* time_t type declaration */
/***********************************************************************/
/* ODBC interface of PlugDB driver declares. */
/***********************************************************************/
#include "podbcerr.h" /* Resource ID for PlugDB Driver */
#if !defined(WIN32)
#include "w16macro.h"
#endif
#define ODBCVER 0x0300
#include "sqltypes.h"
#include "sql.h"
#include "sqlext.h"
/***********************************************************************/
/* Definitions to be used in function prototypes. */
/* The SQL_API is to be used only for those functions exported for */
/* driver manager use. */
/* The EXPFUNC is to be used only for those functions exported but */
/* used internally, ie, dialog procs. */
/* The INTFUNC is to be used for all other functions. */
/***********************************************************************/
#if defined(WIN32)
#define INTFUNC __stdcall
#define EXPFUNC __stdcall
#else
#define INTFUNC FAR PASCAL
#define EXPFUNC __export CALLBACK
#endif
/***********************************************************************/
/* External variables. */
/***********************************************************************/
extern HINSTANCE NEAR s_hModule; // DLL handle.
#ifdef DEBTRACE
extern FILE *debug;
#endif
extern bool clearerror;
/***********************************************************************/
/* Additional values used by PlugDB for ODBC. */
/***********************************************************************/
#define RES_TYPE_PREPARE 1 /* Result from SQLPrepare */
#define RES_TYPE_CATALOG 2 /* Result from catalog funcs */
#define MAXPATHLEN _MAX_PATH /* Max path length */
#define MAXKEYLEN 16 /* Max keyword length */
#define MAXDESC 256 /* Max description length */
#define MAXDSNAME 33 /* Max data source name length */
#define MAXCRNAME 18 /* Max stmt cursor name length */
#define DEFMAXRES 6300 /* Default MaxRes value */
#define NAM_LEN 128 /* Length of col and tab names */
#define MAXRESULT 1000 /* ? */
#define MAXCOMMAND 200 /* ? */
#define RC_ERROR RC_LAST-1
#define RC_FREE 3
#if !defined(NOLIB)
#define CNXKEY uint /* C Key returned by Conn DLL */
#else
typedef struct _conninfo *PCONN;
#endif /* !NOLIB */
#if defined(DEBTRACE)
#define TRACE0(X) fprintf(debug,X);
#define TRACE1(X,A) fprintf(debug,X,A);
#define TRACE2(X,A,B) fprintf(debug,X,A,B);
#define TRACE3(X,A,B,C) fprintf(debug,X,A,B,C);
#define TRACE4(X,A,B,C,D) fprintf(debug,X,A,B,C,D);
#define TRACE5(X,A,B,C,D,E) fprintf(debug,X,A,B,C,D,E);
#define TRACE6(X,A,B,C,D,E,F) fprintf(debug,X,A,B,C,D,E,F);
#else /* !DEBTRACE*/
#define TRACE0(X)
#define TRACE1(X,A)
#define TRACE2(X,A,B)
#define TRACE3(X,A,B,C)
#define TRACE4(X,A,B,C,D)
#define TRACE5(X,A,B,C,D,E)
#define TRACE6(X,A,B,C,D,E,F)
#endif /* !DEBTRACE*/
// This definition MUST be identical to the value in plgdbsem.h
#define XMOD_PREPARE 1
/***********************************************************************/
/* ODBC.INI keywords (use extern definition in SETUP.C) */
/***********************************************************************/
extern char const *EMPTYSTR; /* Empty String */
extern char const *OPTIONON;
extern char const *OPTIONOFF;
extern char const *INI_SDEFAULT; /* Default data source name */
extern char const *ODBC_INI; /* ODBC initialization file */
extern char const *INI_KDEFL; /* Is SQL to use by default? */
extern char const *INI_KLANG; /* Application language */
extern char const *INI_KDATA; /* Data description file */
extern char const *INI_KSVR; /* PLG Server */
/************************************************************************/
/* Attribute key indexes (into an array of Attr structs, see below) */
/************************************************************************/
#define KEY_DSN 0
#define KEY_DEFL 1
#define KEY_LANG 2
#define KEY_DATA 3
#define KEY_SERVER 4
#define LAST_KEY 5 /* Number of keys in TAG's */
#define KEY_DESC 5
#define KEY_TRANSNAME 6
#define KEY_TRANSOPTION 7
#define KEY_TRANSDLL 8
#define NUMOFKEYS 9 /* Number of keys supported */
#define FOURYEARS 126230400 // Four years in seconds (1 leap)
/***********************************************************************/
/* This is used when an "out of memory" error happens, because this */
/* error recording system allocates memory when it logs an error, */
/* and it would be bad if it tried to allocate memory when it got an */
/* out of memory error. */
/***********************************************************************/
typedef enum _ERRSTAT {
errstatOK,
errstatNO_MEMORY,
} ERRSTAT;
/***********************************************************************/
/* Types */
/***********************************************************************/
typedef struct TagAttr {
bool fSupplied;
char Attr[MAXPATHLEN];
} TAG, *PTAG;
typedef struct _parscons { /* Parse constants */
int Slen; /* String length */
int Ntag; /* Number of entries in tags */
int Nlook; /* Number of entries in lookup */
char Sep; /* Separator */
} PARC, *PPARC;
/***********************************************************************/
/* Attribute string look-up table (maps keys to associated indexes) */
/***********************************************************************/
typedef struct _Look {
const char *szKey;
int iKey;
} LOOK, *PLOOK;
/***********************************************************************/
/* This is info about a single error. */
/***********************************************************************/
typedef struct _ERRBLK *PERRBLK;
typedef struct _ERRBLK {
PERRBLK Next; /* Next block in linked list of error blocks */
DWORD Native_Error; /* Native error */
DWORD Stderr; /* SQLC error code */
PSZ Message; /* Points to text of message */
} ERRBLK;
/***********************************************************************/
/* This is a header block, it records information about a list of */
/* errors (ERRBLOCK's). */
/***********************************************************************/
typedef struct _ERRINFO {
PERRBLK First; /* First block in linked list of error blocks. */
PERRBLK Last; /* Last block in above list. */
ERRSTAT Errstat; /* Status for special condition out of memory */
} ERRINFO, *PERRINFO;
/***********************************************************************/
/* Environment information. */
/***********************************************************************/
typedef struct _env {
ERRINFO Errinfo; /* Error list */
UDWORD ODBCver;
UDWORD ODBCdateformat;
} ENV, *PENV;
/***********************************************************************/
/* Classes used in the PlugDB ODBC Driver. */
/***********************************************************************/
typedef class DBC *PDBC;
typedef class STMT *PSTMT;
typedef class CURSOR *PCURSOR;
typedef class RESULT *PRESULT;
typedef class BINDDATA *PBIND;
typedef class BINDPARM *PBDPARM;
typedef class CPLGdrv *PSCDRV;
typedef class DESCRIPTOR *PDSC;
/***********************************************************************/
/* ODBC Prototypes. */
/***********************************************************************/
void PostSQLError(HENV, HDBC, HSTMT, DWORD, DWORD, PSZ);
void ClearSQLError(HENV, HDBC, HSTMT);
short LoadRcString(UWORD, LPSTR, short);
RETCODE RetcodeCopyBytes(HDBC, HSTMT, UCHAR FAR *, SWORD,
SWORD FAR *, UCHAR FAR *, SWORD, bool);
/***********************************************************************/
/* Private functions used by the driver. */
/***********************************************************************/
bool EXPFUNC FDriverConnectProc(HWND, WORD, WPARAM, LPARAM);
extern void ParseAttrString(PLOOK, PTAG, UCHAR FAR *, PPARC);
RETCODE PASCAL StringCopy(HDBC, HSTMT, PTR, SWORD, SWORD FAR *,
char FAR *);
RETCODE PASCAL ShortCopy(HDBC, HSTMT, PTR, SWORD, SWORD FAR *, short);
RETCODE PASCAL LongCopy(HDBC, HSTMT, PTR, SWORD, SWORD FAR *, int);
RETCODE PASCAL GeneralCopy(HDBC, HSTMT, PTR, SWORD,
SWORD FAR *, PTR, SWORD);
/* --------------------- End of PLGODBC.H ---------------------------- */

140
storage/connect/plgxml.cpp Normal file
View File

@@ -0,0 +1,140 @@
/******************************************************************/
/* Implementation of XML document processing using PdbXML. */
/* Author: Olivier Bertrand 2007-2012 */
/******************************************************************/
#include "my_global.h"
#include "global.h"
#include "plgdbsem.h"
#include "block.h"
#include "plgxml.h"
#if !defined(DOMDOC_SUPPORT)
PXDOC GetDomDoc(PGLOBAL g, char *nsl, char *nsdf,
char *enc, PFBLOCK fp)
{
strcpy(g->Message, MSG(DOM_NOT_SUPP));
return NULL;
} // end of GetDomDoc
#endif // !DOMDOC_SUPPORT
#if defined(NOXML2)
PXDOC GetLibxmlDoc(PGLOBAL g, char *nsl, char *nsdf,
char *enc, PFBLOCK fp)
{
strcpy(g->Message, "libxml2 not supported");
return NULL;
} // end of GetLibxmlDoc
#endif // NOXML2
/******************************************************************/
/* XMLDOCUMENT constructor. */
/******************************************************************/
XMLDOCUMENT::XMLDOCUMENT(char *nsl, char *nsdf, char *enc)
{
Namespaces = NULL;
Encoding = enc;
Nslist = nsl;
DefNs = nsdf;
} // end of XMLDOCUMENT constructor
/******************************************************************/
/* Make the namespace structure list. */
/******************************************************************/
bool XMLDOCUMENT::MakeNSlist(PGLOBAL g)
{
char *prefix, *href, *next = Nslist;
PNS nsp, *ppns = &Namespaces;
while (next) {
// Skip spaces
while ((*next) == ' ')
next++;
if ((*next) == '\0')
break;
// Find prefix
prefix = next;
next = strchr(next, '=');
if (next == NULL) {
strcpy(g->Message, MSG(BAS_NS_LIST));
return true;
} // endif next
*(next++) = '\0';
// Find href
href = next;
next = strchr(next, ' ');
if (next != NULL)
*(next++) = '\0';
// Allocate and link NS structure
nsp = (PNS)PlugSubAlloc(g, NULL, sizeof(NS));
nsp->Next = NULL;
nsp->Prefix = prefix;
nsp->Uri = href;
*ppns = nsp;
ppns = &nsp->Next;
} // endwhile next
return false;
} // end of MakeNSlist
/******************************************************************/
/* XMLNODE constructor. */
/******************************************************************/
XMLNODE::XMLNODE(PXDOC dp)
{
Doc = dp;
Next = NULL;
Children = NULL;
Buf = NULL;
Len = -1;
} // end of XMLNODE constructor
/******************************************************************/
/* Attach new node at the end of this node children list. */
/******************************************************************/
PXNODE XMLNODE::NewChild(PXNODE ncp)
{
PXNODE np, *pnp = &Children;
for (np = *pnp; np; np = np->Next)
pnp = &np->Next;
*pnp = np;
return ncp;
} // end of NewChild
/******************************************************************/
/* Delete a node from this node children list. */
/******************************************************************/
void XMLNODE::Delete(PXNODE dnp)
{
PXNODE *pnp = &Children;
for (PXNODE np = *pnp; np; np = np->Next)
if (np == dnp) {
*pnp = dnp->Next;
break;
} else
pnp = &np->Next;
} // end of Delete
/******************************************************************/
/* Store a string in Buf, enventually reallocating it. */
/******************************************************************/
char *XMLNODE::BufAlloc(PGLOBAL g, char *p, int n)
{
if (Len < n) {
Len = n;
Buf = (char*)PlugSubAlloc(g, NULL, n + 1);
} // endif Len
*Buf = '\0';
return strncat(Buf, p, n);
} // end of BufAlloc

177
storage/connect/plgxml.h Normal file
View File

@@ -0,0 +1,177 @@
/******************************************************************/
/* Dual XML implementation base classes defines. */
/******************************************************************/
#if !defined(BASE_BUFFER_SIZE)
enum ElementType { // libxml2
XML_ELEMENT_NODE = 1,
XML_ATTRIBUTE_NODE = 2,
XML_TEXT_NODE = 3,
XML_CDATA_SECTION_NODE = 4,
XML_ENTITY_REF_NODE = 5,
XML_ENTITY_NODE = 6,
XML_PI_NODE = 7,
XML_COMMENT_NODE = 8,
XML_DOCUMENT_NODE = 9,
XML_DOCUMENT_TYPE_NODE = 10,
XML_DOCUMENT_FRAG_NODE = 11,
XML_NOTATION_NODE = 12,
XML_HTML_DOCUMENT_NODE = 13,
XML_DTD_NODE = 14,
XML_ELEMENT_DECL = 15,
XML_ATTRIBUTE_DECL = 16,
XML_ENTITY_DECL = 17,
XML_NAMESPACE_DECL = 18,
XML_XINCLUDE_START = 19,
XML_XINCLUDE_END = 20,
XML_DOCB_DOCUMENT_NODE = 21};
#endif // !BASE_BUFFER_SIZE
//#if !defined(NODE_TYPE_LIST)
#ifdef NOT_USED
enum NodeType { // MS DOM
NODE_ELEMENT = 1,
NODE_ATTRIBUTE = 2,
NODE_TEXT = 3,
NODE_CDATA_SECTION = 4,
NODE_ENTITY_REFERENCE = 5,
NODE_ENTITY = 6,
NODE_PROCESSING_INSTRUCTION = 7,
NODE_COMMENT = 8,
NODE_DOCUMENT = 9,
NODE_DOCUMENT_TYPE = 10,
NODE_DOCUMENT_FRAGMENT = 11,
NODE_NOTATION = 12};
#endif // !NODE_TYPE_LIST
typedef class XMLDOCUMENT *PXDOC; // Document
typedef class XMLNODE *PXNODE; // Node (Element)
typedef class XMLNODELIST *PXLIST; // Node list
typedef class XMLATTRIBUTE *PXATTR; // Attribute
typedef struct _ns {
struct _ns *Next;
char *Prefix;
char *Uri;
} NS, *PNS;
PXDOC GetLibxmlDoc(PGLOBAL g, char *nsl, char *nsdf,
char *enc, PFBLOCK fp = NULL);
PXDOC GetDomDoc(PGLOBAL g, char *nsl, char *nsdf,
char *enc, PFBLOCK fp = NULL);
/******************************************************************/
/* Declaration of XML document. */
/******************************************************************/
class XMLDOCUMENT : public BLOCK {
friend class XML2NODE;
friend class DOMNODE;
public:
// Properties
virtual short GetDocType(void) = 0;
virtual void *GetDocPtr(void) = 0;
// Methods
virtual bool Initialize(PGLOBAL) = 0;
virtual bool ParseFile(char *) = 0;
virtual bool NewDoc(PGLOBAL, char *) = 0;
virtual void AddComment(PGLOBAL, char *) = 0;
virtual PXNODE GetRoot(PGLOBAL) = 0;
virtual PXNODE NewRoot(PGLOBAL, char *) = 0;
virtual PXNODE NewPnode(PGLOBAL, char * = NULL) = 0;
virtual PXATTR NewPattr(PGLOBAL) = 0;
virtual PXLIST NewPlist(PGLOBAL) = 0;
virtual int DumpDoc(PGLOBAL, char *) = 0;
virtual void CloseDoc(PGLOBAL, PFBLOCK) = 0;
virtual PFBLOCK LinkXblock(PGLOBAL, MODE, int, char *) = 0;
protected:
// Constructor
XMLDOCUMENT(char *nsl, char *nsdf, char *enc);
// Utility
bool MakeNSlist(PGLOBAL g);
// Members
PNS Namespaces; /* To the namespaces */
char *Encoding; /* The document encoding */
char *Nslist; /* Namespace list */
char *DefNs; /* Default namespace */
}; // end of class XMLDOCUMENT
/******************************************************************/
/* Declaration of XML node. */
/******************************************************************/
class XMLNODE : public BLOCK {
public:
// Properties
virtual char *GetName(PGLOBAL) = 0;
virtual int GetType(void) = 0;
virtual PXNODE GetNext(PGLOBAL) = 0;
virtual PXNODE GetChild(PGLOBAL) = 0;
// Methods
virtual char *GetText(char *, int) = 0;
virtual bool SetContent(PGLOBAL, char *, int) = 0;
virtual PXNODE Clone(PGLOBAL, PXNODE) = 0;
virtual PXLIST GetChildElements(PGLOBAL, char * = NULL, PXLIST = NULL) = 0;
virtual PXLIST SelectNodes(PGLOBAL, char *, PXLIST = NULL) = 0;
virtual PXNODE SelectSingleNode(PGLOBAL, char *, PXNODE = NULL) = 0;
virtual PXATTR GetAttribute(PGLOBAL, char *, PXATTR = NULL) = 0;
virtual PXNODE AddChildNode(PGLOBAL, char *, PXNODE = NULL) = 0;
virtual PXATTR AddProperty(PGLOBAL, char *, PXATTR = NULL) = 0;
virtual void AddText(PGLOBAL, char *) = 0;
virtual void DeleteChild(PGLOBAL, PXNODE) = 0;
protected:
PXNODE NewChild(PXNODE ncp);
void Delete(PXNODE dnp);
char *BufAlloc(PGLOBAL g, char *p, int n);
// Constructor
XMLNODE(PXDOC dp);
// Members
PXDOC Doc;
PXNODE Next;
PXNODE Children;
char *Buf;
int Len;
}; // end of class XMLNODE
/******************************************************************/
/* Declaration of XML node list. */
/******************************************************************/
class XMLNODELIST : public BLOCK {
public:
// Properties
virtual int GetLength(void) = 0;
virtual PXNODE GetItem(PGLOBAL, int, PXNODE = NULL) = 0;
protected:
// Constructor
XMLNODELIST(PXDOC dp) {Doc = dp;}
// Members
PXDOC Doc;
}; // end of class XMLNODELIST
/******************************************************************/
/* Declaration of XML attribute. */
/******************************************************************/
class XMLATTRIBUTE : public BLOCK {
public:
// Properties
//virtual char *GetText(void) = 0;
// Methods
virtual bool SetText(PGLOBAL, char *, int) = 0;
protected:
// Constructor
XMLATTRIBUTE(PXDOC dp) {Doc = dp;}
// Members
PXDOC Doc;
}; // end of class XMLATTRIBUTE

500
storage/connect/plugutil.c Normal file
View File

@@ -0,0 +1,500 @@
/************** PlugUtil C Program Source Code File (.C) ***************/
/* */
/* PROGRAM NAME: PLUGUTIL */
/* ------------- */
/* Version 2.7 */
/* */
/* COPYRIGHT: */
/* ---------- */
/* (C) Copyright to the author Olivier BERTRAND 1993-2012 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
/* This program are initialization and utility Plug routines. */
/* */
/* WHAT YOU NEED TO COMPILE THIS PROGRAM: */
/* -------------------------------------- */
/* */
/* REQUIRED FILES: */
/* --------------- */
/* See Readme.C for a list and description of required SYSTEM files. */
/* */
/* PLUG.C - Source code */
/* GLOBAL.H - Global declaration file */
/* OPTION.H - Option declaration file */
/* */
/* REQUIRED LIBRARIES: */
/* ------------------- */
/* */
/* OS2.LIB - OS2 libray */
/* LLIBCE.LIB - Protect mode/standard combined large model C */
/* library */
/* */
/* REQUIRED PROGRAMS: */
/* ------------------ */
/* */
/* IBM C Compiler */
/* IBM Linker */
/* */
/***********************************************************************/
//efine DEBTRACE 3
//efine DEBTRACE2
/***********************************************************************/
/* */
/* Include relevant MariaDB header file. */
/* */
/***********************************************************************/
#include "my_global.h"
#if defined(WIN32)
//#include <windows.h>
#else
#if defined(UNIX) || defined(UNIV_LINUX)
#include <errno.h>
#include <unistd.h>
//#define __stdcall
#else
#include <dir.h>
#endif
#include <stdarg.h>
#endif
#if defined(WIN)
#include <alloc.h>
#endif
#include <errno.h> /* definitions of ERANGE ENOMEM */
#if !defined(UNIX) && !defined(UNIV_LINUX)
#include <direct.h> /* Directory management library */
#endif
/***********************************************************************/
/* */
/* Include application header files */
/* */
/* global.h is header containing all global declarations. */
/* */
/***********************************************************************/
#define STORAGE /* Initialize global variables */
#include "osutil.h"
#include "global.h"
#if defined(WIN32)
extern HINSTANCE s_hModule; /* Saved module handle */
#endif // WIN32
extern char plgini[];
extern int trace;
#if defined(XMSG)
extern char msglang[];
#endif // XMSG
/***********************************************************************/
/* Local Definitions and static variables */
/***********************************************************************/
typedef struct {
ushort Segsize;
ushort Size;
} AREASIZE;
ACTIVITY defActivity = { /* Describes activity and language */
NULL, /* Points to user work area(s) */
"Unknown"}; /* Application name */
#if defined(XMSG) || defined(NEWMSG)
static char stmsg[200];
#endif // XMSG || NEWMSG
#if defined(UNIX) || defined(UNIV_LINUX)
int GetRcString(int id, char *buf, int bufsize);
#endif // UNIX
/**************************************************************************/
/* Tracing output function. */
/**************************************************************************/
void htrc(char const *fmt, ...)
{
va_list ap;
va_start (ap, fmt);
//if (trace == 0 || (trace == 1 && !debug) || !fmt) {
// printf("In %s wrong trace=%d debug=%p fmt=%p\n",
// __FILE__, trace, debug, fmt);
// trace = 0;
// } // endif trace
//if (trace == 1)
// vfprintf(debug, fmt, ap);
//else
vfprintf(stderr, fmt, ap);
va_end (ap);
} // end of htrc
/***********************************************************************/
/* Plug initialization routine. */
/* Language points on initial language name and eventual path. */
/* Return value is the pointer to the Global structure. */
/***********************************************************************/
PGLOBAL PlugInit(LPCSTR Language, uint worksize)
{
PGLOBAL g;
if (trace > 1)
htrc("PlugInit: Language='%s'\n",
((!Language) ? "Null" : (char*)Language));
if (!(g = malloc(sizeof(GLOBAL)))) {
fprintf(stderr, MSG(GLOBAL_ERROR), (int)sizeof(GLOBAL));
} else {
g->Sarea_Size = worksize;
g->Trace = 0;
g->Activityp = g->ActivityStart = NULL;
strcpy(g->Message, "");
/*******************************************************************/
/* Allocate the main work segment. */
/*******************************************************************/
if (!(g->Sarea = PlugAllocMem(g, worksize))) {
char errmsg[256];
sprintf(errmsg, MSG(WORK_AREA), g->Message);
strcpy(g->Message, errmsg);
} /* endif Sarea */
} /* endif g */
g->jump_level = -1; /* New setting to allow recursive call of Plug */
return(g);
} /* end of PlugInit */
/***********************************************************************/
/* PlugExit: Terminate Plug operations. */
/***********************************************************************/
int PlugExit(PGLOBAL g)
{
int rc = 0;
PACTIVITY ap;
if (!g)
return rc;
else
ap = g->ActivityStart;
free(g->Sarea);
free(g);
return rc;
} /* end of PlugExit */
/***********************************************************************/
/* Remove the file type from a file name. */
/* Note: this routine is not really implemented for Unix. */
/***********************************************************************/
LPSTR PlugRemoveType(LPSTR pBuff, LPCSTR FileName)
{
#if !defined(UNIX) && !defined(UNIV_LINUX)
char drive[_MAX_DRIVE];
#else
char *drive = NULL;
#endif
char direc[_MAX_DIR];
char fname[_MAX_FNAME];
char ftype[_MAX_EXT];
_splitpath(FileName, drive, direc, fname, ftype);
if (trace > 1) {
htrc("after _splitpath: FileName=%s\n", FileName);
htrc("drive=%s dir=%s fname=%s ext=%s\n",
SVP(drive), direc, fname, ftype);
} // endif trace
_makepath(pBuff, drive, direc, fname, "");
if (trace > 1)
htrc("buff='%s'\n", pBuff);
return pBuff;
} // end of PlugRemoveType
/***********************************************************************/
/* Set the full path of a file relatively to a given path. */
/* Note: this routine is not really implemented for Unix. */
/***********************************************************************/
LPCSTR PlugSetPath(LPSTR pBuff, LPCSTR FileName, LPCSTR defpath)
{
char newname[_MAX_PATH];
char direc[_MAX_DIR], defdir[_MAX_DIR];
char fname[_MAX_FNAME];
char ftype[_MAX_EXT];
#if !defined(UNIX) && !defined(UNIV_LINUX)
char drive[_MAX_DRIVE], defdrv[_MAX_DRIVE];
#else
char *drive = NULL, *defdrv = NULL;
#endif
if (!strncmp(FileName, "//", 2) || !strncmp(FileName, "\\\\", 2)) {
strcpy(pBuff, FileName); // Remote file
return pBuff;
} // endif
_splitpath(FileName, drive, direc, fname, ftype);
_splitpath(defpath, defdrv, defdir, NULL, NULL);
if (trace > 1) {
htrc("after _splitpath: FileName=%s\n", FileName);
#if defined(UNIX) || defined(UNIV_LINUX)
htrc("dir=%s fname=%s ext=%s\n", direc, fname, ftype);
#else
htrc("drive=%s dir=%s fname=%s ext=%s\n", drive, direc, fname, ftype);
htrc("defdrv=%s defdir=%s\n", defdrv, defdir);
#endif
} // endif trace
if (drive && !*drive)
strcpy(drive, defdrv);
switch (*direc) {
case '\0':
strcpy(direc, defdir);
break;
case '\\':
case '/':
break;
default:
// This supposes that defdir ends with a SLASH
strcpy(direc, strcat(defdir, direc));
} // endswitch
_makepath(newname, drive, direc, fname, ftype);
if (trace > 1)
htrc("newname='%s'\n", newname);
if (_fullpath(pBuff, newname, _MAX_PATH)) {
if (trace > 1)
htrc("pbuff='%s'\n", pBuff);
return pBuff;
} else
return FileName; // Error, return unchanged name
} // end of PlugSetPath
#if defined(XMSG)
/***********************************************************************/
/* PlugGetMessage: get a message from the message file. */
/***********************************************************************/
char *PlugReadMessage(PGLOBAL g, int mid, char *m)
{
char msgfile[_MAX_PATH], msgid[32], buff[256];
char *msg;
FILE *mfile = NULL;
GetPrivateProfileString("Message", msglang, "Message\\english.msg",
msgfile, _MAX_PATH, plgini);
if (!(mfile = fopen(msgfile, "rt"))) {
sprintf(stmsg, "Fail to open message file %s for %s", msgfile, msglang);
goto err;
} // endif mfile
for (;;)
if (!fgets(buff, 256, mfile)) {
sprintf(stmsg, "Cannot get message %d %s", mid, SVP(m));
goto fin;
} else
if (atoi(buff) == mid)
break;
if (sscanf(buff, " %*d %s \"%[^\"]", msgid, stmsg) < 2) {
// Old message file
if (!sscanf(buff, " %*d \"%[^\"]", stmsg)) {
sprintf(stmsg, "Bad message file for %d %s", mid, SVP(m));
goto fin;
} else
m = NULL;
} // endif sscanf
if (m && strcmp(m, msgid)) {
// Message file is out of date
strcpy(stmsg, m);
goto fin;
} // endif m
fin:
fclose(mfile);
err:
if (g) {
// Called by STEP
msg = (char *)PlugSubAlloc(g, NULL, strlen(stmsg) + 1);
strcpy(msg, stmsg);
} else // Called by MSG or PlgGetErrorMsg
msg = stmsg;
return msg;
} // end of PlugReadMessage
#elif defined(NEWMSG)
/***********************************************************************/
/* PlugGetMessage: get a message from the resource string table. */
/***********************************************************************/
char *PlugGetMessage(PGLOBAL g, int mid)
{
char *msg;
#if !defined(UNIX) && !defined(UNIV_LINUX)
int n = LoadString(s_hModule, (uint)mid, (LPTSTR)stmsg, 200);
if (n == 0) {
DWORD rc = GetLastError();
msg = (char*)PlugSubAlloc(g, NULL, 512); // Extend buf allocation
n = sprintf(msg, "Message %d, rc=%d: ", mid, rc);
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS, NULL, rc, 0,
(LPTSTR)(msg + n), 512 - n, NULL);
return msg;
} // endif n
#else // UNIX
if (!GetRcString(mid, stmsg, 200))
sprintf(stmsg, "Message %d not found", mid);
#endif // UNIX
if (g) {
// Called by STEP
msg = (char *)PlugSubAlloc(g, NULL, strlen(stmsg) + 1);
strcpy(msg, stmsg);
} else // Called by MSG or PlgGetErrorMsg
msg = stmsg;
return msg;
} // end of PlugGetMessage
#endif // NEWMSG
#if defined(WIN32)
/***********************************************************************/
/* Return the line length of the console screen buffer. */
/***********************************************************************/
short GetLineLength(PGLOBAL g)
{
CONSOLE_SCREEN_BUFFER_INFO coninfo;
HANDLE hcons = GetStdHandle(STD_OUTPUT_HANDLE);
BOOL b = GetConsoleScreenBufferInfo(hcons, &coninfo);
return (b) ? coninfo.dwSize.X : 0;
} // end of GetLineLength
#endif // WIN32
/***********************************************************************/
/* Program for memory allocation of work and language areas. */
/***********************************************************************/
void *PlugAllocMem(PGLOBAL g, uint size)
{
void *areap; /* Pointer to allocated area */
/*********************************************************************/
/* This is the allocation routine for the WIN32/UNIX/AIX version. */
/*********************************************************************/
if (!(areap = malloc(size)))
sprintf(g->Message, MSG(MALLOC_ERROR), "malloc");
if (trace > 1) {
if (areap)
htrc("Memory of %u allocated at %p\n", size, areap);
else
htrc("PlugAllocMem: %s\n", g->Message);
} // endif trace
return (areap);
} /* end of PlugAllocMem */
/***********************************************************************/
/* Program for SubSet initialization of memory pools. */
/* Here there should be some verification done such as validity of */
/* the address and size not larger than memory size. */
/***********************************************************************/
BOOL PlugSubSet(PGLOBAL g, void *memp, uint size)
{
PPOOLHEADER pph = memp;
pph->To_Free = (OFFSET)sizeof(POOLHEADER);
pph->FreeBlk = size - pph->To_Free;
return FALSE;
} /* end of PlugSubSet */
/***********************************************************************/
/* Program for sub-allocating one item in a storage area. */
/* Note: SubAlloc routines of OS/2 are no more used to increase the */
/* code portability and avoid problems when a grammar compiled under */
/* one version of OS/2 is used under another version. */
/* The simple way things are done here is also based on the fact */
/* that no freeing of suballocated blocks is permitted in Plug. */
/***********************************************************************/
void *PlugSubAlloc(PGLOBAL g, void *memp, size_t size)
{
PPOOLHEADER pph; /* Points on area header. */
if (!memp)
/*******************************************************************/
/* Allocation is to be done in the Sarea. */
/*******************************************************************/
memp = g->Sarea;
//size = ((size + 3) / 4) * 4; /* Round up size to multiple of 4 */
size = ((size + 7) / 8) * 8; /* Round up size to multiple of 8 */
pph = (PPOOLHEADER)memp;
#if defined(DEBUG2) || defined(DEBUG3)
htrc("SubAlloc in %p size=%d used=%d free=%d\n",
memp, size, pph->To_Free, pph->FreeBlk);
#endif
if ((uint)size > pph->FreeBlk) { /* Not enough memory left in pool */
char *pname = "Work";
sprintf(g->Message,
"Not enough memory in %s area for request of %u (used=%d free=%d)",
pname, size, pph->To_Free, pph->FreeBlk);
#if defined(DEBUG2) || defined(DEBUG3)
htrc("%s\n", g->Message);
#endif
longjmp(g->jumper[g->jump_level], 1);
} /* endif size OS32 code */
/*********************************************************************/
/* Do the suballocation the simplest way. */
/*********************************************************************/
memp = MakePtr(memp, pph->To_Free); /* Points to suballocated block */
pph->To_Free += size; /* New offset of pool free block */
pph->FreeBlk -= size; /* New size of pool free block */
#if defined(DEBUG2) || defined(DEBUG3)
htrc("Done memp=%p used=%d free=%d\n",
memp, pph->To_Free, pph->FreeBlk);
#endif
return (memp);
} /* end of PlugSubAlloc */
/***********************************************************************/
/* This routine makes a pointer from an offset to a memory pointer. */
/***********************************************************************/
void *MakePtr(void *memp, OFFSET offset)
{
return ((offset == 0) ? NULL : &((char *)memp)[offset]);
} /* end of MakePtr */
/***********************************************************************/
/* This routine makes an offset from a pointer new format. */
/***********************************************************************/
OFFSET MakeOff(void *memp, void *ptr)
{
return ((!ptr) ? 0 : (OFFSET)((char *)ptr - (char *)memp));
} /* end of MakeOff */
/*--------------------- End of PLUGUTIL program -----------------------*/

View File

@@ -0,0 +1,61 @@
#if !defined(PREPARSE_DEFINED)
#define PREPARSE_DEFINED
#include "checklvl.h"
/***********************************************************************/
/* Struct of variables used by the SQL pre-parsers. */
/***********************************************************************/
typedef struct _prepar {
struct _prepar *Next;
char *Debinp; // Start of input buffer
char *Endinp; // End of input buffer
char *Pluginp; // Points on current parsing position
char *Plugbuf; // Start of output buffer
char *Plugptr; // Current output position
char *Debchar; // Next/current start of command
char *Debselp; // Beginning of selection
char *Debline; // Start of current line
char *Plugpar[32]; // Parameters
int Numparms; // Number of defined parameters
int Nprms; // Number of ODBC parameters
int Lines; // Line number
int Chars; // Index of selection start in line
int Endchars; // Index of selection end in line
int Frinp, Frbuf; // 0: no, 1: free, 2: delete Debinp/Plugbuf
int Outsize; // Size of output buffer
FILE *Argfile; // File containing arguments
int Addargs; // 1 if arguments are added to the list
} PREPAR, *PPREP;
/***********************************************************************/
/* Struct of variables used by the date format pre-parser. */
/***********************************************************************/
typedef struct _datpar {
char *Format; // Points to format to decode
char *Curp; // Points to current parsing position
char *InFmt; // Start of input format
char *OutFmt; // Start of output format
int Index[8]; // Indexes of date values
int Num; // Number of values to retrieve
int Flag; // 1: Input, 2: Output, 4: no output blank
int Outsize; // Size of output buffers
} DATPAR, *PDTP;
/***********************************************************************/
/* Preparsers used by SQL language. */
/***********************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
int sqlflex(PPREP pp);
int sqpflex(PPREP pp);
int fmdflex(PDTP pp);
#ifdef __cplusplus
}
#endif
#endif // PREPARSE_DEFINED

209
storage/connect/rcmsg.c Normal file
View File

@@ -0,0 +1,209 @@
/**************** RCMsg C Program Source Code File (.C) ****************/
/* PROGRAM NAME: RCMSG */
/* ------------- */
/* Version 1.0 */
/* */
/* COPYRIGHT */
/* ---------- */
/* (C) Copyright to the author Olivier BERTRAND: 2005 */
/* */
/* WHAT THIS PROGRAM DOES */
/* ----------------------- */
/* This program simulates LoadString for Unix and Linux. */
/* */
/***********************************************************************/
#include <stdio.h>
#include "resource.h"
int GetRcString(int id, char *buf, int bufsize)
{
char *p = NULL, msg[32];
//printf("In GetRcString id=%d\n", id);
switch (id) {
case IDS_00: p = "%s"; break;
#if defined(FRENCH)
case IDS_01: p = "%s: erreur d'allocation du buffer de communication de %d octets"; break;
case IDS_02: p = "%s: erreur d'allocation m<>moire tampon pour %d colonnes"; break;
case IDS_03: p = "%s: Commande sp<73>ciale invalide"; break;
case IDS_04: p = "%s: Wrong number of arguments %d"; break;
case IDS_05: p = "%s"; break;
case IDS_06: p = "%s: Commande d<>passant la taille du buffer interne (%d octets)"; break;
case IDS_07: p = "%s: Donn<6E>es (%d octets) tronqu<71>es <20> la taille du buffer"; break;
case IDS_08: p = "%s: R<>sultat d<>passant la taille du buffer interne (%d octets)"; break;
case IDS_09: p = "Erreur dans %s: %s"; break;
case IDS_10: p = "%s: erreur d'allocating m<>moire de %d octets"; break;
case IDS_11: p = "%s: mauvaise cl<63> de connexion %d"; break;
case IDS_12: p = "%s: Pas plus de %d connexions autoris<69>es pour un programme"; break;
case IDS_13: p = "%s: cl<63> de connexion invalide %d"; break;
case IDS_14: p = "SafeDB: %s rc=%d"; break;
case IDS_15: p = "Mauvaise Dll de communication appel<65>e par le moteur %s"; break;
case IDS_TAB_01: p = "Qualificateur"; break;
case IDS_TAB_02: p = "Propri<EFBFBD>taire"; break;
case IDS_TAB_03: p = "Nom"; break;
case IDS_TAB_04: p = "Type"; break;
case IDS_TAB_05: p = "Remarque"; break;
case IDS_COL_01: p = "Qualif_Table"; break;
case IDS_COL_02: p = "Prop_Tabl"; break;
case IDS_COL_03: p = "Nom_Table"; break;
case IDS_COL_04: p = "Nom_Colonne"; break;
case IDS_COL_05: p = "Type_Donn<EFBFBD>es"; break;
case IDS_COL_06: p = "Nom_Type"; break;
case IDS_COL_07: p = "Pr<EFBFBD>cision"; break;
case IDS_COL_08: p = "Longueur"; break;
case IDS_COL_09: p = "Echelle"; break;
case IDS_COL_10: p = "Base"; break;
case IDS_COL_11: p = "Nullifiable"; break;
case IDS_COL_12: p = "Remarques"; break;
case IDS_INF_01: p = "Nom_Type"; break;
case IDS_INF_02: p = "Type_Donn<EFBFBD>es"; break;
case IDS_INF_03: p = "Pr<EFBFBD>cision"; break;
case IDS_INF_04: p = "Pr<EFBFBD>fixe_Lit<EFBFBD>ral"; break;
case IDS_INF_05: p = "Suffixe_Lit<EFBFBD>ral"; break;
case IDS_INF_06: p = "Cr<EFBFBD>ation_Params"; break;
case IDS_INF_07: p = "Nullifiable"; break;
case IDS_INF_08: p = "Maj_Minuscule"; break;
case IDS_INF_09: p = "Localisable"; break;
case IDS_INF_10: p = "Valeur_Absolue"; break;
case IDS_INF_11: p = "Monnaie"; break;
case IDS_INF_12: p = "Auto_Incr<EFBFBD>ment"; break;
case IDS_INF_13: p = "Nom_Type_Local"; break;
case IDS_INF_14: p = "Echelle_Minimum"; break;
case IDS_INF_15: p = "Echelle_Maximum"; break;
case IDS_PKY_01: p = "Qualif_Table"; break;
case IDS_PKY_02: p = "Prop_Table"; break;
case IDS_PKY_03: p = "Nom_Table"; break;
case IDS_PKY_04: p = "Nom_Colonne"; break;
case IDS_PKY_05: p = "Num<EFBFBD>ro_Cl<EFBFBD>"; break;
case IDS_PKY_06: p = "Nom_Cl<EFBFBD>"; break;
case IDS_FKY_01: p = "PKTable_Qualifier"; break;
case IDS_FKY_02: p = "PKTable_Owner"; break;
case IDS_FKY_03: p = "PKTable_Name"; break;
case IDS_FKY_04: p = "PKColumn_Name"; break;
case IDS_FKY_05: p = "FKTable_Qualifier"; break;
case IDS_FKY_06: p = "FKTable_Owner"; break;
case IDS_FKY_07: p = "FKTable_Name"; break;
case IDS_FKY_08: p = "FKColumn_Name"; break;
case IDS_FKY_09: p = "Key_Seq"; break;
case IDS_FKY_10: p = "Update_Rule"; break;
case IDS_FKY_11: p = "Delete_Rule"; break;
case IDS_FKY_12: p = "FK_Name"; break;
case IDS_FKY_13: p = "PK_Name"; break;
case IDS_STA_01: p = "Table_Qualifier"; break;
case IDS_STA_02: p = "Table_Owner"; break;
case IDS_STA_03: p = "Table_Name"; break;
case IDS_STA_04: p = "Non_Unique"; break;
case IDS_STA_05: p = "Index_Qualifier"; break;
case IDS_STA_06: p = "Index_Name"; break;
case IDS_STA_07: p = "Type"; break;
case IDS_STA_08: p = "Seq_in_Index"; break;
case IDS_STA_09: p = "Column_Name"; break;
case IDS_STA_10: p = "Collation"; break;
case IDS_STA_11: p = "Cardinality"; break;
case IDS_STA_12: p = "Pages"; break;
case IDS_STA_13: p = "Filter_Condition"; break;
case IDS_SPC_01: p = "Champ"; break;
case IDS_SPC_02: p = "Nom_Colonne"; break;
case IDS_SPC_03: p = "Type_Donn<EFBFBD>es"; break;
case IDS_SPC_04: p = "Nom_Type"; break;
case IDS_SPC_05: p = "Pr<EFBFBD>cision"; break;
case IDS_SPC_06: p = "Longueur"; break;
case IDS_SPC_07: p = "Echelle"; break;
case IDS_SPC_08: p = "Pseudo_Colonne"; break;
#else // English
case IDS_01: p = "%s: error allocating communication buffer of %d bytes"; break;
case IDS_02: p = "%s: error allocating parser memory for %d columns"; break;
case IDS_03: p = "%s: Invalid special command"; break;
case IDS_04: p = "%s: Wrong number of arguments %d"; break;
case IDS_05: p = "%s"; break;
case IDS_06: p = "%s: Command bigger than internal buffer of size = %d"; break;
case IDS_07: p = "%s: Data truncated to buffer size, actual length is %d bytes"; break;
case IDS_08: p = "%s: Result bigger than internal buffer of size = %d"; break;
case IDS_09: p = "Error in %s: %s"; break;
case IDS_10: p = "%s: error allocating instance memory of %d bytes"; break;
case IDS_11: p = "%s: wrong connection key value %d"; break;
case IDS_12: p = "%s: No more than %d connections allowed from one process"; break;
case IDS_13: p = "%s: invalid connection key value %d"; break;
case IDS_14: p = "SafeDB: %s rc=%d"; break;
case IDS_15: p = "Wrong communication Dll called for engine %s"; break;
case IDS_TAB_01: p = "Qualifier"; break;
case IDS_TAB_02: p = "Owner"; break;
case IDS_TAB_03: p = "Name"; break;
case IDS_TAB_04: p = "Type"; break;
case IDS_TAB_05: p = "Remark"; break;
case IDS_COL_01: p = "Table_Qualif"; break;
case IDS_COL_02: p = "Table_Owner"; break;
case IDS_COL_03: p = "Table_Name"; break;
case IDS_COL_04: p = "Column_Name"; break;
case IDS_COL_05: p = "Data_Type"; break;
case IDS_COL_06: p = "Type_Name"; break;
case IDS_COL_07: p = "Precision"; break;
case IDS_COL_08: p = "Length"; break;
case IDS_COL_09: p = "Scale"; break;
case IDS_COL_10: p = "Radix"; break;
case IDS_COL_11: p = "Nullable"; break;
case IDS_COL_12: p = "Remarks"; break;
case IDS_INF_01: p = "Type_Name"; break;
case IDS_INF_02: p = "Data_Type"; break;
case IDS_INF_03: p = "Precision"; break;
case IDS_INF_04: p = "Literal_Prefix"; break;
case IDS_INF_05: p = "Literal_Suffix"; break;
case IDS_INF_06: p = "Create_Params"; break;
case IDS_INF_07: p = "Nullable"; break;
case IDS_INF_08: p = "Case_Sensitive"; break;
case IDS_INF_09: p = "Searchable"; break;
case IDS_INF_10: p = "Unsigned_Attribute"; break;
case IDS_INF_11: p = "Money"; break;
case IDS_INF_12: p = "Auto_Increment"; break;
case IDS_INF_13: p = "Local_Type_Name"; break;
case IDS_INF_14: p = "Minimum_Scale"; break;
case IDS_INF_15: p = "Maximum_Scale"; break;
case IDS_PKY_01: p = "Table_Qualifier"; break;
case IDS_PKY_02: p = "Table_Owner"; break;
case IDS_PKY_03: p = "Table_Name"; break;
case IDS_PKY_04: p = "Column_Name"; break;
case IDS_PKY_05: p = "Key_Seq"; break;
case IDS_PKY_06: p = "Pk_Name"; break;
case IDS_FKY_01: p = "PKTable_Qualifier"; break;
case IDS_FKY_02: p = "PKTable_Owner"; break;
case IDS_FKY_03: p = "PKTable_Name"; break;
case IDS_FKY_04: p = "PKColumn_Name"; break;
case IDS_FKY_05: p = "FKTable_Qualifier"; break;
case IDS_FKY_06: p = "FKTable_Owner"; break;
case IDS_FKY_07: p = "FKTable_Name"; break;
case IDS_FKY_08: p = "FKColumn_Name"; break;
case IDS_FKY_09: p = "Key_Seq"; break;
case IDS_FKY_10: p = "Update_Rule"; break;
case IDS_FKY_11: p = "Delete_Rule"; break;
case IDS_FKY_12: p = "FK_Name"; break;
case IDS_FKY_13: p = "PK_Name"; break;
case IDS_STA_01: p = "Table_Qualifier"; break;
case IDS_STA_02: p = "Table_Owner"; break;
case IDS_STA_03: p = "Table_Name"; break;
case IDS_STA_04: p = "Non_Unique"; break;
case IDS_STA_05: p = "Index_Qualifier"; break;
case IDS_STA_06: p = "Index_Name"; break;
case IDS_STA_07: p = "Type"; break;
case IDS_STA_08: p = "Seq_in_Index"; break;
case IDS_STA_09: p = "Column_Name"; break;
case IDS_STA_10: p = "Collation"; break;
case IDS_STA_11: p = "Cardinality"; break;
case IDS_STA_12: p = "Pages"; break;
case IDS_STA_13: p = "Filter_Condition"; break;
case IDS_SPC_01: p = "Scope"; break;
case IDS_SPC_02: p = "Column_Name"; break;
case IDS_SPC_03: p = "Data_Type"; break;
case IDS_SPC_04: p = "Type_Name"; break;
case IDS_SPC_05: p = "Precision"; break;
case IDS_SPC_06: p = "Length"; break;
case IDS_SPC_07: p = "Scale"; break;
case IDS_SPC_08: p = "Pseudo_Column"; break;
#endif // English
default:
sprintf(msg, "ID=%d unknown", id);
p = msg;
} // endswitch(id)
return sprintf(buf, "%.*s", bufsize-1, p);
} // end of GetRcString

421
storage/connect/reldef.cpp Normal file
View File

@@ -0,0 +1,421 @@
/************* RelDef CPP Program Source Code File (.CPP) **************/
/* PROGRAM NAME: REFDEF */
/* ------------- */
/* Version 1.3 */
/* */
/* COPYRIGHT: */
/* ---------- */
/* (C) Copyright to the author Olivier BERTRAND 2004-2012 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
/* This program are the DB definition related routines. */
/* */
/***********************************************************************/
/***********************************************************************/
/* Include relevant MariaDB header file. */
/***********************************************************************/
#include "my_global.h"
#if defined(WIN32)
#include <sqlext.h>
#else
#include <dlfcn.h> // dlopen(), dlclose(), dlsym() ...
#include "osutil.h"
//#include "sqlext.h"
#endif
/***********************************************************************/
/* Include application header files */
/* */
/* global.h is header containing all global declarations. */
/* plgdbsem.h is header containing DB application declarations. */
/* catalog.h is header containing DB description declarations. */
/***********************************************************************/
#include "global.h"
#include "plgdbsem.h"
#include "reldef.h"
#include "colblk.h"
#include "filamap.h"
#include "filamfix.h"
#include "filamvct.h"
#if defined(ZIP_SUPPORT)
#include "filamzip.h"
#endif // ZIP_SUPPORT
#include "tabdos.h"
#include "valblk.h"
#include "tabmul.h"
/***********************************************************************/
/* External static variables. */
/***********************************************************************/
//extern "C" char plgini[];
/* --------------------------- Class RELDEF -------------------------- */
/***********************************************************************/
/* RELDEF Constructor. */
/***********************************************************************/
RELDEF::RELDEF(void)
{
Next = NULL;
To_Cols = NULL;
Name = NULL;
Database = NULL;
Cat = NULL;
} // end of RELDEF constructor
/* --------------------------- Class TABDEF -------------------------- */
/***********************************************************************/
/* TABDEF Constructor. */
/***********************************************************************/
TABDEF::TABDEF(void)
{
Owner = NULL;
Desc = NULL;
Card = 0;
Elemt = 0;
Sort = 0;
Multiple = 0;
Degree = 0;
Pseudo = 0;
Read_Only = false;
} // end of TABDEF constructor
/***********************************************************************/
/* Define: initialize the table definition block from XDB file. */
/***********************************************************************/
bool TABDEF::Define(PGLOBAL g, PCATLG cat, LPCSTR name, LPCSTR am)
{
char buf[8];
int poff = 0;
void *memp = cat->Descp;
Name = (PSZ)PlugSubAlloc(g, memp, strlen(name) + 1);
strcpy(Name, name);
Cat = cat;
Elemt = cat->GetIntCatInfo(name, "Elements", 0);
Multiple = cat->GetIntCatInfo(name, "Multiple", 0);
Degree = cat->GetIntCatInfo(name, "Degree", 0);
cat->GetCharCatInfo(name, "ReadOnly", "No", buf, sizeof(buf));
Read_Only = (toupper(*buf) == 'Y');
// Get The column definitions
if ((poff = cat->GetColCatInfo(g, this)) < 0)
return true;
// Do the definition of AM specific fields
return DefineAM(g, am, poff);
} // end of Define
/* --------------------------- Class OEMDEF -------------------------- */
/***********************************************************************/
/* GetXdef: get the external TABDEF from OEM module. */
/***********************************************************************/
PTABDEF OEMDEF::GetXdef(PGLOBAL g)
{
typedef PTABDEF (__stdcall *XGETDEF) (PGLOBAL, void *);
char c, getname[40] = "Get";
PTABDEF xdefp;
XGETDEF getdef = NULL;
PCATLG cat = Cat;
void *memp = cat->Descp;
#if defined(WIN32)
// Is the DLL already loaded?
if (!Hdll && !(Hdll = GetModuleHandle(Module)))
// No, load the Dll implementing the function
if (!(Hdll = LoadLibrary(Module))) {
char buf[256];
DWORD rc = GetLastError();
sprintf(g->Message, MSG(DLL_LOAD_ERROR), rc, Module);
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS, NULL, rc, 0,
(LPTSTR)buf, sizeof(buf), NULL);
strcat(strcat(g->Message, ": "), buf);
return NULL;
} // endif hDll
// The exported name is always in uppercase
for (int i = 0; ; i++) {
c = Subtype[i];
getname[i + 3] = toupper(c);
if (!c) break;
} // endfor i
// Get the function returning an instance of the external DEF class
if (!(getdef = (XGETDEF)GetProcAddress((HINSTANCE)Hdll, getname))) {
sprintf(g->Message, MSG(PROCADD_ERROR), GetLastError(), getname);
FreeLibrary((HMODULE)Hdll);
return NULL;
} // endif getdef
#else // !WIN32
const char *error = NULL;
// Is the library already loaded?
// if (!Hdll && !(Hdll = ???))
// Load the desired shared library
if (!(Hdll = dlopen(Module, RTLD_LAZY))) {
error = dlerror();
sprintf(g->Message, MSG(SHARED_LIB_ERR), Module, SVP(error));
return NULL;
} // endif Hdll
// The exported name is always in uppercase
for (int i = 0; ; i++) {
c = Subtype[i];
getname[i + 3] = toupper(c);
if (!c) break;
} // endfor i
// Get the function returning an instance of the external DEF class
if (!(getdef = (XGETDEF)dlsym(Hdll, getname))) {
error = dlerror();
sprintf(g->Message, MSG(GET_FUNC_ERR), getname, SVP(error));
dlclose(Hdll);
return NULL;
} // endif getdef
#endif // !WIN32
// Just in case the external Get function does not set error messages
sprintf(g->Message, MSG(DEF_ALLOC_ERROR), Subtype);
// Get the table definition block
if (!(xdefp = getdef(g, memp)))
return NULL;
// Have the external class do its complete definition
if (!cat->Cbuf) {
// Suballocate a temporary buffer for the entire column section
cat->Cblen = cat->GetSizeCatInfo("Database", "Colsize", "8K");
cat->Cbuf = (char*)PlugSubAlloc(g, NULL, cat->Cblen);
} // endif Cbuf
// Here "OEM" should be replace by a more useful value
if (xdefp->Define(g, cat, Name, "OEM"))
return NULL;
// Ok, return external block
return xdefp;
} // end of GetXdef
/***********************************************************************/
/* DeleteTableFile: Delete an OEM table file if applicable. */
/***********************************************************************/
bool OEMDEF::DeleteTableFile(PGLOBAL g)
{
if (!Pxdef)
Pxdef = GetXdef(g);
return (Pxdef) ? Pxdef->DeleteTableFile(g) : true;
} // end of DeleteTableFile
/***********************************************************************/
/* Define: initialize the table definition block from XDB file. */
/***********************************************************************/
bool OEMDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
{
void *memp = Cat->Descp;
Module = Cat->GetStringCatInfo(g, Name, "Module", "");
Subtype = Cat->GetStringCatInfo(g, Name, "Subtype", Module);
if (!*Module)
Module = Subtype;
Desc = (char*)PlugSubAlloc(g, memp, strlen(Module)
+ strlen(Subtype) + 3);
sprintf(Desc, "%s(%s)", Module, Subtype);
return false;
} // end of DefineAM
/***********************************************************************/
/* GetTable: makes a new Table Description Block. */
/***********************************************************************/
PTDB OEMDEF::GetTable(PGLOBAL g, MODE mode)
{
RECFM rfm;
PTDBASE tdbp = NULL;
// If define block not here yet, get it now
if (!Pxdef && !(Pxdef = GetXdef(g)))
return NULL; // Error
/*********************************************************************/
/* Allocate a TDB of the proper type. */
/* Column blocks will be allocated only when needed. */
/*********************************************************************/
if (!(tdbp = (PTDBASE)Pxdef->GetTable(g, mode)))
return NULL;
else
rfm = tdbp->GetFtype();
if (rfm == RECFM_NAF)
return tdbp;
else if (rfm == RECFM_OEM) {
if (Multiple)
tdbp = new(g) TDBMUL(tdbp); // No block optimization yet
return tdbp;
} // endif OEM
/*********************************************************************/
/* The OEM table is based on a file type (currently DOS+ only) */
/*********************************************************************/
assert (rfm == RECFM_VAR || rfm == RECFM_FIX ||
rfm == RECFM_BIN || rfm == RECFM_VCT);
PTXF txfp = NULL;
PDOSDEF defp = (PDOSDEF)Pxdef;
bool map = defp->Mapped && mode != MODE_INSERT &&
!(PlgGetUser(g)->UseTemp == TMP_FORCE &&
(mode == MODE_UPDATE || mode == MODE_DELETE));
int cmpr = defp->Compressed;
/*********************************************************************/
/* Allocate table and file processing class of the proper type. */
/* Column blocks will be allocated only when needed. */
/*********************************************************************/
if (!((PTDBDOS)tdbp)->GetTxfp()) {
if (cmpr) {
#if defined(ZIP_SUPPORT)
if (cmpr == 1)
txfp = new(g) ZIPFAM(defp);
else {
strcpy(g->Message, "Compress 2 not supported yet");
// txfp = new(g) ZLBFAM(defp);
return NULL;
} // endelse
#else // !ZIP_SUPPORT
strcpy(g->Message, "Compress not supported");
return NULL;
#endif // !ZIP_SUPPORT
} else if (rfm == RECFM_VAR) {
if (map)
txfp = new(g) MAPFAM(defp);
else
txfp = new(g) DOSFAM(defp);
} else if (rfm == RECFM_FIX || rfm == RECFM_FIX) {
if (map)
txfp = new(g) MPXFAM(defp);
else
txfp = new(g) FIXFAM(defp);
} else if (rfm == RECFM_VCT) {
assert (Pxdef->GetDefType() == TYPE_AM_VCT);
if (map)
txfp = new(g) VCMFAM((PVCTDEF)defp);
else
txfp = new(g) VCTFAM((PVCTDEF)defp);
} // endif's
((PTDBDOS)tdbp)->SetTxfp(txfp);
} // endif Txfp
if (Multiple)
tdbp = new(g) TDBMUL(tdbp);
return tdbp;
} // end of GetTable
/* --------------------------- Class COLCRT -------------------------- */
/***********************************************************************/
/* COLCRT Constructors. */
/***********************************************************************/
COLCRT::COLCRT(PSZ name)
{
Next = NULL;
Name = name;
Desc = NULL;
Decode = NULL;
Fmt = NULL;
Offset = -1;
Long = -1;
//Freq = -1;
Key = -1;
Prec = -1;
Opt = -1;
DataType = '*';
} // end of COLCRT constructor for table creation
COLCRT::COLCRT(void)
{
Next = NULL;
Name = NULL;
Desc = NULL;
Decode = NULL;
Fmt = NULL;
Offset = 0;
Long = 0;
//Freq = 0;
Key = 0;
Prec = 0;
Opt = 0;
DataType = '*';
} // end of COLCRT constructor for table & view definition
/* --------------------------- Class COLDEF -------------------------- */
/***********************************************************************/
/* COLDEF Constructor. */
/***********************************************************************/
COLDEF::COLDEF(void) : COLCRT()
{
Buf_Type = TYPE_ERROR;
Clen = 0;
Poff = 0;
memset(&F, 0, sizeof(FORMAT));
Flags = 0;
} // end of COLDEF constructor
/***********************************************************************/
/* Define: initialize a column definition from a COLINFO structure. */
/***********************************************************************/
int COLDEF::Define(PGLOBAL g, void *memp, PCOLINFO cfp, int poff)
{
Name = (PSZ)PlugSubAlloc(g, memp, strlen(cfp->Name) + 1);
strcpy(Name, cfp->Name);
Poff = poff;
Buf_Type = cfp->Type;
if ((Clen = GetTypeSize(Buf_Type, cfp->Length)) <= 0) {
sprintf(g->Message, MSG(BAD_COL_TYPE), GetTypeName(Buf_Type), Name);
return -1;
} // endswitch
strcpy(F.Type, GetFormatType(Buf_Type));
F.Length = cfp->Length;
F.Prec = cfp->Prec;
Offset = (cfp->Offset < 0) ? poff : cfp->Offset;
Long = cfp->Length;
Opt = cfp->Opt;
Key = cfp->Key;
//Freq = cfp->Freq;
if (cfp->Remark && *cfp->Remark) {
Desc = (PSZ)PlugSubAlloc(g, memp, strlen(cfp->Remark) + 1);
strcpy(Desc, cfp->Remark);
} // endif Remark
if (cfp->Datefmt) {
Decode = (PSZ)PlugSubAlloc(g, memp, strlen(cfp->Datefmt) + 1);
strcpy(Decode, cfp->Datefmt);
} // endif Datefmt
if (cfp->Fieldfmt) {
Fmt = (PSZ)PlugSubAlloc(g, memp, strlen(cfp->Fieldfmt) + 1);
strcpy(Fmt, cfp->Fieldfmt);
} // endif Fieldfmt
Flags = cfp->Flags;
return (Flags & U_VIRTUAL) ? 0 : Long;
} // end of Define
/* ------------------------- End of RelDef --------------------------- */

194
storage/connect/reldef.h Normal file
View File

@@ -0,0 +1,194 @@
/*************** RelDef H Declares Source Code File (.H) ***************/
/* Name: RELDEF.H Version 1.3 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 2004-2012 */
/* */
/* This file contains the DEF classes definitions. */
/***********************************************************************/
#ifndef __RELDEF_H
#define __RELDEF_H
#include "block.h"
#include "catalog.h"
typedef class INDEXDEF *PIXDEF;
/***********************************************************************/
/* Table or View (relation) definition block. */
/***********************************************************************/
class DllExport RELDEF : public BLOCK { // Relation definition block
friend class CATALOG;
friend class PLUGCAT;
friend class MYCAT;
public:
RELDEF(void); // Constructor
// Implementation
PRELDEF GetNext(void) {return Next;}
PSZ GetName(void) {return Name;}
PSZ GetDB(void) {return (PSZ)Database;}
PCOLDEF GetCols(void) {return To_Cols;}
void SetCols(PCOLDEF pcd) {To_Cols = pcd;}
PCATLG GetCat(void) {return Cat;}
virtual const char *GetType(void) = 0;
virtual AMT GetDefType(void) = 0;
// Methods
virtual bool DeleteTableFile(PGLOBAL g) {return true;}
virtual bool Indexable(void) {return false;}
virtual bool Define(PGLOBAL g, PCATLG cat, LPCSTR name, LPCSTR am) = 0;
virtual PTDB GetTable(PGLOBAL g, MODE mode) = 0;
protected:
PRELDEF Next; /* To next definition block */
PSZ Name; /* Name of the view */
LPCSTR Database; /* Table database */
PCOLDEF To_Cols; /* To a list of column desc */
PCATLG Cat; /* To DB catalog info */
}; // end of RELDEF
/***********************************************************************/
/* These classes correspond to the data base description contained in */
/* a .XDB file the A.M. DOS, FIX, CSV, MAP, BIN, VCT, PLG, ODBC, DOM. */
/***********************************************************************/
class DllExport TABDEF : public RELDEF { /* Logical table descriptor */
friend class CATALOG;
friend class PLUGCAT;
friend class MYCAT;
public:
// Constructor
TABDEF(void); // Constructor
// Implementation
int GetDegree(void) {return Degree;}
void SetDegree(int d) {Degree = d;}
int GetElemt(void) {return Elemt;}
void SetNext(PTABDEF tdfp) {Next = tdfp;}
int GetMultiple(void) {return Multiple;}
int GetPseudo(void) {return Pseudo;}
PSZ GetPath(void)
{return (Database) ? (PSZ)Database : Cat->GetDataPath();}
bool SepIndex(void) {return Cat->GetSepIndex();}
bool IsReadOnly(void) {return Read_Only;}
virtual AMT GetDefType(void) {return TYPE_AM_TAB;}
virtual PIXDEF GetIndx(void) {return NULL;}
virtual void SetIndx(PIXDEF xp) {}
virtual bool IsHuge(void) {return false;}
// Methods
bool DropTable(PGLOBAL g, PSZ name);
virtual bool Define(PGLOBAL g, PCATLG cat, LPCSTR name, LPCSTR am);
virtual bool DefineAM(PGLOBAL, LPCSTR, int) = 0;
protected:
// Members
PSZ Owner; /* Table owner (for ODBC) */
PSZ Desc; /* Table description */
int Card; /* (max) number of rows in table */
int Elemt; /* Number of rows in blocks or rowset */
int Sort; /* Table already sorted ??? */
int Multiple; /* 0: No 1: DIR 2: Section 3: filelist */
int Degree; /* Number of columns in the table */
int Pseudo; /* Bit: 1 ROWID Ok, 2 FILEID Ok */
bool Read_Only; /* true for read only tables */
}; // end of TABDEF
/***********************************************************************/
/* Externally defined OEM tables. */
/***********************************************************************/
class DllExport OEMDEF : public TABDEF { /* OEM table */
friend class CATALOG;
friend class PLUGCAT;
friend class MYCAT;
public:
// Constructor
OEMDEF(void) {Hdll = NULL; Pxdef = NULL; Module = Subtype = NULL;}
// Implementation
virtual const char *GetType(void) {return "OEM";}
virtual AMT GetDefType(void) {return TYPE_AM_OEM;}
// Methods
virtual bool DeleteTableFile(PGLOBAL g);
virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff);
virtual PTDB GetTable(PGLOBAL g, MODE mode);
protected:
PTABDEF GetXdef(PGLOBAL g);
// Members
#if defined(WIN32)
HANDLE Hdll; /* Handle to the external DLL */
#else // !WIN32
void *Hdll; /* Handle for the loaded shared library */
#endif // !WIN32
PTABDEF Pxdef; /* Pointer to the external TABDEF class */
char *Module; /* Path/Name of the DLL implenting it */
char *Subtype; /* The name of the OEM table sub type */
}; // end of OEMDEF
/***********************************************************************/
/* Column definition block used during creation. */
/***********************************************************************/
class DllExport COLCRT : public BLOCK { /* Column description block */
friend class TABDEF;
public:
COLCRT(PSZ name); // Constructor
COLCRT(void); // Constructor (for views)
// Implementation
PSZ GetName(void) {return Name;}
PSZ GetDecode(void) {return Decode;}
PSZ GetFmt(void) {return Fmt;}
int GetOpt(void) {return Opt;}
int GetLong(void) {return Long;}
int GetOffset(void) {return Offset;}
void SetOffset(int offset) {Offset = offset;}
protected:
PCOLCRT Next; /* To next block */
PSZ Name; /* Column name */
PSZ Desc; /* Column description */
PSZ Decode; /* Date format */
PSZ Fmt; /* Input format for formatted files */
int Offset; /* Offset of field within record */
int Long; /* Length of field in file record (!BIN) */
int Key; /* Key (greater than 1 if multiple) */
int Prec; /* Precision for float values */
int Opt; /* 0:Not 1:clustered 2:sorted-asc 3:desc */
char DataType; /* Internal data type (C, N, F, T) */
}; // end of COLCRT
/***********************************************************************/
/* Column definition block. */
/***********************************************************************/
class DllExport COLDEF : public COLCRT { /* Column description block */
friend class CATALOG;
friend class PLUGCAT;
friend class MYCAT;
friend class COLBLK;
friend class DBFFAM;
public:
COLDEF(void); // Constructor
// Implementation
PCOLDEF GetNext(void) {return (PCOLDEF)Next;}
void SetNext(PCOLDEF pcdf) {Next = pcdf;}
int GetLength(void) {return (int)F.Length;}
int GetClen(void) {return Clen;}
int GetType(void) {return Buf_Type;}
int GetPoff(void) {return Poff;}
int Define(PGLOBAL g, void *memp, PCOLINFO cfp, int poff);
void Define(PGLOBAL g, PCOL colp);
protected:
int Buf_Type; /* Internal data type */
int Clen; /* Internal data size in chars (bytes) */
int Poff; /* Calculated offset for Packed tables */
FORMAT F; /* Output format (should be in COLCRT) */
ushort Flags; /* Used by MariaDB CONNECT handler */
}; // end of COLDEF
#endif // __RELDEF_H

136
storage/connect/resource.h Normal file
View File

@@ -0,0 +1,136 @@
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by PlgSock.rc
//
#define IDS_00 115
#define IDS_01 116
#define IDS_02 117
#define IDS_03 118
#define IDS_04 119
#define IDS_05 120
#define IDS_06 121
#define IDS_07 122
#define IDS_08 123
#define IDS_09 124
#define IDS_10 125
#define IDS_11 126
#define IDS_12 127
#define IDS_13 128
#define IDS_14 129
#define IDS_15 130
#define IDS_16 131
#define IDS_17 132
#define IDS_18 133
#define IDS_19 134
#define IDS_20 135
#define IDS_21 136
#define IDS_TABLES 143
#define IDS_TAB_01 144
#define IDS_TAB_02 145
#define IDS_TAB_03 146
#define IDS_TAB_04 147
#define IDS_TAB_05 148
#define IDS_COLUMNS 159
#define IDS_COL_01 160
#define IDS_COL_02 161
#define IDS_COL_03 162
#define IDS_COL_04 163
#define IDS_COL_05 164
#define IDS_COL_06 165
#define IDS_COL_07 166
#define IDS_COL_08 167
#define IDS_COL_09 168
#define IDS_COL_10 169
#define IDS_COL_11 170
#define IDS_COL_12 171
#define IDS_INFO 175
#define IDS_INF_01 176
#define IDS_INF_02 177
#define IDS_INF_03 178
#define IDS_INF_04 179
#define IDS_INF_05 180
#define IDS_INF_06 181
#define IDS_INF_07 182
#define IDS_INF_08 183
#define IDS_INF_09 184
#define IDS_INF_10 185
#define IDS_INF_11 186
#define IDS_INF_12 187
#define IDS_INF_13 188
#define IDS_INF_14 189
#define IDS_INF_15 190
#define IDS_PKEY 191
#define IDS_PKY_01 192
#define IDS_PKY_02 193
#define IDS_PKY_03 194
#define IDS_PKY_04 195
#define IDS_PKY_05 196
#define IDS_PKY_06 197
#define IDS_FKEY 207
#define IDS_FKY_01 208
#define IDS_FKY_02 209
#define IDS_FKY_03 210
#define IDS_FKY_04 211
#define IDS_FKY_05 212
#define IDS_FKY_06 213
#define IDS_FKY_07 214
#define IDS_FKY_08 215
#define IDS_FKY_09 216
#define IDS_FKY_10 217
#define IDS_FKY_11 218
#define IDS_FKY_12 219
#define IDS_FKY_13 220
#define IDS_STAT 223
#define IDS_STA_01 224
#define IDS_STA_02 225
#define IDS_STA_03 226
#define IDS_STA_04 227
#define IDS_STA_05 228
#define IDS_STA_06 229
#define IDS_STA_07 230
#define IDS_STA_08 231
#define IDS_STA_09 232
#define IDS_STA_10 233
#define IDS_STA_11 234
#define IDS_STA_12 235
#define IDS_STA_13 236
#define IDS_SPCOLS 1247
#define IDS_SPC_01 1248
#define IDS_SPC_02 1249
#define IDS_SPC_03 1250
#define IDS_SPC_04 1251
#define IDS_SPC_05 1252
#define IDS_SPC_06 1253
#define IDS_SPC_07 1254
#define IDS_SPC_08 1255
#define IDS_CNX 1263
#define IDS_CNX_01 1264
#define IDS_CNX_02 1265
#define IDS_CNX_03 1266
#define IDS_CNX_04 1267
#define IDS_PLGCOL 1279
#define IDS_PLG_01 1280
#define IDS_PLG_02 1281
#define IDS_PLG_03 1282
#define IDS_PLG_04 1283
#define IDS_PLG_05 1284
#define IDS_PLG_06 1285
#define IDS_PLG_07 1286
#define IDS_PLG_08 1287
#define IDS_PLG_09 1288
#define IDS_DSC 1295
#define IDS_DSC_01 1296
#define IDS_DSC_02 1297
#define IDS_DSC_03 1298
#define IDS_DSC_04 1299
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 1300
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1440
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

30
storage/connect/sqlutil.h Normal file
View File

@@ -0,0 +1,30 @@
#define SQL_UNKNOWN_TYPE 0
#define SQL_CHAR 1
#define SQL_NUMERIC 2
#define SQL_DECIMAL 3
#define SQL_INTEGER 4
#define SQL_SMALLINT 5
#define SQL_FLOAT 6
#define SQL_REAL 7
#define SQL_DOUBLE 8
#define SQL_DATETIME 9
#define SQL_VARCHAR 12
#define SQL_TYPE_NULL 0
#define SQL_DATE 9
#define SQL_INTERVAL 10
#define SQL_TIME 10
#define SQL_TIMESTAMP 11
#define SQL_LONGVARCHAR (-1)
#define SQL_BINARY (-2)
#define SQL_VARBINARY (-3)
#define SQL_LONGVARBINARY (-4)
#define SQL_BIGINT (-5)
#define SQL_TINYINT (-6)
#define SQL_BIT (-7)
#define SQL_GUID (-11)
#define SQL_C_CHAR SQL_CHAR /* CHAR, VARCHAR, DECIMAL, NUMERIC */
#define SQL_C_LONG SQL_INTEGER /* INTEGER */
#define SQL_C_SHORT SQL_SMALLINT /* SMALLINT */
#define SQL_C_FLOAT SQL_REAL /* REAL */
#define SQL_C_DOUBLE SQL_DOUBLE /* FLOAT, DOUBLE */
#define SQL_C_TIMESTAMP SQL_TIMESTAMP

174
storage/connect/tabcol.cpp Normal file
View File

@@ -0,0 +1,174 @@
/************* TabCol C++ Functions Source Code File (.CPP) ************/
/* Name: TABCOL.CPP Version 2.6 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 1998-2012 */
/* */
/* This file contains the PlugDB++ XTAB, COLUMN and XORDER methods. */
/***********************************************************************/
/***********************************************************************/
/* Include relevant MariaDB header file. */
/***********************************************************************/
#if defined(OS16) || defined(OS32)
#include <os2def.h>
#else
#include "my_global.h"
#endif
/***********************************************************************/
/* Include required application header files */
/* global.h is header containing all global Plug declarations. */
/* plgdbsem.h is header containing the DB applic. declarations. */
/* tabcol.h is header containing XTAB, and XORDER declares. */
/***********************************************************************/
#include "global.h"
#include "plgdbsem.h"
#include "xtable.h"
#include "tabcol.h"
/***********************************************************************/
/* XTAB public constructor (in which Correl defaults to Name). */
/***********************************************************************/
XTAB::XTAB(LPCSTR name, LPCSTR correl) : Name(name)
{
Next = NULL;
To_Tdb = NULL;
Correl = (correl) ? correl : name;
Creator = NULL;
Qualifier = NULL;
#ifdef DEBTRACE
htrc(" making new TABLE %s %s\n", Name, Correl);
#endif
} // end of XTAB constructor
/***********************************************************************/
/* XTAB public constructor as a copy of another table. */
/***********************************************************************/
XTAB::XTAB(PTABLE tp) : Name(tp->Name)
{
Next = NULL;
To_Tdb = NULL;
Correl = tp->Correl;
Creator = tp->Creator;
Qualifier = tp->Qualifier;
#ifdef DEBTRACE
htrc(" making copy TABLE %s %s\n", Name, Correl);
#endif
} // end of XTAB constructor
/***********************************************************************/
/* Link the tab2 tables to the tab1(this) table chain. */
/***********************************************************************/
PTABLE XTAB::Link(PTABLE tab2)
{
PTABLE tabp;
#ifdef DEBTRACE
htrc("Linking tables %s... to %s\n", Name, tab2->Name);
#endif
for (tabp = this; tabp->Next; tabp = tabp->Next) ;
tabp->Next = tab2;
return (this);
} /* end of Link */
/***********************************************************************/
/* Make file output of XTAB contents. */
/***********************************************************************/
void XTAB::Print(PGLOBAL g, FILE *f, uint n)
{
char m[64];
memset(m, ' ', n); /* Make margin string */
m[n] = '\0';
for (PTABLE tp = this; tp; tp = tp->Next) {
fprintf(f, "%sTABLE: %s.%s %s\n",
m, SVP(tp->Creator), tp->Name, SVP(tp->Correl));
PlugPutOut(g, f, TYPE_TDB, tp->To_Tdb, n + 2);
} /* endfor tp */
} /* end of Print */
/***********************************************************************/
/* Make string output of XTAB contents. */
/***********************************************************************/
void XTAB::Print(PGLOBAL g, char *ps, uint z)
{
char buf[128];
int i, n = (int)z - 1;
*ps = '\0';
for (PTABLE tp = this; tp && n > 0; tp = tp->Next) {
i = sprintf(buf, "TABLE: %s.%s %s To_Tdb=%p ",
SVP(tp->Creator), tp->Name, SVP(tp->Correl), tp->To_Tdb);
strncat(ps, buf, n);
n -= i;
} // endif tp
} /* end of Print */
/***********************************************************************/
/* COLUMN public constructor. */
/***********************************************************************/
COLUMN::COLUMN(LPCSTR name) : Name(name)
{
To_Table = NULL;
To_Col = NULL;
Qualifier = NULL;
#ifdef DEBTRACE
htrc(" making new COLUMN %s\n", Name);
#endif
} // end of COLUMN constructor
/***********************************************************************/
/* COLUMN SetFormat: should never be called. */
/***********************************************************************/
bool COLUMN::SetFormat(PGLOBAL g, FORMAT& fmt)
{
strcpy(g->Message, MSG(NO_FORMAT_COL));
return true;
} // end of SetFormat
/***********************************************************************/
/* Make file output of COLUMN contents. */
/***********************************************************************/
void COLUMN::Print(PGLOBAL g, FILE *f, uint n)
{
char m[64];
memset(m, ' ', n); // Make margin string
m[n] = '\0';
if (Name)
fprintf(f, "%sCOLUMN: %s.%s\n", m,
((!Qualifier) ? (PSZ)"?" : Qualifier), Name);
else // LNA
fprintf(f, "%sC%d\n", m, (!Qualifier) ? 0 : *(int *)Qualifier);
PlugPutOut(g, f, TYPE_TABLE, To_Table, n + 2);
PlugPutOut(g, f, TYPE_XOBJECT, To_Col, n + 2);
} /* end of Print */
/***********************************************************************/
/* Make string output of COLUMN contents. */
/***********************************************************************/
void COLUMN::Print(PGLOBAL g, char *ps, uint z)
{
char buf[80];
if (Name)
sprintf(buf, "COLUMN: %s.%s table=%p col=%p",
((!Qualifier) ? (PSZ)"?" : Qualifier), Name, To_Table, To_Col);
else // LNA
sprintf(buf, "C%d", (!Qualifier) ? 0 : *(int *)Qualifier);
strncpy(ps, buf, z);
ps[z - 1] = '\0';
} /* end of Print */

110
storage/connect/tabcol.h Normal file
View File

@@ -0,0 +1,110 @@
/*************** TabCol H Declares Source Code File (.H) ***************/
/* Name: TABCOL.H Version 2.7 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 1998-2012 */
/* */
/* This file contains the XTAB, COLUMN and XORDER class definitions. */
/***********************************************************************/
/***********************************************************************/
/* Include required application header files */
/* block.h is header containing Block global declarations. */
/***********************************************************************/
#include "xobject.h"
/***********************************************************************/
/* Definition of class XTAB with all its method functions. */
/***********************************************************************/
class DllExport XTAB: public BLOCK { // Table Name-Owner-Correl block.
public:
// Constructors
XTAB(LPCSTR name, LPCSTR correl = NULL);
XTAB(PTABLE tp);
// Implementation
PTABLE GetNext(void) {return Next;}
PTDB GetTo_Tdb(void) {return To_Tdb;}
LPCSTR GetName(void) {return Name;}
LPCSTR GetCorrel(void) {return Correl;}
LPCSTR GetCreator(void) {return Creator;}
LPCSTR GetQualifier(void) {return Qualifier;}
void SetTo_Tdb(PTDB tdbp) {To_Tdb = tdbp;}
void SetName(LPCSTR name) {Name = name;}
void SetCorrel(LPCSTR correl) {Correl = correl;}
void SetCreator(LPCSTR crname) {Creator = crname;}
void SetQualifier(LPCSTR qname) {Qualifier = qname;}
// Methods
PTABLE Link(PTABLE);
void Print(PGLOBAL g, FILE *f, uint n);
void Print(PGLOBAL g, char *ps, uint z);
protected:
// Members
PTABLE Next; // Points to next table in chain
PTDB To_Tdb; // Points to Table description Block
LPCSTR Name; // Table name (can be changed by LNA and PLG)
LPCSTR Correl; // Correlation name
LPCSTR Creator; // Creator name
LPCSTR Qualifier; // Qualifier name
}; // end of class XTAB
/***********************************************************************/
/* Definition of class COLUMN with all its method functions. */
/* Note: because of LNA routines, the constantness of Name was */
/* removed and constructing a COLUMN with null name was allowed. */
/* Perhaps this should be replaced by the use of a specific class. */
/***********************************************************************/
class DllExport COLUMN: public XOBJECT { // Column Name/Qualifier block.
public:
// Constructor
COLUMN(LPCSTR name);
// Implementation
virtual int GetType(void) {return TYPE_COLUMN;}
virtual int GetResultType(void) {assert(false); return TYPE_VOID;}
virtual int GetLength(void) {assert(false); return 0;}
virtual int GetLengthEx(void) {assert(false); return 0;}
virtual int GetPrecision() {assert(false); return 0;};
LPCSTR GetName(void) {return Name;}
LPCSTR GetQualifier(void) {return Qualifier;}
PTABLE GetTo_Table(void) {return To_Table;}
PCOL GetTo_Col(void) {return To_Col;}
void SetQualifier(LPCSTR qualif) {Qualifier = qualif;}
void SetTo_Table(PTABLE tablep) {To_Table = tablep;}
void SetTo_Col(PCOL colp) {To_Col = colp;}
// Methods
virtual void Print(PGLOBAL g, FILE *f, uint n);
virtual void Print(PGLOBAL g, char *ps, uint z);
// All methods below should never be used for COLUMN's
virtual void Reset(void) {assert(false);}
virtual bool Compare(PXOB) {assert(false); return false;}
virtual bool SetFormat(PGLOBAL, FORMAT&);
virtual bool Eval(PGLOBAL) {assert(false); return true;}
virtual int CheckSpcCol(PTDB, int) {assert(false); return 2;}
virtual bool CheckSort(PTDB) {assert(false); return false;}
virtual void MarkCol(ushort) {assert(false);}
private:
// Members
PTABLE To_Table; // Point to Table Name Block
PCOL To_Col; // Points to Column Description Block
LPCSTR const Name; // Column name
LPCSTR Qualifier; // Qualifier name
}; // end of class COLUMN
/***********************************************************************/
/* Definition of class SPCCOL with all its method functions. */
/* Note: Currently the special columns are ROWID, ROWNUM, FILEID, */
/* SERVID, TABID, and CONID. */
/***********************************************************************/
class SPCCOL: public COLUMN { // Special Column Name/Qualifier block.
public:
// Constructor
SPCCOL(LPCSTR name) : COLUMN(name) {}
private:
// Members
}; // end of class SPCCOL

1228
storage/connect/tabdos.cpp Normal file

File diff suppressed because it is too large Load Diff

246
storage/connect/tabdos.h Normal file
View File

@@ -0,0 +1,246 @@
/*************** TabDos H Declares Source Code File (.H) ***************/
/* Name: TABDOS.H Version 3.2 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 1999-2012 */
/* */
/* This file contains the DOS classes declares. */
/***********************************************************************/
#ifndef __TABDOS_H
#define __TABDOS_H
#include "xtable.h" // Table base class declares
#include "colblk.h" // Column base class declares
#include "xindex.h"
typedef struct _tabdesc *PTABD; // For friend setting
typedef class TXTFAM *PTXF;
/***********************************************************************/
/* DOS table. */
/***********************************************************************/
class DllExport DOSDEF : public TABDEF { /* Logical table description */
friend class OEMDEF;
friend class TDBDOS;
friend class TDBFIX;
friend class TXTFAM;
friend class DBFBASE;
public:
// Constructor
DOSDEF(void);
// Implementation
virtual AMT GetDefType(void) {return TYPE_AM_DOS;}
virtual const char *GetType(void) {return "DOS";}
virtual PIXDEF GetIndx(void) {return To_Indx;}
virtual void SetIndx(PIXDEF xdp) {To_Indx = xdp;}
PSZ GetOfn(void) {return Ofn;}
void SetBlock(int block) {Block = block;}
int GetBlock(void) {return Block;}
int GetLast(void) {return Last;}
void SetLast(int last) {Last = last;}
int GetLrecl(void) {return Lrecl;}
void SetLrecl(int lrecl) {Lrecl = lrecl;}
bool GetPadded(void) {return Padded;}
bool GetEof(void) {return Eof;}
int GetBlksize(void) {return Blksize;}
int GetEnding(void) {return Ending;}
int *GetTo_Pos(void) {return To_Pos;}
virtual bool IsHuge(void) {return Huge;}
// Methods
virtual bool DeleteTableFile(PGLOBAL g);
virtual bool Indexable(void) {return Compressed != 1;}
virtual bool DeleteIndexFile(PGLOBAL g, PIXDEF pxdf);
virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff);
virtual PTDB GetTable(PGLOBAL g, MODE mode);
bool InvalidateIndex(PGLOBAL g);
protected:
virtual bool Erase(char *filename);
// Members
PSZ Fn; /* Path/Name of corresponding file */
PSZ Ofn; /* Base Path/Name of matching index files*/
PIXDEF To_Indx; /* To index definitions blocks */
RECFM Recfm; /* 0:VAR, 1:FIX, 2:BIN, 3:VCT, 6:DBF */
bool Mapped; /* 0: disk file, 1: memory mapped file */
bool Padded; /* true for padded table file */
bool Huge; /* true for files larger than 2GB */
bool Accept; /* true if wrong lines are accepted (DBF)*/
bool Eof; /* true if an EOF (0xA) character exists */
int *To_Pos; /* To array of block starting positions */
int Compressed; /* 0: No, 1: gz, 2:zlib compressed file */
int Lrecl; /* Size of biggest record */
int AvgLen; /* Average size of records */
int Block; /* Number de blocks of FIX/VCT tables */
int Last; /* Number of elements of last block */
int Blksize; /* Size of padded blocks */
int Maxerr; /* Maximum number of bad records (DBF) */
int ReadMode; /* Specific to DBF */
int Ending; /* Length of end of lines */
}; // end of DOSDEF
/***********************************************************************/
/* This is the DOS/UNIX Access Method class declaration for files */
/* that are standard files with columns starting at fixed offset. */
/* The last column (and record) is of variable length. */
/***********************************************************************/
class DllExport TDBDOS : public TDBASE {
//friend class KINDEX;
friend class XINDEX;
friend class DOSCOL;
friend class MAPCOL;
friend class TXTFAM;
friend class DOSFAM;
friend class VCTCOL;
//friend class TDBMUL;
friend RCODE CntDeleteRow(PGLOBAL, PTDB, bool);
public:
// Constructors
TDBDOS(PDOSDEF tdp, PTXF txfp);
TDBDOS(PGLOBAL g, PTDBDOS tdbp);
// Inline functions
inline void SetTxfp(PTXF txfp) {Txfp = txfp; Txfp->SetTdbp(this);}
inline PTXF GetTxfp(void) {return Txfp;}
inline char *GetLine(void) {return To_Line;}
inline int GetCurBlk(void) {return Txfp->GetCurBlk();}
inline void SetLine(char *toline) {To_Line = toline;}
inline void IncLine(int inc) {To_Line += inc;}
inline bool IsRead(void) {return Txfp->IsRead;}
inline PXOB *GetLink(void) {return To_Link;}
//inline PCOL *GetKeyCol(void) {return To_Key_Col;}
// Implementation
virtual AMT GetAmType(void) {return Txfp->GetAmType();}
virtual PSZ GetFile(PGLOBAL g) {return Txfp->To_File;}
virtual void SetFile(PGLOBAL g, PSZ fn) {Txfp->To_File = fn;}
virtual RECFM GetFtype(void) {return Ftype;}
virtual bool SkipHeader(PGLOBAL g) {return false;}
virtual void RestoreNrec(void) {Txfp->SetNrec(1);}
virtual PTDB Duplicate(PGLOBAL g)
{return (PTDB)new(g) TDBDOS(g, this);}
// Methods
virtual PTDB CopyOne(PTABS t);
virtual void ResetDB(void) {Txfp->Reset();}
virtual bool IsUsingTemp(PGLOBAL g);
//virtual bool NeedIndexing(PGLOBAL g);
virtual void ResetSize(void) {MaxSize = Cardinal = -1;}
virtual int ResetTableOpt(PGLOBAL g, bool dox);
//virtual int MakeBlockValues(PGLOBAL g);
//virtual bool SaveBlockValues(PGLOBAL g);
//virtual bool GetBlockValues(PGLOBAL g);
//virtual PBF InitBlockFilter(PGLOBAL g, PFIL filp);
//virtual PBX InitBlockIndex(PGLOBAL g);
//virtual int TestBlock(PGLOBAL g);
virtual void PrintAM(FILE *f, char *m);
// Database routines
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
virtual char *GetOpenMode(PGLOBAL g, char *opmode) {return NULL;}
virtual int GetFileLength(PGLOBAL g) {return Txfp->GetFileLength(g);}
virtual int GetProgMax(PGLOBAL g);
virtual int GetProgCur(void);
virtual int GetAffectedRows(void) {return Txfp->GetDelRows();}
virtual int GetRecpos(void) {return Txfp->GetPos();}
virtual bool SetRecpos(PGLOBAL g, int recpos)
{return Txfp->SetPos(g, recpos);}
virtual int RowNumber(PGLOBAL g, bool b = false);
virtual int Cardinality(PGLOBAL g);
virtual int GetMaxSize(PGLOBAL g);
virtual bool OpenDB(PGLOBAL g);
virtual int ReadDB(PGLOBAL g);
virtual int WriteDB(PGLOBAL g);
virtual int DeleteDB(PGLOBAL g, int irc);
virtual void CloseDB(PGLOBAL g);
virtual int ReadBuffer(PGLOBAL g) {return Txfp->ReadBuffer(g);}
// Specific routine
virtual int EstimatedLength(PGLOBAL g);
// Optimization routines
// void ResetBlockFilter(PGLOBAL g);
int MakeIndex(PGLOBAL g, PIXDEF pxdf, bool add);
// bool GetDistinctColumnValues(PGLOBAL g, int nrec);
protected:
// PBF CheckBlockFilari(PGLOBAL g, PXOB *arg, int op, bool *cnv);
// Members
PTXF Txfp; // To the File access method class
//PBX To_BlkIdx; // To index test block
//PBF To_BlkFil; // To evaluation block filter
//PFIL SavFil; // Saved hidden filter
char *To_Line; // Points to current processed line
int Cardinal; // Table Cardinality
RECFM Ftype; // File type: 0-var 1-fixed 2-binary (VCT)
int Lrecl; // Logical Record Length
int AvgLen; // Logical Record Average Length
//int Xeval; // BlockTest return value
//int Beval; // BlockEval return value
}; // end of class TDBDOS
/***********************************************************************/
/* Class DOSCOL: DOS access method column descriptor. */
/* This A.M. is used for text file tables under operating systems */
/* DOS, OS2, UNIX, WIN16 and WIN32. */
/***********************************************************************/
class DllExport DOSCOL : public COLBLK {
friend class TDBDOS;
friend class TDBFIX;
public:
// Constructors
DOSCOL(PGLOBAL g, PCOLDEF cdp, PTDB tp, PCOL cp, int i, PSZ am = "DOS");
DOSCOL(DOSCOL *colp, PTDB tdbp); // Constructor used in copy process
// Implementation
virtual int GetAmType(void) {return TYPE_AM_DOS;}
//virtual int GetClustered(void) {return Clustered;}
//virtual int IsClustered(void) {return (Clustered &&
// ((PDOSDEF)(((PTDBDOS)To_Tdb)->To_Def))->IsOptimized());}
//virtual int IsSorted(void) {return Sorted;}
virtual void SetTo_Val(PVAL valp) {To_Val = valp;}
//virtual PVBLK GetMin(void) {return Min;}
//virtual PVBLK GetMax(void) {return Max;}
//virtual int GetNdv(void) {return Ndv;}
//virtual int GetNbm(void) {return Nbm;}
//virtual PVBLK GetBmap(void) {return Bmap;}
//virtual PVBLK GetDval(void) {return Dval;}
// Methods
virtual bool VarSize(void);
virtual bool SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check);
virtual void ReadColumn(PGLOBAL g);
virtual void WriteColumn(PGLOBAL g);
virtual void Print(PGLOBAL g, FILE *, uint);
protected:
//virtual bool SetMinMax(PGLOBAL g);
//virtual bool SetBitMap(PGLOBAL g);
// bool CheckSorted(PGLOBAL g);
// bool AddDistinctValue(PGLOBAL g);
// Default constructor not to be used
DOSCOL(void) {}
// Members
//PVBLK Min; // Array of block min values
//PVBLK Max; // Array of block max values
//PVBLK Bmap; // Array of block bitmap values
//PVBLK Dval; // Array of column distinct values
PVAL To_Val; // To value used for Update/Insert
PVAL OldVal; // The previous value of the object.
char *Buf; // Buffer used in write operations
bool Ldz; // True if field contains leading zeros
bool Nod; // True if no decimal point
int Dcm; // Last Dcm digits are decimals
//int Clustered; // 0:No 1:Yes
//int Sorted; // 0:No 1:Asc (2:Desc - NIY)
int Deplac; // Offset in dos_buf
//int Ndv; // Number of distinct values
//int Nbm; // Number of uint in bitmap
}; // end of class DOSCOL
#endif // __TABDOS_H

478
storage/connect/tabfix.cpp Normal file
View File

@@ -0,0 +1,478 @@
/************* TabFix C++ Program Source Code File (.CPP) **************/
/* PROGRAM NAME: TABFIX */
/* ------------- */
/* Version 4.8 */
/* */
/* COPYRIGHT: */
/* ---------- */
/* (C) Copyright to the author Olivier BERTRAND 1998-2012 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
/* This program are the TDBFIX class DB routines. */
/* */
/***********************************************************************/
/***********************************************************************/
/* Include relevant section of system dependant header files. */
/***********************************************************************/
#include "my_global.h"
#if defined(WIN32)
#include <io.h>
#include <fcntl.h>
#include <errno.h>
#if defined(__BORLANDC__)
#define __MFC_COMPAT__ // To define min/max as macro
#endif // __BORLANDC__
//#include <windows.h>
#else // !WIN32
#if defined(UNIX)
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#else // !UNIX
#include <io.h>
#endif // !UNIX
#include <fcntl.h>
#endif // !WIN32
/***********************************************************************/
/* Include application header files: */
/***********************************************************************/
#include "global.h" // global declares
#include "plgdbsem.h" // DB application declares
#include "filamfix.h"
#include "filamdbf.h"
#include "tabfix.h" // TDBFIX, FIXCOL classes declares
/***********************************************************************/
/* DB static variables. */
/***********************************************************************/
extern "C" int trace;
extern int num_read, num_there, num_eq[2]; // Statistics
static const longlong M2G = 0x80000000;
static const longlong M4G = (longlong)2 * M2G;
/* ------------------------------------------------------------------- */
/***********************************************************************/
/* Implementation of the TDBFIX class. */
/***********************************************************************/
TDBFIX::TDBFIX(PDOSDEF tdp, PTXF txfp) : TDBDOS(tdp, txfp)
{
//Cardinal = -1;
} // end of TDBFIX standard constructor
TDBFIX::TDBFIX(PGLOBAL g, PTDBFIX tdbp) : TDBDOS(g, tdbp)
{
//Cardinal = tdbp->Cardinal;
} // end of TDBFIX copy constructor
// Method
PTDB TDBFIX::CopyOne(PTABS t)
{
PTDB tp;
PGLOBAL g = t->G;
tp = new(g) TDBFIX(g, this);
if (Ftype < 2) {
// File is text
PDOSCOL cp1, cp2;
for (cp1 = (PDOSCOL)Columns; cp1; cp1 = (PDOSCOL)cp1->GetNext()) {
cp2 = new(g) DOSCOL(cp1, tp); // Make a copy
NewPointer(t, cp1, cp2);
} // endfor cp1
} else {
// File is binary
PBINCOL cp1, cp2;
for (cp1 = (PBINCOL)Columns; cp1; cp1 = (PBINCOL)cp1->GetNext()) {
cp2 = new(g) BINCOL(cp1, tp); // Make a copy
NewPointer(t, cp1, cp2);
} // endfor cp1
} // endif Ftype
return tp;
} // end of CopyOne
/***********************************************************************/
/* Reset read/write position values. */
/***********************************************************************/
void TDBFIX::ResetDB(void)
{
TDBDOS::ResetDB();
} // end of ResetDB
/***********************************************************************/
/* Allocate FIX (DOS) or BIN column description block. */
/***********************************************************************/
PCOL TDBFIX::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
{
if (Ftype == RECFM_BIN)
return new(g) BINCOL(g, cdp, this, cprec, n);
else
return new(g) DOSCOL(g, cdp, this, cprec, n);
} // end of MakeCol
/***********************************************************************/
/* Remake the indexes after the table was modified. */
/***********************************************************************/
int TDBFIX::ResetTableOpt(PGLOBAL g, bool dox)
{
RestoreNrec(); // May have been modified
return TDBDOS::ResetTableOpt(g, dox);
} // end of ResetTableOpt
/***********************************************************************/
/* Reset the Nrec and BlkSize values that can have been modified. */
/***********************************************************************/
void TDBFIX::RestoreNrec(void)
{
if (!Txfp->Padded) {
Txfp->Nrec = (To_Def && To_Def->GetElemt()) ? To_Def->GetElemt()
: DOS_BUFF_LEN;
Txfp->Blksize = Txfp->Nrec * Txfp->Lrecl;
} // endif Padded
} // end of RestoreNrec
/***********************************************************************/
/* FIX Cardinality: returns table cardinality in number of rows. */
/* This function can be called with a null argument to test the */
/* availability of Cardinality implementation (1 yes, 0 no). */
/***********************************************************************/
int TDBFIX::Cardinality(PGLOBAL g)
{
if (!g)
return Txfp->Cardinality(g);
if (Cardinal < 0)
Cardinal = Txfp->Cardinality(g);
return Cardinal;
} // end of Cardinality
/***********************************************************************/
/* FIX GetMaxSize: returns file size in number of lines. */
/***********************************************************************/
int TDBFIX::GetMaxSize(PGLOBAL g)
{
if (MaxSize < 0)
MaxSize = Cardinality(g);
return MaxSize;
} // end of GetMaxSize
/***********************************************************************/
/* FIX ResetSize: Must reset Headlen for DBF tables only. */
/***********************************************************************/
void TDBFIX::ResetSize(void)
{
if (Txfp->GetAmType() == TYPE_AM_DBF)
Txfp->Headlen = 0;
MaxSize = Cardinal = -1;
} // end of ResetSize
/***********************************************************************/
/* FIX GetProgMax: get the max value for progress information. */
/***********************************************************************/
int TDBFIX::GetProgMax(PGLOBAL g)
{
return Cardinality(g);
} // end of GetProgMax
/***********************************************************************/
/* RowNumber: return the ordinal number of the current row. */
/***********************************************************************/
int TDBFIX::RowNumber(PGLOBAL g, bool b)
{
if (Txfp->GetAmType() == TYPE_AM_DBF) {
if (!b && To_Kindex) {
/*****************************************************************/
/* Don't know how to retrieve Rows from DBF file address */
/* because of eventual deleted lines still in the file. */
/*****************************************************************/
sprintf(g->Message, MSG(NO_ROWID_FOR_AM),
GetAmName(g, Txfp->GetAmType()));
return 0;
} // endif To_Kindex
if (!b)
return Txfp->GetRows();
} // endif DBF
return Txfp->GetRowID();
} // end of RowNumber
/***********************************************************************/
/* FIX tables don't use temporary files except if specified as do it. */
/***********************************************************************/
bool TDBFIX::IsUsingTemp(PGLOBAL g)
{
USETEMP usetemp = PlgGetUser(g)->UseTemp;
return (usetemp == TMP_YES || usetemp == TMP_FORCE);
} // end of IsUsingTemp
/***********************************************************************/
/* FIX Access Method opening routine (also used by the BIN a.m.) */
/* New method now that this routine is called recursively (last table */
/* first in reverse order): index blocks are immediately linked to */
/* join block of next table if it exists or else are discarted. */
/***********************************************************************/
bool TDBFIX::OpenDB(PGLOBAL g)
{
if (trace)
htrc("FIX OpenDB: tdbp=%p tdb=R%d use=%d key=%p mode=%d Ftype=%d\n",
this, Tdb_No, Use, To_Key_Col, Mode, Ftype);
if (Use == USE_OPEN) {
/*******************************************************************/
/* Table already open, just replace it at its beginning. */
/*******************************************************************/
if (To_Kindex)
/*****************************************************************/
/* Table is to be accessed through a sorted index table. */
/*****************************************************************/
To_Kindex->Reset();
else
Txfp->Rewind(); // see comment in Work.log
return false;
} // endif use
/*********************************************************************/
/* Call Cardinality to calculate Block in the case of Func queries. */
/* and also in the case of multiple tables. */
/*********************************************************************/
if (Cardinality(g) < 0)
return true;
/*********************************************************************/
/* Open according to required logical input/output mode. */
/* Use conventionnal input/output functions. */
/* Treat fixed length text files as binary. */
/*********************************************************************/
if (Txfp->OpenTableFile(g))
return true;
Use = USE_OPEN; // Do it now in case we are recursively called
/*********************************************************************/
/* Initialize To_Line at the beginning of the block buffer. */
/*********************************************************************/
To_Line = Txfp->GetBuf(); // For WriteDB
if (trace)
htrc("OpenDos: R%hd mode=%d\n", Tdb_No, Mode);
/*********************************************************************/
/* Reset buffer access according to indexing and to mode. */
/*********************************************************************/
Txfp->ResetBuffer(g);
/*********************************************************************/
/* Reset statistics values. */
/*********************************************************************/
num_read = num_there = num_eq[0] = num_eq[1] = 0;
return false;
} // end of OpenDB
/***********************************************************************/
/* WriteDB: Data Base write routine for FIX access method. */
/***********************************************************************/
int TDBFIX::WriteDB(PGLOBAL g)
{
return Txfp->WriteBuffer(g);
} // end of WriteDB
// ------------------------ BINCOL functions ----------------------------
/***********************************************************************/
/* BINCOL public constructor. */
/***********************************************************************/
BINCOL::BINCOL(PGLOBAL g, PCOLDEF cdp, PTDB tp, PCOL cp, int i, PSZ am)
: DOSCOL(g, cdp, tp, cp, i, am)
{
Fmt = (cdp->GetFmt()) ? toupper(*cdp->GetFmt()) : 'X';
} // end of BINCOL constructor
/***********************************************************************/
/* FIXCOL constructor used for copying columns. */
/* tdbp is the pointer to the new table descriptor. */
/***********************************************************************/
BINCOL::BINCOL(BINCOL *col1, PTDB tdbp) : DOSCOL(col1, tdbp)
{
Fmt = col1->Fmt;
} // end of BINCOL copy constructor
/***********************************************************************/
/* ReadColumn: what this routine does is to access the last line */
/* read from the corresponding table and extract from it the field */
/* corresponding to this column. */
/***********************************************************************/
void BINCOL::ReadColumn(PGLOBAL g)
{
char *p;
int rc;
PTDBFIX tdbp = (PTDBFIX)To_Tdb;
if (trace)
htrc("BIN ReadColumn: col %s R%d coluse=%.4X status=%.4X buf_type=%d\n",
Name, tdbp->GetTdb_No(), ColUse, Status, Buf_Type);
/*********************************************************************/
/* If physical reading of the line was deferred, do it now. */
/*********************************************************************/
if (!tdbp->IsRead())
if ((rc = tdbp->ReadBuffer(g)) != RC_OK) {
if (rc == RC_EF)
sprintf(g->Message, MSG(INV_DEF_READ), rc);
longjmp(g->jumper[g->jump_level], 11);
} // endif
p = tdbp->To_Line + Deplac;
/*********************************************************************/
/* Set Value from the line field. */
/*********************************************************************/
switch (Fmt) {
case 'X': // Standard not converted values
Value->SetBinValue(p);
break;
case 'S': // Short integer
Value->SetValue((int)*(short*)p);
break;
case 'T': // Tiny integer
Value->SetValue((int)*p);
break;
case 'I': // Integer or
case 'L': // Long Integer
Value->SetValue(*(int*)p);
break;
case 'F': // Float
case 'R': // Real
Value->SetValue((double)*(float*)p);
break;
case 'D': // Double
Value->SetValue(*(double*)p);
break;
case 'C': // Text
Value->SetValue_char(p, Long);
break;
default:
sprintf(g->Message, MSG(BAD_BIN_FMT), Fmt, Name);
longjmp(g->jumper[g->jump_level], 11);
} // endswitch Fmt
} // 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. */
/***********************************************************************/
void BINCOL::WriteColumn(PGLOBAL g)
{
char *p, *s;
int n;
PTDBFIX tdbp = (PTDBFIX)To_Tdb;
if (trace) {
htrc("BIN WriteColumn: col %s R%d coluse=%.4X status=%.4X",
Name, tdbp->GetTdb_No(), ColUse, Status);
htrc(" Lrecl=%d\n", tdbp->Lrecl);
htrc("Long=%d deplac=%d coltype=%d ftype=%c\n",
Long, Deplac, Buf_Type, *Format.Type);
} // endif trace
/*********************************************************************/
/* Check whether the new value has to be converted to Buf_Type. */
/*********************************************************************/
if (Value != To_Val)
Value->SetValue_pval(To_Val, false); // Convert the updated value
p = tdbp->To_Line + Deplac;
/*********************************************************************/
/* Check whether updating is Ok, meaning col value is not too long. */
/* Updating will be done only during the second pass (Status=true) */
/* Conversion occurs if the external format Fmt is specified. */
/*********************************************************************/
switch (Fmt) {
case 'X':
// Standard not converted values
if (Value->GetBinValue(p, Long, Status)) {
sprintf(g->Message, MSG(BIN_F_TOO_LONG),
Name, Value->GetSize(), Long);
longjmp(g->jumper[g->jump_level], 31);
} // endif Fmt
break;
case 'S': // Short integer
n = Value->GetIntValue();
if (n > 32767 || n < -32768) {
sprintf(g->Message, MSG(VALUE_TOO_BIG), n, Name);
longjmp(g->jumper[g->jump_level], 31);
} else if (Status)
*(short *)p = (short)n;
break;
case 'T': // Short integer
n = Value->GetIntValue();
if (n > 255 || n < -256) {
sprintf(g->Message, MSG(VALUE_TOO_BIG), n, Name);
longjmp(g->jumper[g->jump_level], 31);
} else if (Status)
*p = (char)n;
break;
case 'I': // Integer or
case 'L': // Long Integer
if (Status)
*(int *)p = Value->GetIntValue();
break;
case 'F': // Float
case 'R': // Real
if (Status)
*(float *)p = (float)Value->GetFloatValue();
break;
case 'D': // Double
if (Status)
*(double *)p = Value->GetFloatValue();
break;
case 'C': // Characters
if ((n = (signed)strlen(Value->GetCharString(Buf))) > Long) {
sprintf(g->Message, MSG(BIN_F_TOO_LONG), Name, n, Long);
longjmp(g->jumper[g->jump_level], 31);
} // endif n
if (Status) {
s = Value->GetCharString(Buf);
memset(p, ' ', Long);
memcpy(p, s, strlen(s));
} // endif Status
break;
default:
sprintf(g->Message, MSG(BAD_BIN_FMT), Fmt, Name);
longjmp(g->jumper[g->jump_level], 11);
} // endswitch Fmt
} // end of WriteColumn
/* ------------------------ End of TabFix ---------------------------- */

80
storage/connect/tabfix.h Normal file
View File

@@ -0,0 +1,80 @@
/*************** TabDos H Declares Source Code File (.H) ***************/
/* Name: TABFIX.H Version 2.3 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 1999-2012 */
/* */
/* This file contains the TDBFIX and (FIX/BIN)COL classes declares. */
/***********************************************************************/
#ifndef __TABFIX__
#define __TABFIX__
#include "tabdos.h" /* Base class declares */
typedef class FIXCOL *PFIXCOL;
typedef class BINCOL *PBINCOL;
typedef class TXTFAM *PTXF;
/***********************************************************************/
/* This is the DOS/UNIX Access Method class declaration for files */
/* that are standard files with columns starting at fixed offset. */
/* This class is for fixed formatted files. */
/***********************************************************************/
class DllExport TDBFIX : public TDBDOS {
friend class FIXCOL;
friend class BINCOL;
public:
// Constructor
TDBFIX(PDOSDEF tdp, PTXF txfp);
TDBFIX(PGLOBAL g, PTDBFIX tdbp);
// Implementation
virtual AMT GetAmType(void) {return TYPE_AM_FIX;}
virtual void RestoreNrec(void);
virtual PTDB Duplicate(PGLOBAL g)
{return (PTDB)new(g) TDBFIX(g, this);}
// Methods
virtual PTDB CopyOne(PTABS t);
virtual void ResetDB(void);
virtual bool IsUsingTemp(PGLOBAL g);
virtual int RowNumber(PGLOBAL g, bool b = false);
virtual int ResetTableOpt(PGLOBAL g, bool dox);
virtual void ResetSize(void);
virtual int GetBadLines(void) {return Txfp->GetNerr();}
// Database routines
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
virtual int GetProgMax(PGLOBAL g);
virtual int Cardinality(PGLOBAL g);
virtual int GetMaxSize(PGLOBAL g);
virtual bool OpenDB(PGLOBAL g);
virtual int WriteDB(PGLOBAL g);
protected:
// Members are inherited from TDBDOS
}; // end of class TDBFIX
/***********************************************************************/
/* Class BINCOL: BIN access method column descriptor. */
/* This A.M. is used for file processed by blocks. */
/***********************************************************************/
class DllExport BINCOL : public DOSCOL {
friend class TDBFIX;
public:
// Constructors
BINCOL(PGLOBAL g, PCOLDEF cdp, PTDB tp, PCOL cp, int i, PSZ am = "BIN");
BINCOL(BINCOL *colp, PTDB tdbp); // Constructor used in copy process
// Implementation
virtual int GetAmType(void) {return TYPE_AM_BIN;}
// Methods
virtual void ReadColumn(PGLOBAL g);
virtual void WriteColumn(PGLOBAL g);
protected:
BINCOL(void) {} // Default constructor not to be used
// Members
char Fmt; // The column numeric format
}; // end of class BINCOL
#endif // __TABFIX__

1089
storage/connect/tabfmt.cpp Normal file

File diff suppressed because it is too large Load Diff

164
storage/connect/tabfmt.h Normal file
View File

@@ -0,0 +1,164 @@
/*************** TabFmt H Declares Source Code File (.H) ***************/
/* Name: TABFMT.H Version 2.2 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 2001-2012 */
/* */
/* This file contains the CSV and FMT classes declares. */
/***********************************************************************/
#include "xtable.h" // Base class declares
#include "tabdos.h"
//pedef struct _tabdesc *PTABD; // For friend setting
typedef class TDBFMT *PTDBFMT;
/***********************************************************************/
/* CSV table. */
/***********************************************************************/
class DllExport CSVDEF : public DOSDEF { /* Logical table description */
friend class TDBCSV;
//friend class TDBMCV;
public:
// Constructor
CSVDEF(void);
// Implementation
virtual const char *GetType(void) {return "CSV";}
char GetSep(void) {return Sep;}
char GetQot(void) {return Qot;}
// Methods
virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff);
virtual PTDB GetTable(PGLOBAL g, MODE mode);
protected:
// Members
bool Fmtd; /* true for formatted files */
//bool Accept; /* true if wrong lines are accepted */
bool Header; /* true if first line contains headers */
//int Maxerr; /* Maximum number of bad records */
int Quoted; /* Quoting level for quoted fields */
char Sep; /* Separator for standard CSV files */
char Qot; /* Character for quoted strings */
}; // end of CSVDEF
/***********************************************************************/
/* This is the DOS/UNIX Access Method class declaration for files */
/* that are CSV files with columns separated by the Sep character. */
/***********************************************************************/
class TDBCSV : public TDBDOS {
friend class CSVCOL;
public:
// Constructor
TDBCSV(PCSVDEF tdp, PTXF txfp);
TDBCSV(PGLOBAL g, PTDBCSV tdbp);
// Implementation
virtual AMT GetAmType(void) {return TYPE_AM_CSV;}
virtual PTDB Duplicate(PGLOBAL g)
{return (PTDB)new(g) TDBCSV(g, this);}
// Methods
virtual PTDB CopyOne(PTABS t);
//virtual bool IsUsingTemp(PGLOBAL g);
virtual int GetBadLines(void) {return (int)Nerr;}
// Database routines
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
virtual bool OpenDB(PGLOBAL g);
virtual int WriteDB(PGLOBAL g);
virtual int CheckWrite(PGLOBAL g);
virtual int ReadBuffer(PGLOBAL g); // Physical file read
// Specific routines
virtual int EstimatedLength(PGLOBAL g);
virtual bool SkipHeader(PGLOBAL g);
virtual bool CheckErr(void);
protected:
// Members
PSZ *Field; // Field to write to current line
int *Offset; // Column offsets for current record
int *Fldlen; // Column field length for current record
bool *Fldtyp; // true for numeric fields
int Fields; // Number of fields to handle
int Nerr; // Number of bad records
int Maxerr; // Maximum number of bad records
int Quoted; // Quoting level for quoted fields
bool Accept; // true if bad lines are accepted
bool Header; // true if first line contains column headers
char Sep; // Separator
char Qot; // Quoting character
}; // end of class TDBCSV
/***********************************************************************/
/* Class CSVCOL: CSV access method column descriptor. */
/* This A.M. is used for Comma Separated V(?) files. */
/***********************************************************************/
class CSVCOL : public DOSCOL {
friend class TDBCSV;
friend class TDBFMT;
public:
// Constructors
CSVCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i);
CSVCOL(CSVCOL *colp, PTDB tdbp); // Constructor used in copy process
// Implementation
virtual int GetAmType() {return TYPE_AM_CSV;}
// Methods
virtual bool VarSize(void);
virtual void ReadColumn(PGLOBAL g);
virtual void WriteColumn(PGLOBAL g);
// void Print(FILE *, uint);
protected:
// Default constructor not to be used
CSVCOL(void) {}
// Members
int Fldnum; // Field ordinal number (0 based)
}; // end of class CSVCOL
/***********************************************************************/
/* This is the DOS/UNIX Access Method class declaration for files */
/* whose record format is described by a Format keyword. */
/***********************************************************************/
class TDBFMT : public TDBCSV {
friend class CSVCOL;
//friend class FMTCOL;
public:
// Standard constructor
TDBFMT(PCSVDEF tdp, PTXF txfp) : TDBCSV(tdp, txfp)
{FldFormat = NULL; To_Fld = NULL; FmtTest = NULL; Linenum = 0;}
// Copy constructor
TDBFMT(PGLOBAL g, PTDBFMT tdbp);
// Implementation
virtual AMT GetAmType(void) {return TYPE_AM_FMT;}
virtual PTDB Duplicate(PGLOBAL g)
{return (PTDB)new(g) TDBFMT(g, this);}
// Methods
virtual PTDB CopyOne(PTABS t);
// Database routines
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
//virtual int GetMaxSize(PGLOBAL g);
virtual bool OpenDB(PGLOBAL g);
virtual int WriteDB(PGLOBAL g);
//virtual int CheckWrite(PGLOBAL g);
virtual int ReadBuffer(PGLOBAL g); // Physical file read
// Specific routines
virtual int EstimatedLength(PGLOBAL g);
protected:
// Members
PSZ *FldFormat; // Field read format
void *To_Fld; // To field test buffer
int *FmtTest; // Test on ending by %n or %m
int Linenum; // Last read line
}; // end of class TDBFMT
/* ------------------------- End of TabFmt.H ------------------------- */

427
storage/connect/table.cpp Normal file
View File

@@ -0,0 +1,427 @@
/************** Table C++ Functions Source Code File (.CPP) ************/
/* Name: TABLE.CPP Version 2.5 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 1999-2012 */
/* */
/* This file contains the TBX, TDB and OPJOIN classes 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. */
/* xobject.h is header containing XOBJECT derived classes declares. */
/***********************************************************************/
#include "global.h"
#include "plgdbsem.h"
#include "xtable.h"
#include "tabcol.h"
#include "filamtxt.h"
#include "tabdos.h"
//#include "catalog.h"
#include "reldef.h"
int TDB::Tnum = 0;
extern "C" int trace; // The general trace value
/***********************************************************************/
/* Utility routines. */
/***********************************************************************/
void NewPointer(PTABS, void *, void *);
void AddPointer(PTABS, void *);
/* ---------------------------- class TBX ---------------------------- */
/***********************************************************************/
/* TBX public constructors. */
/***********************************************************************/
TBX::TBX(void)
{
Use = USE_NO;
To_Orig = NULL;
To_Filter = NULL;
} // end of TBX constructor
TBX::TBX(PTBX txp)
{
Use = txp->Use;
To_Orig = txp;
To_Filter = NULL;
} // end of TBX copy constructor
// Methods
/* ---------------------------- class TDB ---------------------------- */
/***********************************************************************/
/* TDB public constructors. */
/***********************************************************************/
TDB::TDB(PTABDEF tdp) : Tdb_No(++Tnum)
{
Next = NULL;
Name = (tdp) ? tdp->GetName() : NULL;
To_Table = NULL;
Columns = NULL;
Degree = (tdp) ? tdp->GetDegree() : 0;
Mode = MODE_READ;
} // end of TDB standard constructor
TDB::TDB(PTDB tdbp) : TBX(tdbp), Tdb_No(++Tnum)
{
Next = NULL;
Name = tdbp->Name;
To_Table = tdbp->To_Table;
Columns = NULL;
Degree = tdbp->Degree;
Mode = tdbp->Mode;
} // end of TDB copy constructor
/***********************************************************************/
/* OpenTable: Call AM open routine. */
/***********************************************************************/
bool TDB::OpenTable(PGLOBAL g, PSQL sqlp, MODE mode)
{
if (trace)
htrc("Open Tdb_No=%d use=%d type=%d tdb.Mode=%d mode=%d\n",
Tdb_No, Use, GetAmType(), Mode, mode);
switch (Use) {
case USE_LIN:
/*****************************************************************/
/* If table is read/only, only MODE_READ is allowed. */
/*****************************************************************/
if (IsReadOnly() && mode != MODE_READ) {
strcpy(g->Message, MSG(READ_ONLY));
return true;
} // endif ReadOnly
/*****************************************************************/
/* This could be done in any order. */
/* Note: for not Read only first table in open in that mode. */
/*****************************************************************/
if (Next)
Next->OpenTable(g, sqlp, MODE_READ);
Mode = mode;
/*****************************************************************/
/* Pre-opening is done, allocate select buffers now. */
/*****************************************************************/
Use = USE_READY;
break;
case USE_READY:
/*****************************************************************/
/* This is to open files in reverse order. */
/*****************************************************************/
if (Next)
if (Next->OpenTable(g, sqlp, mode))
return true;
/*****************************************************************/
/* This was moved after filter conversion so filtering can be */
/* done when making index tables for DOS files. */
/* Also it was moved after allocating select buffers so some */
/* data can be pre-read during open to allow storage sorting. */
/*****************************************************************/
if (OpenDB(g)) // Do open the table file
return true;
Use = USE_OPEN;
break;
case USE_OPEN:
/*****************************************************************/
/* Table is already open. */
/* Call open routine that will just "rewind" the files. */
/*****************************************************************/
if (OpenDB(g)) // Rewind the table file
return true;
break;
default:
sprintf(g->Message, MSG(TDB_USE_ERROR), Use);
return true;
} // endswitch Use
return false;
} // end of OpenTable
/***********************************************************************/
/* CloseTable: Close a table of any AM type. */
/***********************************************************************/
void TDB::CloseTable(PGLOBAL g)
{
if (trace)
htrc("CloseTable: tdb_no %d use=%d amtype=%d am.Mode=%d\n",
Tdb_No, Use, GetAmType(), Mode);
CloseDB(g);
Use = USE_READY; // x'7FFD'
Mode = MODE_ANY;
} // end of CloseTable
// Methods
/***********************************************************************/
/* RowNumber: returns the current row ordinal number. */
/***********************************************************************/
int TDB::RowNumber(PGLOBAL g, bool b)
{
sprintf(g->Message, MSG(ROWID_NOT_IMPL), GetAmName(g, GetAmType()));
return 0;
} // end of RowNumber
PTBX TDB::Copy(PTABS t)
{
PTDB tp, tdb1, tdb2 = NULL, outp = NULL;
//PGLOBAL g = t->G; // Is this really useful ???
for (tdb1 = this; tdb1; tdb1 = tdb1->Next) {
tp = tdb1->CopyOne(t);
if (!outp)
outp = tp;
else
tdb2->Next = tp;
tdb2 = tp;
NewPointer(t, tdb1, tdb2);
} // endfor tdb1
return outp;
} // end of Copy
void TDB::Print(PGLOBAL g, FILE *f, uint n)
{
PCOL cp;
char m[64];
memset(m, ' ', n); // Make margin string
m[n] = '\0';
for (PTDB tp = this; tp; tp = tp->Next) {
fprintf(f, "%sTDB (%p) %s no=%d use=%d type=%d\n", m,
tp, tp->Name, tp->Tdb_No, tp->Use, tp->GetAmType());
tp->PrintAM(f, m);
fprintf(f, "%s Columns (deg=%d):\n", m, tp->Degree);
for (cp = tp->Columns; cp; cp = cp->GetNext())
cp->Print(g, f, n);
} /* endfor tp */
} // end of Print
void TDB::Print(PGLOBAL g, char *ps, uint z)
{
sprintf(ps, "R%d.%s", Tdb_No, Name);
} // end of Print
/* -------------------------- class TDBASE --------------------------- */
/***********************************************************************/
/* Implementation of the TDBASE class. This is the base class to all */
/* classes for tables that can be joined together. */
/***********************************************************************/
TDBASE::TDBASE(PTABDEF tdp) : TDB(tdp)
{
To_Def = tdp;
To_Link = NULL;
To_Key_Col = NULL;
To_Kindex = NULL;
To_SetCols = NULL;
MaxSize = -1;
Knum = 0;
Read_Only = (tdp) ? tdp->IsReadOnly() : false;
} // end of TDBASE constructor
TDBASE::TDBASE(PTDBASE tdbp) : TDB(tdbp)
{
To_Def = tdbp->To_Def;
To_SetCols = tdbp->To_SetCols; // ???
MaxSize = tdbp->MaxSize;
Read_Only = tdbp->Read_Only;
} // end of TDBASE copy constructor
/***********************************************************************/
/* Return the pointer on the DB catalog this table belongs to. */
/***********************************************************************/
PCATLG TDBASE::GetCat(void)
{
return (To_Def) ? To_Def->GetCat() : NULL;
} // end of GetCat
/***********************************************************************/
/* Return the datapath of the DB this table belongs to. */
/***********************************************************************/
PSZ TDBASE::GetPath(void)
{
return To_Def->GetPath();
} // end of GetPath
/***********************************************************************/
/* Initialize TDBASE based column description block construction. */
/* name is used to call columns by name. */
/* num is used by TBL to construct columns by index number. */
/* Note: name=Null and num=0 for constructing all columns (select *) */
/***********************************************************************/
PCOL TDBASE::ColDB(PGLOBAL g, PSZ name, int num)
{
int i;
PCOLDEF cdp;
PCOL cp, colp = NULL, cprec = NULL;
if (trace)
htrc("ColDB: am=%d colname=%s tabname=%s num=%d\n",
GetAmType(), SVP(name), Name, num);
for (cdp = To_Def->GetCols(), i = 1; cdp; cdp = cdp->GetNext(), i++)
if ((!name && !num) ||
(name && !stricmp(cdp->GetName(), name)) || num == i) {
/*****************************************************************/
/* Check for existence of desired column. */
/* Also find where to insert the new block. */
/*****************************************************************/
for (cp = Columns; cp; cp = cp->GetNext())
if (cp->GetIndex() < i)
cprec = cp;
else if (cp->GetIndex() == i)
break;
if (trace)
htrc("cdp(%d).Name=%s cp=%p\n", i, cdp->GetName(), cp);
/*****************************************************************/
/* Now take care of Column Description Block. */
/*****************************************************************/
if (cp)
colp = cp;
else
colp = MakeCol(g, cdp, cprec, i);
if (trace)
htrc("colp=%p\n", colp);
if (name || num)
break;
else if (colp)
cprec = colp;
} // endif Name
return (colp);
} // end of ColDB
/***********************************************************************/
/* InsertSpecialColumn: Put a special column ahead of the column list.*/
/***********************************************************************/
PCOL TDBASE::InsertSpecialColumn(PGLOBAL g, PCOL colp)
{
if (!colp->IsSpecial())
return NULL;
colp->SetNext(Columns);
Columns = colp;
return colp;
} // end of InsertSpecialColumn
/***********************************************************************/
/* Make a special COLBLK to insert in a table. */
/***********************************************************************/
PCOL TDBASE::InsertSpcBlk(PGLOBAL g, PCOLUMN cp)
{
char *name = (char*)cp->GetName();
PCOL colp;
if (!strcmp(name, "FILEID")) {
// !strcmp(name, "SERVID")) {
if (!To_Def || !(To_Def->GetPseudo() & 2)) {
sprintf(g->Message, MSG(BAD_SPEC_COLUMN));
return NULL;
} // endif Pseudo
// if (!strcmp(name, "FILEID"))
colp = new(g) FIDBLK(cp);
// else
// colp = new(g) SIDBLK(cp);
} else if (!strcmp(name, "TABID")) {
colp = new(g) TIDBLK(cp);
//} else if (!strcmp(name, "CONID")) {
// colp = new(g) CIDBLK(cp);
} else if (!strcmp(name, "ROWID")) {
colp = new(g) RIDBLK(cp, false);
} else if (!strcmp(name, "ROWNUM")) {
colp = new(g) RIDBLK(cp, true);
} else {
sprintf(g->Message, MSG(BAD_SPECIAL_COL), name);
return NULL;
} // endif's name
if (!(colp = InsertSpecialColumn(g, colp))) {
sprintf(g->Message, MSG(BAD_SPECIAL_COL), name);
return NULL;
} // endif Insert
return (colp);
} // end of InsertSpcBlk
/***********************************************************************/
/* ResetTableOpt: Wrong for this table type. */
/***********************************************************************/
int TDBASE::ResetTableOpt(PGLOBAL g, bool dox)
{
strcpy(g->Message, "This table is not indexable");
return RC_INFO;
} // end of ResetTableOpt
/***********************************************************************/
/* SetKindex: set or reset the index pointer. */
/***********************************************************************/
void TDBASE::SetKindex(PKXBASE kxp)
{
if (To_Kindex)
To_Kindex->Close(); // Discard old index
To_Kindex = kxp;
} // end of SetKindex
/***********************************************************************/
/* SetRecpos: Replace the table at the specified position. */
/***********************************************************************/
bool TDBASE::SetRecpos(PGLOBAL g, int recpos)
{
strcpy(g->Message, MSG(SETRECPOS_NIY));
return true;
} // end of SetRecpos
/***********************************************************************/
/* Methods */
/***********************************************************************/
void TDBASE::PrintAM(FILE *f, char *m)
{
fprintf(f, "%s AM(%d): mode=%d\n", m, GetAmType(), Mode);
} // end of PrintAM
/***********************************************************************/
/* Marks DOS/MAP table columns used in internal joins. */
/* tdb2 is the top of tree or first tdb in chained tdb's and tdbp */
/* points to the currently marked tdb. */
/* Two questions here: exact meaning of U_J_INT ? */
/* Why is the eventual reference to To_Key_Col not marked U_J_EXT ? */
/***********************************************************************/
void TDBASE::MarkDB(PGLOBAL g, PTDB tdb2)
{
if (trace)
htrc("DOS MarkDB: tdbp=%p tdb2=%p\n", this, tdb2);
} // end of MarkDB

458
storage/connect/tabmac.cpp Normal file
View File

@@ -0,0 +1,458 @@
/***********************************************************************/
/* TABMAC: Author Olivier Bertrand -- PlugDB -- 2008-2012 */
/* From the article and sample code by Khalid Shaikh. */
/* TABMAC: virtual table to get the list of MAC addresses. */
/***********************************************************************/
#if defined(WIN32)
#include "my_global.h"
//#include <iphlpapi.h>
#else // !WIN32
#error This is a WIN32 only table type
#endif // !WIN32
#include "global.h"
#include "plgdbsem.h"
//#include "catalog.h"
#include "reldef.h"
#include "xtable.h"
#include "colblk.h"
#include "tabmac.h"
#if 0 // This is placed here just to know what are the actual values
#define MAX_ADAPTER_DESCRIPTION_LENGTH 128
#define MAX_ADAPTER_NAME_LENGTH 256
#define MAX_ADAPTER_ADDRESS_LENGTH 8
#define DEFAULT_MINIMUM_ENTITIES 32
#define MAX_HOSTNAME_LEN 128
#define MAX_DOMAIN_NAME_LEN 128
#define MAX_SCOPE_ID_LEN 256
#define BROADCAST_NODETYPE 1
#define PEER_TO_PEER_NODETYPE 2
#define MIXED_NODETYPE 4
#define HYBRID_NODETYPE 8
#define IP_ADAPTER_DDNS_ENABLED 0x01
#define IP_ADAPTER_REGISTER_ADAPTER_SUFFIX 0x02
#define IP_ADAPTER_DHCP_ENABLED 0x04
#define IP_ADAPTER_RECEIVE_ONLY 0x08
#define IP_ADAPTER_NO_MULTICAST 0x10
#define IP_ADAPTER_IPV6_OTHER_STATEFUL_CONFIG 0x20
#endif // 0
/* -------------- Implementation of the MAC classes ------------------ */
/***********************************************************************/
/* DefineAM: define specific AM block values from MAC file. */
/***********************************************************************/
bool MACDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
{
return false;
} // end of DefineAM
/***********************************************************************/
/* GetTable: makes a new TDB of the proper type. */
/***********************************************************************/
PTDB MACDEF::GetTable(PGLOBAL g, MODE m)
{
return new(g) TDBMAC(this);
} // end of GetTable
/* ------------------------------------------------------------------- */
/***********************************************************************/
/* Implementation of the TDBMAC class. */
/***********************************************************************/
TDBMAC::TDBMAC(PMACDEF tdp) : TDBASE(tdp)
{
FixedInfo = NULL;
Piaf = NULL;
Curp = NULL;
Next = NULL;
Buflen = 0;
Fix = false;
Adap = false;
N = 0;
} // end of TDBMAC constructor
/***********************************************************************/
/* Allocate MAC column description block. */
/***********************************************************************/
PCOL TDBMAC::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
{
PCOL colp;
colp = new(g) MACCOL(cdp, this, n);
if (cprec) {
colp->SetNext(cprec->GetNext());
cprec->SetNext(colp);
} else {
colp->SetNext(Columns);
Columns = colp;
} // endif cprec
return colp;
} // end of MakeCol
/***********************************************************************/
/* MAC: Get the number of found adapters. */
/***********************************************************************/
void TDBMAC::MakeErrorMsg(PGLOBAL g, DWORD drc)
{
if (drc == ERROR_BUFFER_OVERFLOW)
sprintf(g->Message,
"GetAdaptersInfo: Buffer Overflow buflen=%d maxsize=%d",
Buflen, MaxSize);
else if (drc == ERROR_INVALID_PARAMETER)
strcpy(g->Message, "GetAdaptersInfo: Invalid parameters");
else if (drc == ERROR_NO_DATA)
strcpy(g->Message,
"No adapter information exists for the local computer");
else if (drc == ERROR_NOT_SUPPORTED)
strcpy(g->Message, "GetAdaptersInfo is not supported");
else
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(),
0, g->Message, sizeof(g->Message), NULL);
} // end of MakeErrorMsg
/***********************************************************************/
/* GetMacInfo: Get info for all found adapters. */
/***********************************************************************/
bool TDBMAC::GetMacInfo(PGLOBAL g)
{
DWORD drc;
if (GetMaxSize(g) < 0)
return true;
else if (MaxSize == 0)
return false;
Piaf = (PIP_ADAPTER_INFO)PlugSubAlloc(g, NULL, Buflen);
drc = GetAdaptersInfo(Piaf, &Buflen);
if (drc == ERROR_SUCCESS) {
Next = Piaf; // Next is the first one
return false; // Success
} // endif drc
MakeErrorMsg(g, drc);
return true;
} // end of GetMacInfo
/***********************************************************************/
/* GetFixedInfo: Get info for network parameters. */
/***********************************************************************/
bool TDBMAC::GetFixedInfo(PGLOBAL g)
{
ULONG len;
DWORD drc;
FixedInfo = (FIXED_INFO*)PlugSubAlloc(g, NULL, sizeof(FIXED_INFO));
len = sizeof(FIXED_INFO);
drc = GetNetworkParams(FixedInfo, &len);
if (drc == ERROR_BUFFER_OVERFLOW) {
FixedInfo = (FIXED_INFO*)PlugSubAlloc(g, NULL, len);
drc = GetNetworkParams(FixedInfo, &len);
} // endif drc
if (drc != ERROR_SUCCESS) {
sprintf(g->Message, "GetNetworkParams failed. Rc=%08x\n", drc);
return true;
} // endif drc
return false;
} // end of GetFixedInfo
/***********************************************************************/
/* MAC: Get the number of found adapters. */
/***********************************************************************/
int TDBMAC::GetMaxSize(PGLOBAL g)
{
if (Use != USE_OPEN)
// Called from info, Adap and Fix are not set yet
return 1;
if (MaxSize < 0) {
// Best method
if (Adap) {
DWORD drc = GetAdaptersInfo(NULL, &(Buflen = 0));
if (drc == ERROR_SUCCESS)
MaxSize = (Fix) ? 1 : 0;
else if (drc == ERROR_BUFFER_OVERFLOW) {
// sizeof(IP_ADAPTER_INFO) was returning 640 but is now sometimes
// returning 648 while the Buflen setting remains the same (n*640)
// >> Of course, the code above contains a race condition....
// if the size of the structure Windows wants to return grows after
// the first call to GetAdaptersInfo() but before the second call
// to GetAdaptersInfo(), the second call to GetAdaptersInfo() will
// fail with ERROR_BUFFER_OVERFLOW as well, and your function won't
// work (by Jeremy Friesner on stackoverflow.com).
// That's why we add something to it to be comfortable.
MaxSize = (Buflen + 600) / sizeof(IP_ADAPTER_INFO);
// Now Buflen must be updated if 648 is true.
Buflen = MaxSize * sizeof(IP_ADAPTER_INFO);
} else
MakeErrorMsg(g, drc);
} else
MaxSize = (Fix) ? 1 : 0;
#if 0
// This method returns too many adapters
DWORD dw, drc = GetNumberOfInterfaces((PDWORD)&dw);
if (drc == NO_ERROR) {
MaxSize = (int)dw;
Buflen = MaxSize * sizeof(IP_ADAPTER_INFO);
} else
MakeErrorMsg(g, 0);
#endif
} // endif MaxSize
return MaxSize;
} // end of GetMaxSize
/***********************************************************************/
/* MAC Access Method opening routine. */
/***********************************************************************/
bool TDBMAC::OpenDB(PGLOBAL g)
{
if (Use == USE_OPEN) {
/*******************************************************************/
/* Table already open, this should not happen. */
/*******************************************************************/
strcpy(g->Message, "TDBMAC should not be reopened");
return true;
} // endif use
if (Mode != MODE_READ) {
/*******************************************************************/
/* MAC tables cannot be modified. */
/*******************************************************************/
strcpy(g->Message, "MAC tables are read only");
return true;
} else
Use = USE_OPEN;
/*********************************************************************/
/* Get the adapters info. */
/*********************************************************************/
if (Adap && GetMacInfo(g))
return true;
if (Fix && GetFixedInfo(g))
return true;
/*********************************************************************/
/* All is done. */
/*********************************************************************/
return false;
} // end of OpenDB
/***********************************************************************/
/* Data Base read routine for MAC access method. */
/***********************************************************************/
int TDBMAC::ReadDB(PGLOBAL g)
{
Curp = Next;
if (Curp)
Next = Curp->Next;
else if (N || !Fix)
return RC_EF;
N++;
return RC_OK;
} // end of ReadDB
/***********************************************************************/
/* WriteDB: Data Base write routine for MAC access methods. */
/***********************************************************************/
int TDBMAC::WriteDB(PGLOBAL g)
{
strcpy(g->Message, "MAC tables are read only");
return RC_FX;
} // end of WriteDB
/***********************************************************************/
/* Data Base delete line routine for MAC access methods. */
/***********************************************************************/
int TDBMAC::DeleteDB(PGLOBAL g, int irc)
{
strcpy(g->Message, "Delete not enabled for MAC tables");
return RC_FX;
} // end of DeleteDB
// ------------------------ MACCOL functions ----------------------------
/***********************************************************************/
/* MACCOL public constructor. */
/***********************************************************************/
MACCOL::MACCOL(PCOLDEF cdp, PTDB tdbp, int n)
: COLBLK(cdp, tdbp, n)
{
Tdbp = (PTDBMAC)tdbp;
Flag = cdp->GetOffset();
if (Flag < 10)
Tdbp->Fix = true;
else
Tdbp->Adap = true;
} // end of MACCOL constructor
/***********************************************************************/
/* Read the next MAC address elements. */
/***********************************************************************/
void MACCOL::ReadColumn(PGLOBAL g)
{
// Type conversion is handled by Value set routines
char *p = NULL, buf[260] = "";
unsigned int i;
int n = 0;
PIP_ADAPTER_INFO adp = Tdbp->Curp;
FIXED_INFO *fip = Tdbp->FixedInfo;
if (!adp && Flag >= 10) {
// Fix info row, no adapter info available
switch (Flag) {
case 13:
case 14:
case 19:
case 22:
case 23:
n = 0;
break;
default:
p = "";
} // endswitch Flag
} else switch (Flag) {
// FIXED INFO
case 1: // Host Name
p = fip->HostName;
break;
case 2: // Domain Name
p = fip->DomainName;
break;
case 3: // DNS IPaddress
p = (fip->CurrentDnsServer)
? (char*)&fip->CurrentDnsServer->IpAddress
: (char*)&fip->DnsServerList.IpAddress;
break;
case 4: // Node Type
n = (int)fip->NodeType;
break;
case 5: // Scope ID ???
p = fip->ScopeId;
break;
case 6: // Routing enabled
n = (int)fip->EnableRouting;
break;
case 7: // Proxy enabled
n = (int)fip->EnableProxy;
break;
case 8: // DNS enabled
n = (int)fip->EnableDns;
break;
// ADAPTERS INFO
case 10: // Name
p = adp->AdapterName;
break;
case 11: // Description
if ((p = strstr(adp->Description, " - Packet Scheduler Miniport"))) {
strncpy(buf, adp->Description, p - adp->Description);
i = p - adp->Description;
strncpy(buf, adp->Description, i);
buf[i] = 0;
p = buf;
} else if ((p = strstr(adp->Description,
" - Miniport d'ordonnancement de paquets"))) {
i = p - adp->Description;
strncpy(buf, adp->Description, i);
buf[i] = 0;
p = buf;
} else
p = adp->Description;
break;
case 12: // MAC Address
for (p = buf, i = 0; i < adp->AddressLength; i++) {
if (i)
strcat(p++, "-");
p += sprintf(p, "%.2X", adp->Address[i]);
} // endfor i
p = buf;
break;
case 13: // Type
#if 0 // This is not found in the SDK
switch (adp->Type) {
case IF_ETHERNET_ADAPTERTYPE: p = "Ethernet Adapter"; break;
case IF_TOKEN_RING_ADAPTERTYPE: p = "Token Ring Adapter"; break;
case IF_FDDI_ADAPTERTYPE: p = "FDDI Adapter"; break;
case IF_PPP_ADAPTERTYPE: p = "PPP Adapter"; break;
case IF_LOOPBACK_ADAPTERTYPE: p = "Loop Back Adapter"; break;
// case IF_SLIP_ADAPTERTYPE: p = "Generic Slip Adapter"; break;
default:
sprintf(buf, "Other Adapter, type=%d", adp->Type);
p = buf;
} // endswitch Type
#endif // 0
n = (int)adp->Type;
break;
case 14: // DHCP enabled
n = (int)adp->DhcpEnabled;
break;
case 15: // IP Address
p = (adp->CurrentIpAddress)
? (char*)&adp->CurrentIpAddress->IpAddress
: (char*)&adp->IpAddressList.IpAddress;
break;
case 16: // Subnet Mask
p = (adp->CurrentIpAddress)
? (char*)&adp->CurrentIpAddress->IpMask
: (char*)&adp->IpAddressList.IpMask;
break;
case 17: // Gateway
p = (char*)&adp->GatewayList.IpAddress;
break;
case 18: // DHCP Server
p = (char*)&adp->DhcpServer.IpAddress;
break;
case 19: // Have WINS
n = (adp->HaveWins) ? 1 : 0;
break;
case 20: // Primary WINS
p = (char*)&adp->PrimaryWinsServer.IpAddress;
break;
case 21: // Secondary WINS
p = (char*)&adp->SecondaryWinsServer.IpAddress;
break;
case 22: // Lease obtained
n = (int)adp->LeaseObtained;
break;
case 23: // Lease expires
n = (int)adp->LeaseExpires;
break;
default:
if (Buf_Type == TYPE_STRING) {
sprintf(buf, "Invalid flag value %d", Flag);
p = buf;
} else
n = 0;
} // endswitch Flag
if (p)
Value->SetValue_psz(p);
else
Value->SetValue(n);
} // end of ReadColumn

107
storage/connect/tabmac.h Normal file
View File

@@ -0,0 +1,107 @@
// TABMAC.H Olivier Bertrand 2011-2012
// MAC: virtual table to Get Mac Addresses via GetAdaptersInfo
#if defined(WIN32)
#include <windows.h>
#include <iphlpapi.h>
#else // !WIN32
#error This is a WIN32 only table TYPE
#endif // !WIN32
/***********************************************************************/
/* Definitions. */
/***********************************************************************/
typedef class MACDEF *PMACDEF;
typedef class TDBMAC *PTDBMAC;
typedef class MACCOL *PMACCOL;
/* -------------------------- MAC classes ---------------------------- */
/***********************************************************************/
/* MAC: virtual table to get the list of MAC addresses. */
/***********************************************************************/
class DllExport MACDEF : public TABDEF { /* Logical table description */
friend class TDBMAC;
public:
// Constructor
MACDEF(void) {Pseudo = 3;}
// Implementation
virtual const char *GetType(void) {return "MAC";}
// Methods
virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff);
virtual PTDB GetTable(PGLOBAL g, MODE m);
virtual bool DeleteTableFile(PGLOBAL g) {return true;}
protected:
// Members
}; // end of MACDEF
/***********************************************************************/
/* This is the class declaration for the MAC table. */
/***********************************************************************/
class TDBMAC : public TDBASE {
friend class MACCOL;
public:
// Constructor
TDBMAC(PMACDEF tdp);
//TDBMAC(PGLOBAL g, PTDBMAC tdbp);
// Implementation
virtual AMT GetAmType(void) {return TYPE_AM_MAC;}
//virtual PTDB Duplicate(PGLOBAL g) {return (PTDB)new(g) TDBMAC(g, this);}
// Methods
//virtual PTDB CopyOne(PTABS t);
virtual int GetRecpos(void) {return N;}
virtual int RowNumber(PGLOBAL g, bool b = false) {return N;}
// Database routines
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
virtual int GetMaxSize(PGLOBAL g);
virtual bool OpenDB(PGLOBAL g);
virtual int ReadDB(PGLOBAL g);
virtual int WriteDB(PGLOBAL g);
virtual int DeleteDB(PGLOBAL g, int irc);
virtual void CloseDB(PGLOBAL g) {}
protected:
// Specific routines
bool GetMacInfo(PGLOBAL g);
bool GetFixedInfo(PGLOBAL g);
void MakeErrorMsg(PGLOBAL g, DWORD drc);
// Members
FIXED_INFO *FixedInfo; // Points to fixed info structure
PIP_ADAPTER_INFO Piaf; // Points on Adapter info array
PIP_ADAPTER_INFO Curp; // Points on current Adapt info
PIP_ADAPTER_INFO Next; // Points on next Adapt info
ULONG Buflen; // Buffer length
bool Fix; // true if FixedInfo is needed
bool Adap; // true if Piaf is needed
int N; // Row number
}; // end of class TDBMAC
/***********************************************************************/
/* Class MACCOL: MAC Address column. */
/***********************************************************************/
class MACCOL : public COLBLK {
friend class TDBMAC;
public:
// Constructors
MACCOL(PCOLDEF cdp, PTDB tdbp, int n);
//MACCOL(MACCOL *colp, PTDB tdbp); // Constructor used in copy process
// Implementation
virtual int GetAmType(void) {return TYPE_AM_MAC;}
// Methods
virtual void ReadColumn(PGLOBAL g);
protected:
MACCOL(void) {} // Default constructor not to be used
// Members
PTDBMAC Tdbp; // Points to MAC table block
int Flag; // Indicates what to display
}; // end of class MACCOL

1480
storage/connect/tabmul.cpp Normal file

File diff suppressed because it is too large Load Diff

220
storage/connect/tabmul.h Normal file
View File

@@ -0,0 +1,220 @@
/*************** Tabmul H Declares Source Code File (.H) ***************/
/* Name: TABMUL.H Version 1.4 */
/* */
/* (C) Copyright to PlugDB Software Development 2003-2012 */
/* Author: Olivier BERTRAND */
/* */
/* This file contains the TDBMUL and TDBDIR classes declares. */
/***********************************************************************/
#if defined(WIN32)
#include <io.h>
#else // !WIN32
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <dirent.h>
#endif // !WIN32
//#include "osutil.h"
#include "block.h"
typedef class TDBMUL *PTDBMUL;
typedef class TDBSDR *PTDBSDR;
/***********************************************************************/
/* This is the MUL Access Method class declaration for files that are */
/* physically split in multiple files having the same format. */
/***********************************************************************/
class DllExport TDBMUL : public TDBASE {
//friend class MULCOL;
public:
// Constructor
TDBMUL(PTDBASE tdbp);
TDBMUL(PTDBMUL tdbp);
// Implementation
virtual AMT GetAmType(void) {return Tdbp->GetAmType();}
virtual PTDB Duplicate(PGLOBAL g);
// Methods
virtual void ResetDB(void);
virtual PTDB CopyOne(PTABS t);
virtual bool IsSame(PTBX tp) {return tp == (PTBX)Tdbp;}
virtual PSZ GetFile(PGLOBAL g) {return Tdbp->GetFile(g);}
virtual int GetRecpos(void) {return 0;}
virtual PCOL ColDB(PGLOBAL g, PSZ name, int num);
bool InitFileNames(PGLOBAL g);
// Database routines
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
{strcpy(g->Message, MSG(MUL_MAKECOL_ERR)); return NULL;}
virtual int Cardinality(PGLOBAL g);
virtual int GetMaxSize(PGLOBAL g);
virtual int GetProgMax(PGLOBAL g);
virtual int GetProgCur(void);
virtual int RowNumber(PGLOBAL g, bool b = false);
virtual bool OpenDB(PGLOBAL g);
virtual int ReadDB(PGLOBAL g);
virtual int WriteDB(PGLOBAL g);
virtual int DeleteDB(PGLOBAL g, int irc);
virtual void CloseDB(PGLOBAL g);
protected:
// Members
TDBASE *Tdbp; // Points to a (file) table class
char* *Filenames; // Points to file names
int Rows; // Total rows of already read files
int Mul; // Type of multiple file list
int NumFiles; // Number of physical files
int iFile; // Index of currently processed file
}; // end of class TDBMUL
/***********************************************************************/
/* Directory listing table. */
/***********************************************************************/
class DllExport DIRDEF : public TABDEF { /* Directory listing table */
friend class CATALOG;
friend class TDBDIR;
public:
// Constructor
DIRDEF(void) {Fn = NULL; Incl = false; Huge = false;}
// Implementation
virtual const char *GetType(void) {return "DIR";}
// Methods
virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff);
virtual PTDB GetTable(PGLOBAL g, MODE m);
protected:
// Members
PSZ Fn; /* Path/Name of file search */
bool Incl; /* true to include sub-directories */
bool Huge; /* true if files can be larger than 2GB */
}; // end of DIRDEF
/***********************************************************************/
/* This is the DIR Access Method class declaration for tables that */
/* represent a directory listing. The pathname is given at the create */
/* time and can contain wildcard characters in the file name, and the */
/* (virtual) table is populated when it is in use. */
/***********************************************************************/
class TDBDIR : public TDBASE {
friend class DIRCOL;
public:
// Constructor
TDBDIR(PDIRDEF tdp);
TDBDIR(PTDBDIR tdbp);
// Implementation
virtual AMT GetAmType(void) {return TYPE_AM_DIR;}
virtual PTDB Duplicate(PGLOBAL g)
{return (PTDB)new(g) TDBDIR(this);}
// Methods
virtual PTDB CopyOne(PTABS t);
virtual int GetRecpos(void) {return iFile;}
// Database routines
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
virtual int GetMaxSize(PGLOBAL g);
virtual int GetProgMax(PGLOBAL g) {return GetMaxSize(g);}
virtual int GetProgCur(void) {return iFile;}
virtual bool OpenDB(PGLOBAL g);
virtual int ReadDB(PGLOBAL g);
virtual int WriteDB(PGLOBAL g);
virtual int DeleteDB(PGLOBAL g, int irc);
virtual void CloseDB(PGLOBAL g);
protected:
char *Path(PGLOBAL g);
// Members
PSZ To_File; // Points to file search pathname
int iFile; // Index of currently retrieved file
#if defined(WIN32)
_finddata_t FileData; // Find data structure
int Hsearch; // Search handle
char Drive[_MAX_DRIVE]; // Drive name
#else // !WIN32
struct stat Fileinfo; // File info structure
struct dirent *Entry; // Point to directory entry structure
DIR *Dir; // To searched directory structure
bool Done; // true when _splipath is done
char Pattern[_MAX_FNAME+_MAX_EXT];
#endif // !WIN32
char Fpath[_MAX_PATH]; // Absolute file search pattern
char Direc[_MAX_DIR]; // Search path
char Fname[_MAX_FNAME]; // File name
char Ftype[_MAX_EXT]; // File extention
}; // end of class TDBDIR
/***********************************************************************/
/* This is the DIR Access Method class declaration for tables that */
/* represent a directory listing. The pathname is given at the create */
/* time and can contain wildcard characters in the file name, and the */
/* (virtual) table is populated when it is in use. In addition, this */
/* class also includes files of included sub-directories. */
/***********************************************************************/
class TDBSDR : public TDBDIR {
friend class DIRCOL;
public:
// Constructors
TDBSDR(PDIRDEF tdp) : TDBDIR(tdp) {Sub = NULL;}
TDBSDR(PTDBSDR tdbp);
// Implementation
virtual PTDB Duplicate(PGLOBAL g)
{return (PTDB)new(g) TDBSDR(this);}
// Methods
virtual PTDB CopyOne(PTABS t);
// Database routines
virtual int GetMaxSize(PGLOBAL g);
virtual int GetProgMax(PGLOBAL g) {return GetMaxSize(g);}
virtual bool OpenDB(PGLOBAL g);
virtual int ReadDB(PGLOBAL g);
//virtual void CloseDB(PGLOBAL g);
protected:
int FindInDir(PGLOBAL g);
typedef struct _Sub_Dir {
struct _Sub_Dir *Next;
struct _Sub_Dir *Prev;
#if defined(WIN32)
int H; // Search handle
#else // !WIN32
DIR *D;
#endif // !WIN32
size_t Len; // Initial directory name length
} SUBDIR, *PSUBDIR;
// Members
PSUBDIR Sub; // To current Subdir block
}; // end of class TDBSDR
/***********************************************************************/
/* Class DIRCOL: DIR access method column descriptor. */
/* This A.M. is used for tables populated by DIR file name list. */
/***********************************************************************/
class DIRCOL : public COLBLK {
public:
// Constructors
DIRCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am = "DIR");
DIRCOL(DIRCOL *colp, PTDB tdbp); // Constructor used in copy process
// Implementation
virtual int GetAmType(void) {return TYPE_AM_DIR;}
// Methods
virtual void ReadColumn(PGLOBAL g);
protected:
// Default constructor not to be used
DIRCOL(void) {}
// Members
int N; // Column number
}; // end of class DIRCOL

1096
storage/connect/tabmysql.cpp Normal file

File diff suppressed because it is too large Load Diff

139
storage/connect/tabmysql.h Normal file
View File

@@ -0,0 +1,139 @@
// TDBMYSQL.H Olivier Bertrand 2007-2012
#include "myconn.h" // MySQL connection declares
typedef class MYSQLDEF *PMYDEF;
typedef class TDBMYSQL *PTDBMY;
typedef class MYSQLC *PMYC;
typedef class MYSQLCOL *PMYCOL;
/* ------------------------- MYSQL classes --------------------------- */
/***********************************************************************/
/* MYSQL: table type that are MySQL tables. */
/* Using embedded MySQL library (or optionally calling a MySQL server)*/
/***********************************************************************/
/***********************************************************************/
/* MYSQL table. */
/***********************************************************************/
class MYSQLDEF : public TABDEF {/* Logical table description */
friend class TDBMYSQL;
public:
// Constructor
MYSQLDEF(void);
// Implementation
virtual const char *GetType(void) {return "MYSQL";}
inline PSZ GetHostname(void) {return Hostname;};
inline PSZ GetDatabase(void) {return Database;};
inline PSZ GetTabname(void) {return Tabname;}
inline PSZ GetUsername(void) {return Username;};
inline PSZ GetPassword(void) {return Password;};
inline int GetPortnumber(void) {return Portnumber;}
// Methods
virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff);
virtual PTDB GetTable(PGLOBAL g, MODE m);
protected:
// Members
PSZ Hostname; /* Host machine to use */
PSZ Database; /* Database to be used by server */
PSZ Tabname; /* External table name */
PSZ Username; /* User logon name */
PSZ Password; /* Password logon info */
int Portnumber; /* MySQL port number (0 = default) */
bool Bind; /* Use prepared statement on insert */
bool Delayed; /* Delayed insert */
}; // end of MYSQLDEF
/***********************************************************************/
/* This is the class declaration for the MYSQL table. */
/***********************************************************************/
class TDBMYSQL : public TDBASE {
friend class MYSQLCOL;
public:
// Constructor
TDBMYSQL(PMYDEF tdp);
TDBMYSQL(PGLOBAL g, PTDBMY tdbp);
// Implementation
virtual AMT GetAmType(void) {return TYPE_AM_MYSQL;}
virtual PTDB Duplicate(PGLOBAL g) {return (PTDB)new(g) TDBMYSQL(g, this);}
// Methods
virtual PTDB CopyOne(PTABS t);
virtual int GetAffectedRows(void) {return AftRows;}
virtual int GetRecpos(void) {return N;}
virtual int GetProgMax(PGLOBAL g);
virtual void ResetDB(void) {N = 0;}
virtual int RowNumber(PGLOBAL g, bool b = FALSE);
// Database routines
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
virtual int GetMaxSize(PGLOBAL g);
virtual bool OpenDB(PGLOBAL g);
virtual int ReadDB(PGLOBAL g);
virtual int WriteDB(PGLOBAL g);
virtual int DeleteDB(PGLOBAL g, int irc);
virtual void CloseDB(PGLOBAL g);
protected:
// Internal functions
bool MakeSelect(PGLOBAL g);
bool MakeInsert(PGLOBAL g);
//bool MakeUpdate(PGLOBAL g);
//bool MakeDelete(PGLOBAL g);
int BindColumns(PGLOBAL g);
// Members
MYSQLC Myc; // MySQL connection class
MYSQL_BIND *Bind; // To the MySQL bind structure array
char *Host; // Host machine to use
char *User; // User logon info
char *Pwd; // Password logon info
char *Database; // Database to be used by server
char *Tabname; // External table name
char *Query; // Points to SQL query
char *Qbuf; // Used for not prepared insert
bool Fetched; // True when fetch was done
bool Prep; // Use prepared statement on insert
bool Delayed; // Use delayed insert
int m_Rc; // Return code from command
int AftRows; // The number of affected rows
int N; // The current table index
int Port; // MySQL port number (0 = default)
int Nparm; // The number of statement parameters
}; // end of class TDBMYSQL
/***********************************************************************/
/* Class MYSQLCOL: MySQL table column. */
/***********************************************************************/
class MYSQLCOL : public COLBLK {
friend class TDBMYSQL;
public:
// Constructors
MYSQLCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am = "MYSQL");
MYSQLCOL(MYSQLCOL *colp, PTDB tdbp); // Constructor used in copy process
// Implementation
virtual int GetAmType(void) {return TYPE_AM_MYSQL;}
void InitBind(PGLOBAL g);
// Methods
virtual bool SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check);
virtual void ReadColumn(PGLOBAL g);
virtual void WriteColumn(PGLOBAL g);
protected:
// Default constructor not to be used
MYSQLCOL(void) {}
// Members
MYSQL_BIND *Bind; // This column bind structure pointer
PVAL To_Val; // To value used for Update/Insert
unsigned long Slen; // Bind string lengh
int Rank; // Rank (position) number in the query
}; // end of class MYSQLCOL

893
storage/connect/tabodbc.cpp Normal file
View File

@@ -0,0 +1,893 @@
/************* Tabodbc C++ Program Source Code File (.CPP) *************/
/* PROGRAM NAME: TABODBC */
/* ------------- */
/* Version 2.3 */
/* */
/* COPYRIGHT: */
/* ---------- */
/* (C) Copyright to the author Olivier BERTRAND 2000-2012 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
/* This program are the TABODBC class DB execution routines. */
/* */
/* WHAT YOU NEED TO COMPILE THIS PROGRAM: */
/* -------------------------------------- */
/* */
/* REQUIRED FILES: */
/* --------------- */
/* TABODBC.CPP - Source code */
/* PLGDBSEM.H - DB application declaration file */
/* TABODBC.H - TABODBC classes declaration file */
/* GLOBAL.H - Global declaration file */
/* */
/* REQUIRED LIBRARIES: */
/* ------------------- */
/* Large model C library */
/* */
/* REQUIRED PROGRAMS: */
/* ------------------ */
/* IBM, Borland, GNU or Microsoft C++ Compiler and Linker */
/* */
/***********************************************************************/
/***********************************************************************/
/* Include relevant MariaDB header file. */
/***********************************************************************/
#include "my_global.h"
#if defined(WIN32)
#include <io.h>
#include <fcntl.h>
#if defined(__BORLANDC__)
#define __MFC_COMPAT__ // To define min/max as macro
#endif
//#include <windows.h>
#include <sqltypes.h>
#else
#if defined(UNIX)
#include <errno.h>
#include "osutil.h"
#else
#include <io.h>
#endif
#include <fcntl.h>
#define NODW
#endif
/***********************************************************************/
/* Include application header files: */
/* global.h is header containing all global declarations. */
/* plgdbsem.h is header containing the DB application declarations. */
/* kindex.h is kindex header that also includes tabdos.h. */
/* tabodbc.h is header containing the TABODBC class declarations. */
/* odbconn.h is header containing ODBC connection declarations. */
/***********************************************************************/
#include "global.h"
#include "plgdbsem.h"
//#include "sqry.h"
#include "xtable.h"
#include "tabodbc.h"
#include "tabmul.h"
#include "reldef.h"
#include "tabcol.h"
#include "valblk.h"
/***********************************************************************/
/* DB static variables. */
/***********************************************************************/
// int num_read, num_there, num_eq[2], num_nf; // Statistics
extern int num_read, num_there, num_eq[2]; // Statistics
/* -------------------------- Class ODBCDEF -------------------------- */
/***********************************************************************/
/* DefineAM: define specific AM block values from XDB file. */
/***********************************************************************/
bool ODBCDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
{
//void *memp = Cat->GetDescp();
//PSZ dbfile = Cat->GetDescFile();
int dop = ODBConn::noOdbcDialog; // Default for options
Desc = Connect = Cat->GetStringCatInfo(g, Name, "Connect", "");
Tabname = Cat->GetStringCatInfo(g, Name, "Name", Name); // Deprecated
Tabname = Cat->GetStringCatInfo(g, Name, "Tabname", Tabname);
Tabowner = Cat->GetStringCatInfo(g, Name, "Owner", "");
Tabqual = Cat->GetStringCatInfo(g, Name, "Qualifier", "");
Qchar = Cat->GetStringCatInfo(g, Name, "Qchar", "");
Catver = Cat->GetIntCatInfo(Name, "Catver", 2);
Options = Cat->GetIntCatInfo(Name, "Options", dop);
//Options = Cat->GetIntCatInfo(Name, "Options", 0);
Pseudo = 2; // FILID is Ok but not ROWID
return false;
} // end of DefineAM
/***********************************************************************/
/* GetTable: makes a new Table Description Block. */
/***********************************************************************/
PTDB ODBCDEF::GetTable(PGLOBAL g, MODE m)
{
PTDBASE tdbp = NULL;
/*********************************************************************/
/* Allocate a TDB of the proper type. */
/* Column blocks will be allocated only when needed. */
/*********************************************************************/
tdbp = new(g) TDBODBC(this);
if (Multiple == 1)
tdbp = new(g) TDBMUL(tdbp);
else if (Multiple == 2)
strcpy(g->Message, MSG(NO_ODBC_MUL));
return tdbp;
} // end of GetTable
/* -------------------------- Class TDBODBC -------------------------- */
/***********************************************************************/
/* Implementation of the TDBODBC class. */
/***********************************************************************/
TDBODBC::TDBODBC(PODEF tdp) : TDBASE(tdp)
{
Ocp = NULL;
Cnp = NULL;
if (tdp) {
Connect = tdp->GetConnect();
TableName = tdp->GetTabname();
Owner = tdp->GetTabowner();
Qualifier = tdp->GetTabqual();
Quote = tdp->GetQchar();
Options = tdp->GetOptions();
Rows = tdp->GetElemt();
Catver = tdp->GetCatver();
} else {
Connect = NULL;
TableName = NULL;
Owner = NULL;
Qualifier = NULL;
Quote = NULL;
Options = 0;
Rows = 0;
Catver = 0;
} // endif tdp
Query = NULL;
Count = NULL;
//Where = NULL;
MulConn = NULL;
DBQ = NULL;
Fpos = 0;
AftRows = 0;
CurNum = 0;
Rbuf = 0;
BufSize = 0;
Nparm = 0;
} // end of TDBODBC standard constructor
TDBODBC::TDBODBC(PTDBODBC tdbp) : TDBASE(tdbp)
{
Ocp = tdbp->Ocp; // is that right ?
Cnp = tdbp->Cnp;
Connect = tdbp->Connect;
TableName = tdbp->TableName;
Owner = tdbp->Owner;
Qualifier = tdbp->Qualifier;
Quote = tdbp->Quote;
Query = tdbp->Query;
Count = tdbp->Count;
//Where = tdbp->Where;
MulConn = tdbp->MulConn;
DBQ = tdbp->DBQ;
Options = tdbp->Options;
Rows = tdbp->Rows;
Fpos = tdbp->Fpos;
AftRows = tdbp->AftRows;
//Tpos = tdbp->Tpos;
//Spos = tdbp->Spos;
CurNum = tdbp->CurNum;
Rbuf = tdbp->Rbuf;
BufSize = tdbp->BufSize;
Nparm = tdbp->Nparm;
} // end of TDBODBC copy constructor
// Method
PTDB TDBODBC::CopyOne(PTABS t)
{
PTDB tp;
PODBCCOL cp1, cp2;
PGLOBAL g = t->G; // Is this really useful ???
tp = new(g) TDBODBC(this);
for (cp1 = (PODBCCOL)Columns; cp1; cp1 = (PODBCCOL)cp1->GetNext()) {
cp2 = new(g) ODBCCOL(cp1, tp); // Make a copy
NewPointer(t, cp1, cp2);
} // endfor cp1
return tp;
} // end of CopyOne
/***********************************************************************/
/* Allocate ODBC column description block. */
/***********************************************************************/
PCOL TDBODBC::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
{
return new(g) ODBCCOL(cdp, this, cprec, n);
} // end of MakeCol
/***********************************************************************/
/* Extract the filename from connect string and return it. */
/* This used for Multiple(1) tables. Also prepare a connect string */
/* with a place holder to be used by SetFile. */
/***********************************************************************/
PSZ TDBODBC::GetFile(PGLOBAL g)
{
if (Connect) {
char *p1, *p2;
size_t n;
if ((p1 = strstr(Connect, "DBQ="))) {
p1 += 4; // Beginning of file name
p2 = strchr(p1, ';'); // End of file path/name
// Make the File path/name from the connect string
n = (p2) ? p2 - p1 : strlen(p1);
DBQ = (PSZ)PlugSubAlloc(g, NULL, n + 1);
memcpy(DBQ, p1, n);
DBQ[n] = '\0';
// Make the Format used to re-generate Connect (3 = "%s" + 1)
MulConn = (char*)PlugSubAlloc(g, NULL, strlen(Connect) - n + 3);
memcpy(MulConn, Connect, p1 - Connect);
MulConn[p1 - Connect] = '\0';
strcat(strcat(MulConn, "%s"), (p2) ? p2 : ";");
} // endif p1
} // endif Connect
return (DBQ) ? DBQ : (PSZ)"???";
} // end of GetFile
/***********************************************************************/
/* Set DBQ and get the new file name into the connect string. */
/***********************************************************************/
void TDBODBC::SetFile(PGLOBAL g, PSZ fn)
{
if (MulConn) {
int n = strlen(MulConn) + strlen(fn) - 1;
if (n > BufSize) {
// Allocate a buffer larger than needed so the chance
// of having to reallocate it is reduced.
BufSize = n + 6;
Connect = (char*)PlugSubAlloc(g, NULL, BufSize);
} // endif n
// Make the complete connect string
sprintf(Connect, MulConn, fn);
} // endif MultConn
DBQ = fn;
} // end of SetFile
#if !defined(NO_ICONV)
/******************************************************************/
/* Convert an UTF-8 string to latin characters. */
/******************************************************************/
int TDBODBC::Decode(iconv_t cd, char *utf, char *buf, size_t n)
{
#if defined(WIN32) || defined(AIX)
const char *inp = (const char *)utf;
#else
char *inp = (char *)utf;
#endif
char *outp = buf;
size_t i = strlen(inp), o = n;
int rc = iconv(cd, &inp, &i, &outp, &o);
buf[n - o] = '\0';
return rc;
} // end of Decode
#endif // !NO_ICONV
/***********************************************************************/
/* MakeSQL: make the SQL statement use with ODBC connection. */
/* Note: when implementing EOM filtering, column only used in local */
/* filter should be removed from column list. */
/***********************************************************************/
char *TDBODBC::MakeSQL(PGLOBAL g, bool cnt)
{
char *colist, *tabname, *sql, buf[64];
LPCSTR ownp = NULL, qualp = NULL;
int rc, len, ncol = 0;
bool first = true;
PTABLE tablep = To_Table;
PCOL colp;
#if !defined(NO_ICONV)
iconv_t cd = iconv_open("ISO-8859-1", "UTF-8");
#else
void *cd = NULL;
#endif // !NO_ICONV
if (!cnt) {
// Normal SQL statement to retrieve results
for (colp = Columns; colp; colp = colp->GetNext())
if (!colp->IsSpecial())
ncol++;
if (ncol) {
colist = (char*)PlugSubAlloc(g, NULL, (NAM_LEN + 4) * ncol);
for (colp = Columns; colp; colp = colp->GetNext())
if (!colp->IsSpecial()) {
// Column name can be in UTF-8 encoding
rc = Decode(cd, colp->GetName(), buf, sizeof(buf));
if (Quote) {
if (first) {
strcat(strcat(strcpy(colist, Quote), buf), Quote);
first = false;
} else
strcat(strcat(strcat(strcat(colist, ", "),
Quote), buf), Quote);
} else {
if (first) {
strcpy(colist, buf);
first = false;
} else
strcat(strcat(colist, ", "), buf);
} // endif Quote
} // endif !Special
} else {
// ncol == 0 can occur for queries such that sql count(*) from...
// for which we will count the rows from sql * from...
colist = (char*)PlugSubAlloc(g, NULL, 2);
strcpy(colist, "*");
} // endif ncol
} else {
// SQL statement used to retrieve the size of the result
colist = (char*)PlugSubAlloc(g, NULL, 9);
strcpy(colist, "count(*)");
} // endif cnt
// Table name can be encoded in UTF-8
rc = Decode(cd, TableName, buf, sizeof(buf));
// Put table name between identifier quotes in case in contains blanks
tabname = (char*)PlugSubAlloc(g, NULL, strlen(buf) + 3);
if (Quote)
strcat(strcat(strcpy(tabname, Quote), buf), Quote);
else
strcpy(tabname, buf);
// Below 14 is length of 'select ' + length of ' from ' + 1
len = (strlen(colist) + strlen(buf) + 14);
len += (To_Filter ? strlen(To_Filter) + 7 : 0);
// if (tablep->GetQualifier()) This is used when using a table
// qualp = tablep->GetQualifier(); from anotherPlugDB database but
// else makes no sense for ODBC.
if (Qualifier && *Qualifier)
qualp = Qualifier;
if (qualp)
len += (strlen(qualp) + 2);
if (tablep->GetCreator())
ownp = tablep->GetCreator();
else if (Owner && *Owner)
ownp = Owner;
if (ownp)
len += (strlen(ownp) + 1);
sql = (char*)PlugSubAlloc(g, NULL, len);
strcat(strcat(strcpy(sql, "SELECT "), colist), " FROM ");
if (qualp) {
strcat(sql, qualp);
if (ownp)
strcat(strcat(sql, "."), ownp);
else
strcat(sql, ".");
strcat(sql, ".");
} else if (ownp)
strcat(strcat(sql, ownp), ".");
strcat(sql, tabname);
#if !defined(NO_ICONV)
iconv_close(cd);
#endif // !NO_ICONV
if (To_Filter)
strcat(strcat(sql, " WHERE "), To_Filter);
return sql;
} // end of MakeSQL
/***********************************************************************/
/* ResetSize: call by TDBMUL when calculating size estimate. */
/***********************************************************************/
void TDBODBC::ResetSize(void)
{
MaxSize = -1;
if (Ocp && Ocp->IsOpen())
Ocp->Close();
} // end of ResetSize
/***********************************************************************/
/* ODBC GetMaxSize: returns table size estimate in number of lines. */
/***********************************************************************/
int TDBODBC::GetMaxSize(PGLOBAL g)
{
if (MaxSize < 0) {
if (!Ocp)
Ocp = new(g) ODBConn(g, this);
if (!Ocp->IsOpen())
if (Ocp->Open(Connect, Options) < 1)
return -1;
if (!Count && !(Count = MakeSQL(g, true)))
return -2;
if (!Cnp) {
// Allocate a Count(*) column (must not use the default constructor)
Cnp = new(g) ODBCCOL;
Cnp->InitValue(g);
} // endif Cnp
if ((MaxSize = Ocp->GetResultSize(Count, Cnp)) < 0)
return -3;
} // endif MaxSize
return MaxSize;
} // end of GetMaxSize
/***********************************************************************/
/* Return 0 in mode DELETE or UPDATE to tell that it is done. */
/***********************************************************************/
int TDBODBC::GetProgMax(PGLOBAL g)
{
return (Mode == MODE_DELETE || Mode == MODE_UPDATE) ? 0
: GetMaxSize(g);
} // end of GetProgMax
/***********************************************************************/
/* ODBC Access Method opening routine. */
/* New method now that this routine is called recursively (last table */
/* first in reverse order): index blocks are immediately linked to */
/* join block of next table if it exists or else are discarted. */
/***********************************************************************/
bool TDBODBC::OpenDB(PGLOBAL g)
{
bool rc = false;
if (g->Trace)
htrc("ODBC OpenDB: tdbp=%p tdb=R%d use=%dmode=%d\n",
this, Tdb_No, Use, Mode);
if (Use == USE_OPEN) {
/*******************************************************************/
/* Table already open, just replace it at its beginning. */
/*******************************************************************/
// if (To_Kindex)
/*****************************************************************/
/* Table is to be accessed through a sorted index table. */
/*****************************************************************/
// To_Kindex->Reset();
// rewind(Stream); >>>>>>> Something to be done with Cursor <<<<<<<
return false;
} // endif use
/*********************************************************************/
/* Open an ODBC connection for this table. */
/* Note: this may not be the proper way to do. Perhaps it is better */
/* to test whether a connection is already open for this datasource */
/* and if so to allocate just a new result set. But this only for */
/* drivers allowing concurency in getting results ??? */
/*********************************************************************/
if (!Ocp)
Ocp = new(g) ODBConn(g, this);
else if (Ocp->IsOpen())
Ocp->Close();
if (Ocp->Open(Connect, Options) < 1)
return true;
Use = USE_OPEN; // Do it now in case we are recursively called
/*********************************************************************/
/* Allocate whatever is used for getting results. */
/*********************************************************************/
if (Mode == MODE_READ) {
/*******************************************************************/
/* The issue here is that if max result size is needed, it must be */
/* calculated before the result set for the final data retrieval is*/
/* allocated and the final statement prepared so we call GetMaxSize*/
/* here. It can be a waste of time if the max size is not needed */
/* but currently we always are asking for it (for progress info). */
/*******************************************************************/
GetMaxSize(g); // Will be set for next call
if (!Query)
if ((Query = MakeSQL(g, false))) {
for (PODBCCOL colp = (PODBCCOL)Columns;
colp; colp = (PODBCCOL)colp->GetNext())
if (!colp->IsSpecial())
colp->AllocateBuffers(g, Rows);
} else
rc = true;
if (!rc)
rc = ((Rows = Ocp->ExecDirectSQL(Query, (PODBCCOL)Columns)) < 0);
} else {
strcpy(g->Message, "ODBC tables are read only in this version");
return true;
} // endelse
if (rc) {
Ocp->Close();
return true;
} // endif rc
/*********************************************************************/
/* Reset statistics values. */
/*********************************************************************/
num_read = num_there = num_eq[0] = num_eq[1] = 0;
return false;
} // end of OpenDB
/***********************************************************************/
/* GetRecpos: return the position of last read record. */
/***********************************************************************/
int TDBODBC::GetRecpos(void)
{
return Fpos; // To be really implemented
} // end of GetRecpos
/***********************************************************************/
/* VRDNDOS: Data Base read routine for odbc access method. */
/***********************************************************************/
int TDBODBC::ReadDB(PGLOBAL g)
{
int rc;
#ifdef DEBTRACE
htrc("ODBC ReadDB: R%d Mode=%d key=%p link=%p Kindex=%p\n",
GetTdb_No(), Mode, To_Key_Col, To_Link, To_Kindex);
#endif
if (To_Kindex) {
// Direct access of ODBC tables is not implemented yet
strcpy(g->Message, MSG(NO_ODBC_DIRECT));
longjmp(g->jumper[g->jump_level], GetAmType());
#if 0
/*******************************************************************/
/* Reading is by an index table. */
/*******************************************************************/
int recpos = To_Kindex->Fetch(g);
switch (recpos) {
case -1: // End of file reached
return RC_EF;
case -2: // No match for join
return RC_NF;
case -3: // Same record as current one
num_there++;
return RC_OK;
default:
/***************************************************************/
/* Set the cursor position according to record to read. */
/***************************************************************/
//--------------------------------- TODO --------------------------------
break;
} // endswitch recpos
#endif // 0
} // endif To_Kindex
/*********************************************************************/
/* Now start the reading process. */
/* Here is the place to fetch the line(s). */
/*********************************************************************/
if (++CurNum >= Rbuf) {
Rbuf = Ocp->Fetch();
CurNum = 0;
} // endif CurNum
rc = (Rbuf > 0) ? RC_OK : (Rbuf == 0) ? RC_EF : RC_FX;
Fpos++; // Used for progress info
#ifdef DEBTRACE
htrc(" Read: Rbuf=%d rc=%d\n", Rbuf, rc);
#endif
return rc;
} // end of ReadDB
/***********************************************************************/
/* Data Base Insert write routine for ODBC access method. */
/***********************************************************************/
int TDBODBC::WriteDB(PGLOBAL g)
{
strcpy(g->Message, "ODBC tables are read only");
return RC_FX;
} // end of WriteDB
/***********************************************************************/
/* Data Base delete line routine for ODBC access method. */
/***********************************************************************/
int TDBODBC::DeleteDB(PGLOBAL g, int irc)
{
strcpy(g->Message, MSG(NO_ODBC_DELETE));
return RC_FX;
} // end of DeleteDB
/***********************************************************************/
/* Data Base close routine for ODBC access method. */
/***********************************************************************/
void TDBODBC::CloseDB(PGLOBAL g)
{
//if (To_Kindex) {
// To_Kindex->Close();
// To_Kindex = NULL;
// } // endif
Ocp->Close();
#ifdef DEBTRACE
htrc("ODBC CloseDB: closing %s\n", Name);
#endif
} // end of CloseDB
/* --------------------------- ODBCCOL ------------------------------- */
/***********************************************************************/
/* ODBCCOL public constructor. */
/***********************************************************************/
ODBCCOL::ODBCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am)
: COLBLK(cdp, tdbp, i)
{
if (cprec) {
Next = cprec->GetNext();
cprec->SetNext(this);
} else {
Next = tdbp->GetColumns();
tdbp->SetColumns(this);
} // endif cprec
// Set additional ODBC access method information for column.
Long = cdp->GetLong();
//strcpy(F_Date, cdp->F_Date);
To_Val = NULL;
Slen = 0;
StrLen = &Slen;
Sqlbuf = NULL;
Bufp = NULL;
Blkp = NULL;
Rank = 0; // Not known yet
#ifdef DEBTRACE
htrc(" making new %sCOL C%d %s at %p\n",
am, Index, Name, this);
#endif
} // end of ODBCCOL constructor
/***********************************************************************/
/* ODBCCOL private constructor. */
/***********************************************************************/
ODBCCOL::ODBCCOL(void) : COLBLK()
{
Buf_Type = TYPE_INT; // This is a count(*) column
// Set additional Dos access method information for column.
Long = sizeof(int);
To_Val = NULL;
Slen = 0;
StrLen = &Slen;
Sqlbuf = NULL;
Bufp = NULL;
Blkp = NULL;
Rank = 1;
} // end of ODBCCOL constructor
/***********************************************************************/
/* ODBCCOL constructor used for copying columns. */
/* tdbp is the pointer to the new table descriptor. */
/***********************************************************************/
ODBCCOL::ODBCCOL(ODBCCOL *col1, PTDB tdbp) : COLBLK(col1, tdbp)
{
Long = col1->Long;
//strcpy(F_Date, col1->F_Date);
To_Val = col1->To_Val;
Slen = col1->Slen;
StrLen = col1->StrLen;
Sqlbuf = col1->Sqlbuf;
Bufp = col1->Bufp;
Blkp = col1->Blkp;
Rank = col1->Rank;
} // end of ODBCCOL copy constructor
/***********************************************************************/
/* SetBuffer: prepare a column block for write operation. */
/***********************************************************************/
bool ODBCCOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check)
{
if (!(To_Val = value)) {
sprintf(g->Message, MSG(VALUE_ERROR), Name);
return true;
} else if (Buf_Type == value->GetType()) {
// Values are of the (good) column type
if (Buf_Type == TYPE_DATE) {
// If any of the date values is formatted
// output format must be set for the receiving table
if (GetDomain() || ((DTVAL *)value)->IsFormatted())
goto newval; // This will make a new value;
} else if (Buf_Type == TYPE_FLOAT)
// Float values must be written with the correct (column) precision
// Note: maybe this should be forced by ShowValue instead of this ?
((DFVAL *)value)->SetPrec(GetPrecision());
Value = value; // Directly access the external value
} else {
// Values are not of the (good) column type
if (check) {
sprintf(g->Message, MSG(TYPE_VALUE_ERR), Name,
GetTypeName(Buf_Type), GetTypeName(value->GetType()));
return true;
} // endif check
newval:
if (InitValue(g)) // Allocate the matching value block
return true;
} // endif's Value, Buf_Type
// Because Colblk's have been made from a copy of the original TDB in
// case of Update, we must reset them to point to the original one.
if (To_Tdb->GetOrig())
To_Tdb = (PTDB)To_Tdb->GetOrig();
// Set the Column
Status = (ok) ? BUF_EMPTY : BUF_NO;
return false;
} // end of SetBuffer
/***********************************************************************/
/* ReadColumn: when SQLFetch is used there is nothing to do as the */
/* column buffer was bind to the record set. This is also the case */
/* when calculating MaxSize (Bufp is NULL even when Rows is not). */
/***********************************************************************/
void ODBCCOL::ReadColumn(PGLOBAL g)
{
PTDBODBC tdbp = (PTDBODBC)To_Tdb;
int n = tdbp->CurNum;
if (StrLen[n] == SQL_NULL_DATA) {
// Null value
Value->Reset();
return;
} // endif StrLen
if (Bufp && tdbp->Rows)
if (Buf_Type == TYPE_DATE)
*Sqlbuf = ((TIMESTAMP_STRUCT*)Bufp)[n];
else
Value->SetValue_pvblk(Blkp, n);
if (Buf_Type == TYPE_DATE) {
struct tm dbtime = {0,0,0,0,0,0,0,0,0};
dbtime.tm_sec = (int)Sqlbuf->second;
dbtime.tm_min = (int)Sqlbuf->minute;
dbtime.tm_hour = (int)Sqlbuf->hour;
dbtime.tm_mday = (int)Sqlbuf->day;
dbtime.tm_mon = (int)Sqlbuf->month - 1;
dbtime.tm_year = (int)Sqlbuf->year - 1900;
((DTVAL*)Value)->MakeTime(&dbtime);
} // endif Buf_Type
if (g->Trace) {
char buf[32];
htrc("ODBC Column %s: rows=%d buf=%p type=%d value=%s\n",
Name, tdbp->Rows, Bufp, Buf_Type, Value->GetCharString(buf));
} // endif Trace
} // end of ReadColumn
/***********************************************************************/
/* AllocateBuffers: allocate the extended buffer for SQLExtendedFetch */
/* or Fetch. Note: we use Long+1 here because ODBC must have space */
/* for the ending null character. */
/***********************************************************************/
void ODBCCOL::AllocateBuffers(PGLOBAL g, int rows)
{
if (Buf_Type == TYPE_DATE)
Sqlbuf = (TIMESTAMP_STRUCT*)PlugSubAlloc(g, NULL,
sizeof(TIMESTAMP_STRUCT));
if (!rows)
return;
if (Buf_Type == TYPE_DATE)
Bufp = PlugSubAlloc(g, NULL, rows * sizeof(TIMESTAMP_STRUCT));
else {
Blkp = AllocValBlock(g, NULL, Buf_Type, rows, Long+1, 0, true, false);
Bufp = Blkp->GetValPointer();
} // endelse
if (rows > 1)
StrLen = (SQLLEN *)PlugSubAlloc(g, NULL, rows * sizeof(int));
} // end of AllocateBuffers
/***********************************************************************/
/* Returns the buffer to use for Fetch or Extended Fetch. */
/***********************************************************************/
void *ODBCCOL::GetBuffer(DWORD rows)
{
if (rows && To_Tdb) {
assert(rows == (DWORD)((TDBODBC*)To_Tdb)->Rows);
return Bufp;
} else
return (Buf_Type == TYPE_DATE) ? Sqlbuf : Value->GetTo_Val();
} // end of GetBuffer
/***********************************************************************/
/* Returns the buffer length to use for Fetch or Extended Fetch. */
/***********************************************************************/
SWORD ODBCCOL::GetBuflen(void)
{
if (Buf_Type == TYPE_DATE)
return (SWORD)sizeof(TIMESTAMP_STRUCT);
else if (Buf_Type == TYPE_STRING)
return (SWORD)Value->GetClen() + 1;
else
return (SWORD)Value->GetClen();
} // end of GetBuflen
/***********************************************************************/
/* WriteColumn: make sure the bind buffer is updated. */
/***********************************************************************/
void ODBCCOL::WriteColumn(PGLOBAL g)
{
/*********************************************************************/
/* Do convert the column value if necessary. */
/*********************************************************************/
if (Value != To_Val)
Value->SetValue_pval(To_Val, false); // Convert the inserted value
if (Buf_Type == TYPE_DATE) {
struct tm *dbtime = ((DTVAL*)Value)->GetGmTime();
Sqlbuf->second = dbtime->tm_sec;
Sqlbuf->minute = dbtime->tm_min;
Sqlbuf->hour = dbtime->tm_hour;
Sqlbuf->day = dbtime->tm_mday;
Sqlbuf->month = dbtime->tm_mon + 1;
Sqlbuf->year = dbtime->tm_year + 1900;
} // endif Buf_Type
} // end of WriteColumn
/* ------------------------ End of Tabodbc --------------------------- */

170
storage/connect/tabodbc.h Normal file
View File

@@ -0,0 +1,170 @@
/*************** Tabodbc H Declares Source Code File (.H) **************/
/* Name: TABODBC.H Version 1.4 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 2000-2012 */
/* */
/* This file contains the TDBODBC classes declares. */
/***********************************************************************/
#if !defined(NO_ICONV)
#include <iconv.h>
#endif // !NO_ICONV
#include "colblk.h"
typedef class ODBCDEF *PODEF;
typedef class TDBODBC *PTDBODBC;
typedef class ODBCCOL *PODBCCOL;
/***********************************************************************/
/* ODBC table. */
/***********************************************************************/
class DllExport ODBCDEF : public TABDEF { /* Logical table description */
public:
// Constructor
ODBCDEF(void)
{Connect = Tabname = Tabowner = Tabqual = Qchar = NULL; Options = 0;}
// Implementation
virtual const char *GetType(void) {return "ODBC";}
PSZ GetConnect(void) {return Connect;}
PSZ GetTabname(void) {return Tabname;}
PSZ GetTabowner(void) {return Tabowner;}
PSZ GetTabqual(void) {return Tabqual;}
PSZ GetQchar(void) {return (Qchar && *Qchar) ? Qchar : NULL;}
int GetCatver(void) {return Catver;}
int GetOptions(void) {return Options;}
// Methods
virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff);
virtual PTDB GetTable(PGLOBAL g, MODE m);
protected:
// Members
PSZ Connect; /* ODBC connection string */
PSZ Tabname; /* External table name */
PSZ Tabowner; /* External table owner */
PSZ Tabqual; /* External table qualifier */
PSZ Qchar; /* Identifier quoting character */
int Catver; /* ODBC version for catalog functions */
int Options; /* Open connection options */
}; // end of ODBCDEF
#if !defined(NODBC)
#include "odbconn.h"
/***********************************************************************/
/* This is the ODBC Access Method class declaration for files from */
/* other DB drivers to be accessed via ODBC. */
/***********************************************************************/
class TDBODBC : public TDBASE {
friend class ODBCCOL;
friend class ODBConn;
public:
// Constructor
TDBODBC(PODEF tdp = NULL);
TDBODBC(PTDBODBC tdbp);
// Implementation
virtual AMT GetAmType(void) {return TYPE_AM_ODBC;}
virtual PTDB Duplicate(PGLOBAL g)
{return (PTDB)new(g) TDBODBC(this);}
// Methods
virtual PTDB CopyOne(PTABS t);
virtual int GetRecpos(void);
virtual PSZ GetFile(PGLOBAL g);
virtual void SetFile(PGLOBAL g, PSZ fn);
virtual void ResetSize(void);
virtual int GetAffectedRows(void) {return AftRows;}
// Database routines
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
virtual int GetProgMax(PGLOBAL g);
virtual int GetMaxSize(PGLOBAL g);
virtual bool OpenDB(PGLOBAL g);
virtual int ReadDB(PGLOBAL g);
virtual int WriteDB(PGLOBAL g);
virtual int DeleteDB(PGLOBAL g, int irc);
virtual void CloseDB(PGLOBAL g);
protected:
// Internal functions
#if !defined(NO_ICONV)
int Decode(iconv_t cd, char *utf, char *buf, size_t n);
#else // NO_ICONV
inline int Decode(void *cd, char *str, char *buf, size_t n)
{strncpy(buf, str, n); return 0;}
#endif // NO_ICONV
char *MakeSQL(PGLOBAL g, bool cnt);
//bool MakeUpdate(PGLOBAL g, PSELECT selist);
//bool MakeInsert(PGLOBAL g);
//bool MakeDelete(PGLOBAL g);
//bool MakeFilter(PGLOBAL g, bool c);
//bool BindParameters(PGLOBAL g);
// Members
ODBConn *Ocp; // Points to an ODBC connection class
ODBCCOL *Cnp; // Points to count(*) column
char *Connect; // Points to connection string
char *TableName; // Points to EOM table name
char *Owner; // Points to EOM table Owner
char *Qualifier; // Points to EOM table Qualifier
char *Query; // Points to SQL statement
char *Count; // Points to count(*) SQL statement
//char *Where; // Points to local where clause
char *Quote; // The identifier quoting character
char *MulConn; // Used for multiple ODBC tables
char *DBQ; // The address part of Connect string
int Options; // Connect options
int Fpos; // Position of last read record
int AftRows; // The number of affected rows
int Rows; // Rowset size
int Catver; // Catalog ODBC version
int CurNum; // Current buffer line number
int Rbuf; // Number of lines read in buffer
int BufSize; // Size of connect string buffer
int Nparm; // The number of statement parameters
}; // end of class TDBODBC
/***********************************************************************/
/* Class ODBCCOL: DOS access method column descriptor. */
/* This A.M. is used for ODBC tables. */
/***********************************************************************/
class ODBCCOL : public COLBLK {
friend class TDBODBC;
public:
// Constructors
ODBCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am = "ODBC");
ODBCCOL(ODBCCOL *colp, PTDB tdbp); // Constructor used in copy process
// Implementation
virtual int GetAmType(void) {return TYPE_AM_ODBC;}
SQLLEN *GetStrLen(void) {return StrLen;}
int GetRank(void) {return Rank;}
// PVBLK GetBlkp(void) {return Blkp;}
// Methods
//virtual bool CheckLocal(PTDB tdbp);
virtual bool SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check);
virtual void ReadColumn(PGLOBAL g);
virtual void WriteColumn(PGLOBAL g);
void AllocateBuffers(PGLOBAL g, int rows);
void *GetBuffer(DWORD rows);
SWORD GetBuflen(void);
// void Print(PGLOBAL g, FILE *, uint);
protected:
// Constructor used by GetMaxSize
ODBCCOL(void);
// Members
TIMESTAMP_STRUCT *Sqlbuf; // To get SQL_TIMESTAMP's
void *Bufp; // To extended buffer
PVBLK Blkp; // To Value Block
//char F_Date[12]; // Internal Date format
PVAL To_Val; // To value used for Insert
SQLLEN *StrLen; // As returned by ODBC
SQLLEN Slen; // Used with Fetch
int Rank; // Rank (position) number in the query
}; // end of class ODBCCOL
#endif // !NODBC

1202
storage/connect/tabpivot.cpp Normal file

File diff suppressed because it is too large Load Diff

241
storage/connect/tabpivot.h Normal file
View File

@@ -0,0 +1,241 @@
/************** TabPivot H Declares Source Code File (.H) **************/
/* Name: TABPIVOT.H Version 1.3 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 2005-2012 */
/* */
/* This file contains the PIVOT classes declares. */
/***********************************************************************/
typedef class TDBPIVOT *PTDBPIVOT;
typedef class FNCCOL *PFNCCOL;
typedef class SRCCOL *PSRCCOL;
typedef class TDBQRS *PTDBQRS;
typedef class QRSCOL *PQRSCOL;
/* -------------------------- PIVOT classes -------------------------- */
/***********************************************************************/
/* PIVOT: table that provides a view of a source table where the */
/* pivot column is expended in as many columns as there are distinct */
/* values in it and containing the function value matching other cols.*/
/***********************************************************************/
/***********************************************************************/
/* PIVOT table. */
/***********************************************************************/
//ass DllExport PIVOTDEF : public TABDEF {/* Logical table description */
class PIVOTDEF : public TABDEF { /* Logical table description */
friend class TDBPIVOT;
public:
// Constructor
PIVOTDEF(void) {Pseudo = 3;
Tabname = Tabsrc = Picol = Fncol = Function = NULL;}
// Implementation
virtual const char *GetType(void) {return "PIVOT";}
// Methods
virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff);
virtual PTDB GetTable(PGLOBAL g, MODE m);
protected:
// Members
char *Host; /* Host machine to use */
char *User; /* User logon info */
char *Pwd; /* Password logon info */
char *DB; /* Database to be used by server */
char *Tabname; /* Name of source table */
char *Tabsrc; /* The source table SQL description */
char *Picol; /* The pivot column */
char *Fncol; /* The function column */
char *Function; /* The function applying to group by */
bool GBdone; /* True if tabname as group by format */
int Port; /* MySQL port number */
}; // end of PIVOTDEF
/***********************************************************************/
/* This is the class declaration for the PIVOT table. */
/***********************************************************************/
//ass DllExport TDBPIVOT : public TDBASE, public CSORT {
class TDBPIVOT : public TDBASE, public CSORT {
friend class FNCCOL;
friend class SRCCOL;
public:
// Constructor
TDBPIVOT(PPIVOTDEF tdp);
//TDBPIVOT(PTDBPIVOT tdbp);
// Implementation
virtual AMT GetAmType(void) {return TYPE_AM_PIVOT;}
//virtual PTDB Duplicate(PGLOBAL g) {return (PTDB)new(g) TDBPIVOT(this);}
// void SetTdbp(PTDB tdbp) {Tdbp = tdbp;}
// Methods
//virtual PTDB CopyOne(PTABS t);
virtual int GetRecpos(void) {return N;}
virtual void ResetDB(void) {N = 0;}
virtual int RowNumber(PGLOBAL g, bool b = FALSE);
// Database routines
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
virtual int GetMaxSize(PGLOBAL g);
virtual bool OpenDB(PGLOBAL g);
virtual int ReadDB(PGLOBAL g);
virtual int WriteDB(PGLOBAL g);
virtual int DeleteDB(PGLOBAL g, int irc);
virtual void CloseDB(PGLOBAL g);
// The sorting function
virtual int Qcompare(int *, int *);
protected:
PQRYRES GetSourceTable(PGLOBAL g);
int MakePivotColumns(PGLOBAL g);
bool UpdateTableFields(PGLOBAL g, int n);
// Members
MYSQLC Myc; // MySQL connection class
PTDBQRS Tqrp; // To the source table result
char *Host; // Host machine to use
char *User; // User logon info
char *Pwd; // Password logon info
char *Database; // Database to be used by server
PQRYRES Qryp; // Points to Query result block
char *Tabname; // Name of source table
char *Tabsrc; // SQL of source table
char *Picol; // Pivot column name
char *Fncol; // Function column name
char *Function; // The function applying to group by
PQRSCOL Fcolp; // To the function column in source
PQRSCOL Xcolp; // To the pivot column in source
PCOLRES Xresp; // To the pivot result column
//PCOLRES To_Sort; // Saved Qryp To_Sort pointer
PVBLK Rblkp; // The value block of the pivot column
bool GBdone; // True when subtable is "Group by"
int Mult; // Multiplication factor
int Ncol; // The number of generated columns
int N; // The current table index
int M; // The occurence rank
int Port; // MySQL port number
BYTE FileStatus; // 0: First 1: Rows 2: End-of-File
BYTE RowFlag; // 0: Ok, 1: Same, 2: Skip
}; // end of class TDBPIVOT
/***********************************************************************/
/* Class FNCCOL: for the multiple generated column. */
/***********************************************************************/
class FNCCOL : public COLBLK {
friend class TDBPIVOT;
public:
// Constructor
FNCCOL(PCOL colp, PTDBPIVOT tdbp);
// Implementation
virtual int GetAmType(void) {return TYPE_AM_FNC;}
// Methods
virtual void Reset(void) {}
bool InitColumn(PGLOBAL g, PVAL valp);
protected:
// Member
PVAL Hval; // The original value used to generate the header
}; // end of class FNCCOL
/***********************************************************************/
/* Class SRCCOL: for other source columns. */
/***********************************************************************/
class SRCCOL : public COLBLK {
friend class TDBPIVOT;
public:
// Constructors
//SRCCOL(PCOLDEF cdp, PTDBPIVOT tdbp, int n);
SRCCOL(PCOL cp, PTDBPIVOT tdbp, int n);
//SRCCOL(SRCCOL *colp, PTDB tdbp); // Constructor used in copy process
// Implementation
virtual int GetAmType(void) {return TYPE_AM_SRC;}
// Methods
virtual void Reset(void) {}
void SetColumn(void);
bool Init(PGLOBAL g, PTDBPIVOT tdbp);
bool CompareColumn(void);
protected:
// Default constructor not to be used
SRCCOL(void) {}
// Members
PQRSCOL Colp;
PVAL Cnval;
}; // end of class SRCCOL
/***********************************************************************/
/* TDBQRS: This is the Access Method class declaration for the Query */
/* Result stored in memory in the current work area (volatil). */
/***********************************************************************/
class DllExport TDBQRS : public TDBASE {
friend class QRSCOL;
public:
// Constructor
TDBQRS(PQRYRES qrp) : TDBASE() {Qrp = qrp; CurPos = 0;}
TDBQRS(PTDBQRS tdbp);
// Implementation
virtual AMT GetAmType(void) {return TYPE_AM_QRS;}
virtual PTDB Duplicate(PGLOBAL g)
{return (PTDB)new(g) TDBQRS(this);}
PQRYRES GetQrp(void) {return Qrp;}
// Methods
virtual PTDB CopyOne(PTABS t);
virtual int RowNumber(PGLOBAL g, BOOL b = FALSE);
virtual int GetRecpos(void);
//virtual PCATLG GetCat(void);
//virtual PSZ GetPath(void);
virtual int GetBadLines(void) {return Qrp->BadLines;}
// Database routines
virtual PCOL ColDB(PGLOBAL g, PSZ name, int num);
virtual int GetMaxSize(PGLOBAL g);
virtual bool OpenDB(PGLOBAL g);
virtual int ReadDB(PGLOBAL g);
virtual int WriteDB(PGLOBAL g);
virtual int DeleteDB(PGLOBAL g, int irc);
virtual void CloseDB(PGLOBAL g);
private:
TDBQRS(void) : TDBASE() {} // Standard constructor not to be used
protected:
// Members
PQRYRES Qrp; // Points to Query Result block
int CurPos; // Current line position
}; // end of class TDBQRS
/***********************************************************************/
/* Class QRSCOL: QRS access method column descriptor. */
/***********************************************************************/
class DllExport QRSCOL : public COLBLK {
friend class TDBQRS;
public:
// Constructors
QRSCOL(PGLOBAL g, PCOLRES crp, PTDB tdbp, PCOL cprec, int i);
QRSCOL(QRSCOL *colp, PTDB tdbp); // Constructor used in copy process
// Implementation
virtual int GetAmType(void) {return TYPE_AM_QRS;}
PCOLRES GetCrp(void) {return Crp;}
void *GetQrsData(void) {return Crp->Kdata;}
// Methods
virtual void ReadColumn(PGLOBAL g);
virtual void Print(PGLOBAL g, FILE *, UINT);
protected:
QRSCOL(void) {} // Default constructor not to be used
// Members
PCOLRES Crp;
}; // end of class QRSCOL

877
storage/connect/tabsys.cpp Normal file
View File

@@ -0,0 +1,877 @@
/************* TabSys C++ Program Source Code File (.CPP) **************/
/* PROGRAM NAME: TABSYS */
/* ------------- */
/* Version 2.2 */
/* */
/* Author Olivier BERTRAND 2004-2013 */
/* */
/* This program are the INI/CFG tables classes. */
/***********************************************************************/
/***********************************************************************/
/* Include relevant sections of the System header files. */
/***********************************************************************/
#include "my_global.h"
#if defined(WIN32)
#if defined(__BORLANDC__)
#define __MFC_COMPAT__ // To define min/max as macro
#endif // __BORLANDC__
//#include <windows.h>
#else // !WIN32
#if defined(UNIX)
#include <errno.h>
#include <unistd.h>
#else // !UNIX
#include <io.h>
#endif // !UNIX
#include <fcntl.h>
#endif // !WIN32
/***********************************************************************/
/* Include application header files: */
/* global.h is header containing all global declarations. */
/* plgdbsem.h is header containing the DB application declarations. */
/* tabdos.h is header containing the TABDOS class declarations. */
/***********************************************************************/
#include "global.h"
#include "plgdbsem.h"
#include "reldef.h"
//#include "xobject.h"
#include "filamtxt.h"
#include "tabdos.h"
#include "tabsys.h"
#include "tabmul.h"
#if defined(UNIX)
#include "osutil.h"
#endif // UNIX
#define CSZ 36 // Column section name length
#define CDZ 256 // Column definition length
#if !defined(WIN32)
#define GetPrivateProfileSectionNames(S,L,I) \
GetPrivateProfileString(NULL,NULL,"",S,L,I)
#endif // !WIN32
extern "C" int trace;
/* -------------- Implementation of the INI classes ------------------ */
/***********************************************************************/
/* Constructor. */
/***********************************************************************/
INIDEF::INIDEF(void)
{
Pseudo = 3;
Fn = NULL;
Xname = NULL;
Subtype = '?';
Layout = '?';
Ln = 0;
} // end of INIDEF constructor
/***********************************************************************/
/* DefineAM: define specific AM block values from XDB file. */
/***********************************************************************/
bool INIDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
{
char buf[8], ds[2];
void *memp = Cat->GetDescp();
if (!stricmp(am, "SYS"))
strcpy(ds, "T"); // SYS tables default to T(able)
else
strcpy(ds, "I"); // INI tables default to I(ni)
Fn = Cat->GetStringCatInfo(g, Name, "Filename", "?");
Cat->GetCharCatInfo(Name, "Subtype", ds, buf, sizeof(buf));
Subtype = toupper(*buf);
Cat->GetCharCatInfo(Name, "Layout", "C", buf, sizeof(buf));
Layout = toupper(*buf);
switch (Subtype) {
#if 0
case 'C':
case 'T':
// Restricted table
Xname = Cat->GetStringCatInfo(g, Name, "Name", "?");
if (!strcmp(Xname, "?"))
Xname = NULL;
if (*Fn == '?')
Fn = Cat->GetStringCatInfo(g, Name, "Database", "?");
if (*Fn != '?') {
char *p = (char*)PlugSubAlloc(g, memp, _MAX_PATH);
if (!PlgSetXdbPath(g, Fn, NULL, p, _MAX_PATH, NULL, 0))
Fn = p;
} else
Fn = Cat->GetDescFile();
Ln = GetIniSize("Database", "Tabsize", "2K", Fn);
break;
#endif // 0
case 'I':
if (*Fn != '?') {
char *p = (char*)PlugSubAlloc(g, memp, _MAX_PATH);
PlugSetPath(p, Fn, GetPath());
Fn = p;
} else {
strcpy(g->Message, MSG(MISSING_FNAME));
return true;
} // endif Fn
Ln = Cat->GetSizeCatInfo((char*)Name, "Secsize", "8K");
break;
default:
sprintf(g->Message, MSG(INV_SUBTYPE), buf);
return true;
} // endswitch Subtype
Desc = Fn;
return false;
} // end of DefineAM
/***********************************************************************/
/* GetTable: makes a new TDB of the proper type. */
/***********************************************************************/
PTDB INIDEF::GetTable(PGLOBAL g, MODE m)
{
PTDBASE tdbp;
switch (Subtype) {
case 'I':
if (Layout == 'C')
tdbp = new(g) TDBINI(this);
else
tdbp = new(g) TDBXIN(this);
break;
default:
return NULL;
} // endswitch Subtype
if (Multiple)
tdbp = new(g) TDBMUL(tdbp); // No block optimization yet
return tdbp;
} // end of GetTable
/***********************************************************************/
/* DeleteTableFile: Delete INI table files using platform API. */
/* SysTable and SysColumn tables are readonly and not erasable. */
/***********************************************************************/
bool INIDEF::DeleteTableFile(PGLOBAL g)
{
char filename[_MAX_PATH];
bool rc;
// Delete the INI table file if not protected
if (Subtype == 'I' && !IsReadOnly()) {
PlugSetPath(filename, Fn, GetPath());
#if defined(WIN32)
rc = !DeleteFile(filename);
#else // UNIX
rc = remove(filename);
#endif // UNIX
} else
rc =true;
return rc; // Return true if error
} // end of DeleteTableFile
/* ------------------------------------------------------------------- */
/***********************************************************************/
/* Implementation of the TDBINI class. */
/***********************************************************************/
TDBINI::TDBINI(PINIDEF tdp) : TDBASE(tdp)
{
Ifile = tdp->Fn;
Seclist = NULL;
Section = NULL;
Seclen = tdp->Ln;
N = 0;
} // end of TDBINI constructor
TDBINI::TDBINI(PTDBINI tdbp) : TDBASE(tdbp)
{
Ifile = tdbp->Ifile;
Seclist = tdbp->Seclist;
Section = tdbp->Section;
Seclen = tdbp->Seclen;
N = tdbp->N;
} // end of TDBINI copy constructor
// Is this really useful ???
PTDB TDBINI::CopyOne(PTABS t)
{
PTDB tp;
PINICOL cp1, cp2;
PGLOBAL g = t->G;
tp = new(g) TDBINI(this);
for (cp1 = (PINICOL)Columns; cp1; cp1 = (PINICOL)cp1->GetNext()) {
cp2 = new(g) INICOL(cp1, tp); // Make a copy
NewPointer(t, cp1, cp2);
} // endfor cp1
return tp;
} // end of CopyOne
/***********************************************************************/
/* Get the section list from the INI file. */
/***********************************************************************/
char *TDBINI::GetSeclist(PGLOBAL g)
{
if (trace)
htrc("GetSeclist: Seclist=%p\n", Seclist);
if (!Seclist) {
// Result will be retrieved from the INI file
Seclist = (char*)PlugSubAlloc(g, NULL, Seclen);
GetPrivateProfileSectionNames(Seclist, Seclen, Ifile);
} // endif Seclist
return Seclist;
} // end of GetSeclist
/***********************************************************************/
/* Allocate INI column description block. */
/***********************************************************************/
PCOL TDBINI::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
{
return new(g) INICOL(cdp, this, cprec, n);
} // end of MakeCol
/***********************************************************************/
/* INI GetMaxSize: returns the number of sections in the INI file. */
/***********************************************************************/
int TDBINI::GetMaxSize(PGLOBAL g)
{
if (MaxSize < 0 && GetSeclist(g)) {
// Count the number of sections from the section list
char *p;
for (MaxSize = 0, p = Seclist; *p; p += (strlen(p) + 1))
MaxSize++;
} // endif MaxSize
return MaxSize;
} // end of GetMaxSize
/***********************************************************************/
/* INI Access Method opening routine. */
/***********************************************************************/
bool TDBINI::OpenDB(PGLOBAL g)
{
PINICOL colp;
if (Use == USE_OPEN) {
if (To_Kindex)
/*****************************************************************/
/* Table is to be accessed through a sorted index table. */
/*****************************************************************/
To_Kindex->Reset();
Section = NULL;
N = 0;
return false;
} // endif use
/*********************************************************************/
/* OpenDB: initialize the INI file processing. */
/*********************************************************************/
GetSeclist(g);
Use = USE_OPEN; // Do it now in case we are recursively called
/*********************************************************************/
/* Allocate the buffers that will contain key values. */
/*********************************************************************/
for (colp = (PINICOL)Columns; colp; colp = (PINICOL)colp->GetNext())
if (!colp->IsSpecial()) // Not a pseudo column
colp->AllocBuf(g);
if (trace)
htrc("INI OpenDB: seclist=%s seclen=%d ifile=%s\n",
Seclist, Seclen, Ifile);
return false;
} // end of OpenDB
/***********************************************************************/
/* Data Base read routine for INI access method. */
/***********************************************************************/
int TDBINI::ReadDB(PGLOBAL g)
{
/*********************************************************************/
/* Now start the pseudo reading process. */
/*********************************************************************/
if (To_Kindex) {
/*******************************************************************/
/* Reading is by an index table. */
/*******************************************************************/
int recpos = To_Kindex->Fetch(g);
switch (recpos) {
case -1: // End of file reached
return RC_EF;
case -2: // No match for join
return RC_NF;
case -3: // Same record as last non null one
return RC_OK;
default:
Section = (char*)recpos;
} // endswitch recpos
} else {
if (!Section)
Section = Seclist;
else
Section += (strlen(Section) + 1);
if (trace > 1)
htrc("INI ReadDB: section=%s N=%d\n", Section, N);
N++;
} // endif To_Kindex
return (*Section) ? RC_OK : RC_EF;
} // end of ReadDB
/***********************************************************************/
/* WriteDB: Data Base write routine for INI access methods. */
/***********************************************************************/
int TDBINI::WriteDB(PGLOBAL g)
{
// This is to check that section name was given when inserting
if (Mode == MODE_INSERT)
Section = NULL;
// Nothing else to do because all was done in WriteColumn
return RC_OK;
} // end of WriteDB
/***********************************************************************/
/* Data Base delete line routine for INI access methods. */
/***********************************************************************/
int TDBINI::DeleteDB(PGLOBAL g, int irc)
{
switch (irc) {
case RC_EF:
break;
case RC_FX:
while (ReadDB(g) == RC_OK)
WritePrivateProfileString(Section, NULL, NULL, Ifile);
break;
default:
if (!Section) {
strcpy(g->Message, MSG(NO_SECTION_NAME));
return RC_FX;
} else
WritePrivateProfileString(Section, NULL, NULL, Ifile);
} // endswitch irc
return RC_OK;
} // end of DeleteDB
/***********************************************************************/
/* Data Base close routine for INI access methods. */
/***********************************************************************/
void TDBINI::CloseDB(PGLOBAL g)
{
// Nothing to do
} // end of CloseDB
// ------------------------ INICOL functions ----------------------------
/***********************************************************************/
/* INICOL public constructor. */
/***********************************************************************/
INICOL::INICOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am)
: COLBLK(cdp, tdbp, i)
{
if (cprec) {
Next = cprec->GetNext();
cprec->SetNext(this);
} else {
Next = tdbp->GetColumns();
tdbp->SetColumns(this);
} // endif cprec
// Set additional INI access method information for column.
Valbuf = NULL;
Flag = cdp->GetOffset();
Long = cdp->GetLong();
To_Val = NULL;
} // end of INICOL constructor
/***********************************************************************/
/* INICOL constructor used for copying columns. */
/* tdbp is the pointer to the new table descriptor. */
/***********************************************************************/
INICOL::INICOL(INICOL *col1, PTDB tdbp) : COLBLK(col1, tdbp)
{
Valbuf = col1->Valbuf;
Flag = col1->Flag;
Long = col1->Long;
To_Val = col1->To_Val;
} // end of INICOL copy constructor
/***********************************************************************/
/* Allocate a buffer of the proper size. */
/***********************************************************************/
void INICOL::AllocBuf(PGLOBAL g)
{
if (!Valbuf)
Valbuf = (char*)PlugSubAlloc(g, NULL, Long + 1);
} // end of AllocBuf
/***********************************************************************/
/* SetBuffer: prepare a column block for write operation. */
/***********************************************************************/
bool INICOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check)
{
if (!(To_Val = value)) {
sprintf(g->Message, MSG(VALUE_ERROR), Name);
return true;
} else if (Buf_Type == value->GetType()) {
// Values are of the (good) column type
if (Buf_Type == TYPE_DATE) {
// If any of the date values is formatted
// output format must be set for the receiving table
if (GetDomain() || ((DTVAL *)value)->IsFormatted())
goto newval; // This will make a new value;
} else if (Buf_Type == TYPE_FLOAT)
// Float values must be written with the correct (column) precision
// Note: maybe this should be forced by ShowValue instead of this ?
((DFVAL *)value)->SetPrec(GetPrecision());
Value = value; // Directly access the external value
} else {
// Values are not of the (good) column type
if (check) {
sprintf(g->Message, MSG(TYPE_VALUE_ERR), Name,
GetTypeName(Buf_Type), GetTypeName(value->GetType()));
return true;
} // endif check
newval:
if (InitValue(g)) // Allocate the matching value block
return true;
} // endif's Value, Buf_Type
// Allocate the internal value buffer
AllocBuf(g);
// Because Colblk's have been made from a copy of the original TDB in
// case of Update, we must reset them to point to the original one.
if (To_Tdb->GetOrig())
To_Tdb = (PTDB)To_Tdb->GetOrig();
// Set the Column
Status = (ok) ? BUF_EMPTY : BUF_NO;
return false;
} // end of SetBuffer
/***********************************************************************/
/* ReadColumn: what this routine does is to access the key buffer set */
/* from the corresponding section, extract from it the key value */
/* corresponding to this column name and convert it to buffer type. */
/***********************************************************************/
void INICOL::ReadColumn(PGLOBAL g)
{
PTDBINI tdbp = (PTDBINI)To_Tdb;
if (trace > 1)
htrc("INI ReadColumn: col %s R%d flag=%d\n",
Name, tdbp->GetTdb_No(), Flag);
/*********************************************************************/
/* Get the key value from the INI file. */
/*********************************************************************/
switch (Flag) {
case 1:
strncpy(Valbuf, tdbp->Section, Long); // Section name
Valbuf[Long] = '\0';
break;
default:
GetPrivateProfileString(tdbp->Section, Name, "",
Valbuf, Long + 1, tdbp->Ifile);
break;
} // endswitch Flag
Value->SetValue_psz(Valbuf);
} // 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 INICOL::WriteColumn(PGLOBAL g)
{
char *p;
PTDBINI tdbp = (PTDBINI)To_Tdb;
if (trace > 1)
htrc("INI WriteColumn: col %s R%d coluse=%.4X status=%.4X\n",
Name, tdbp->GetTdb_No(), ColUse, Status);
/*********************************************************************/
/* Get the string representation of Value according to column type. */
/*********************************************************************/
if (Value != To_Val)
Value->SetValue_pval(To_Val, false); // Convert the updated value
p = Value->GetCharString(Valbuf);
if (strlen(p) > (unsigned)Long) {
sprintf(g->Message, MSG(VALUE_TOO_LONG), p, Name, Long);
longjmp(g->jumper[g->jump_level], 31);
} else if (Flag == 1) {
if (tdbp->Mode == MODE_UPDATE) {
strcpy(g->Message, MSG(NO_SEC_UPDATE));
longjmp(g->jumper[g->jump_level], 31);
} else {
tdbp->Section = p;
return;
} // endif Mode
} else if (!tdbp->Section) {
strcpy(g->Message, MSG(SEC_NAME_FIRST));
longjmp(g->jumper[g->jump_level], 31);
} // endif's
/*********************************************************************/
/* Updating must be done only when not in checking pass. */
/*********************************************************************/
if (Status)
WritePrivateProfileString(tdbp->Section, Name, p, tdbp->Ifile);
} // end of WriteColumn
/* ------------------------------------------------------------------- */
/***********************************************************************/
/* Implementation of the TDBXIN class. */
/***********************************************************************/
TDBXIN::TDBXIN(PINIDEF tdp) : TDBINI(tdp)
{
Keylist = NULL;
Keycur = NULL;
Keylen = Seclen;
Oldsec = -1;
} // end of TDBXIN constructor
TDBXIN::TDBXIN(PTDBXIN tdbp) : TDBINI(tdbp)
{
Keylist = tdbp->Keylist;
Keycur = tdbp->Keycur;
Keylen = tdbp->Keylen;
Oldsec = tdbp->Oldsec;
} // end of TDBXIN copy constructor
// Is this really useful ???
PTDB TDBXIN::CopyOne(PTABS t)
{
PTDB tp;
PXINCOL cp1, cp2;
PGLOBAL g = t->G;
tp = new(g) TDBXIN(this);
for (cp1 = (PXINCOL)Columns; cp1; cp1 = (PXINCOL)cp1->GetNext()) {
cp2 = new(g) XINCOL(cp1, tp); // Make a copy
NewPointer(t, cp1, cp2);
} // endfor cp1
return tp;
} // end of CopyOne
/***********************************************************************/
/* Get the key list from the INI file. */
/***********************************************************************/
char *TDBXIN::GetKeylist(PGLOBAL g, char *sec)
{
if (!Keylist)
Keylist = (char*)PlugSubAlloc(g, NULL, Keylen);
GetPrivateProfileString(sec, NULL, "", Keylist, Keylen, Ifile);
return Keylist;
} // end of GetKeylist
/***********************************************************************/
/* Allocate XIN column description block. */
/***********************************************************************/
PCOL TDBXIN::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
{
return new(g) XINCOL(cdp, this, cprec, n);
} // end of MakeCol
/***********************************************************************/
/* XIN GetMaxSize: returns the number of sections in the XIN file. */
/***********************************************************************/
int TDBXIN::GetMaxSize(PGLOBAL g)
{
if (MaxSize < 0 && GetSeclist(g)) {
// Count the number of keys from the section list
char *p, *k;
for (MaxSize = 0, p = Seclist; *p; p += (strlen(p) + 1))
for (k = GetKeylist(g, p); *k; k += (strlen(k) + 1))
MaxSize++;
} // endif MaxSize
return MaxSize;
} // end of GetMaxSize
/***********************************************************************/
/* Record position is Section+Key. */
/***********************************************************************/
int TDBXIN::GetRecpos(void)
{
union {
short X[2]; // Section and Key offsets
int Xpos; // File position
}; // end of union
X[0] = (short)(Section - Seclist);
X[1] = (short)(Keycur - Keylist);
return Xpos;
} // end of GetRecpos
/***********************************************************************/
/* Record position is Section+Key. */
/***********************************************************************/
bool TDBXIN::SetRecpos(PGLOBAL g, int recpos)
{
union {
short X[2]; // Section and Key offsets
int Xpos; // File position
}; // end of union
Xpos = recpos;
if (X[0] != Oldsec) {
Section = Seclist + X[0];
Keycur = GetKeylist(g, Section) + X[1];
Oldsec = X[0];
} else
Keycur = Keylist + X[1];
return false;
} // end of SetRecpos
/***********************************************************************/
/* XIN Access Method opening routine. */
/***********************************************************************/
bool TDBXIN::OpenDB(PGLOBAL g)
{
Oldsec = -1; // To replace the table at its beginning
return TDBINI::OpenDB(g);
} // end of OpenDB
/***********************************************************************/
/* Data Base read routine for XIN access method. */
/***********************************************************************/
int TDBXIN::ReadDB(PGLOBAL g)
{
/*********************************************************************/
/* Now start the pseudo reading process. */
/*********************************************************************/
if (To_Kindex) {
/*******************************************************************/
/* Reading is by an index table. */
/*******************************************************************/
int recpos = To_Kindex->Fetch(g);
switch (recpos) {
case -1: // End of file reached
return RC_EF;
case -2: // No match for join
return RC_NF;
case -3: // Same record as last non null one
return RC_OK;
default:
SetRecpos(g, recpos);
} // endswitch recpos
} else {
do {
if (!Keycur || !*Keycur) {
if (!Section)
Section = Seclist;
else
Section += (strlen(Section) + 1);
if (*Section)
Keycur = GetKeylist(g, Section);
else
return RC_EF;
} else
Keycur += (strlen(Keycur) + 1);
} while (!*Keycur);
N++;
} // endif To_Kindex
return RC_OK;
} // end of ReadDB
/***********************************************************************/
/* WriteDB: Data Base write routine for XIN access methods. */
/***********************************************************************/
int TDBXIN::WriteDB(PGLOBAL g)
{
// To check that section and key names were given when inserting
if (Mode == MODE_INSERT) {
Section = NULL;
Keycur = NULL;
} // endif Mode
// Nothing else to do because all was done in WriteColumn
return RC_OK;
} // end of WriteDB
/***********************************************************************/
/* Data Base delete line routine for XIN access methods. */
/***********************************************************************/
int TDBXIN::DeleteDB(PGLOBAL g, int irc)
{
if (irc == RC_EF) {
} else if (irc == RC_FX) {
for (Section = Seclist; *Section; Section += (strlen(Section) + 1))
WritePrivateProfileString(Section, NULL, NULL, Ifile);
} else if (Section) {
WritePrivateProfileString(Section, Keycur, NULL, Ifile);
} else {
strcpy(g->Message, MSG(NO_SECTION_NAME));
return RC_FX;
} // endif's
return RC_OK;
} // end of DeleteDB
// ------------------------ XINCOL functions ----------------------------
/***********************************************************************/
/* XINCOL public constructor. */
/***********************************************************************/
XINCOL::XINCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am)
: INICOL(cdp, tdbp, cprec, i, am)
{
} // end of XINCOL constructor
/***********************************************************************/
/* XINCOL constructor used for copying columns. */
/* tdbp is the pointer to the new table descriptor. */
/***********************************************************************/
XINCOL::XINCOL(XINCOL *col1, PTDB tdbp) : INICOL(col1, tdbp)
{
} // end of XINCOL copy constructor
/***********************************************************************/
/* ReadColumn: what this routine does is to access the key buffer set */
/* from the corresponding section, extract from it the key value */
/* corresponding to this column name and convert it to buffer type. */
/***********************************************************************/
void XINCOL::ReadColumn(PGLOBAL g)
{
PTDBXIN tdbp = (PTDBXIN)To_Tdb;
/*********************************************************************/
/* Get the key value from the XIN file. */
/*********************************************************************/
switch (Flag) {
case 1:
strncpy(Valbuf, tdbp->Section, Long); // Section name
Valbuf[Long] = '\0';
break;
case 2:
strncpy(Valbuf, tdbp->Keycur, Long); // Key name
Valbuf[Long] = '\0';
break;
default:
GetPrivateProfileString(tdbp->Section, tdbp->Keycur, "",
Valbuf, Long + 1, tdbp->Ifile);
break;
} // endswitch Flag
Value->SetValue_psz(Valbuf);
} // 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 XINCOL::WriteColumn(PGLOBAL g)
{
char *p;
PTDBXIN tdbp = (PTDBXIN)To_Tdb;
if (trace > 1)
htrc("XIN WriteColumn: col %s R%d coluse=%.4X status=%.4X\n",
Name, tdbp->GetTdb_No(), ColUse, Status);
/*********************************************************************/
/* Get the string representation of Value according to column type. */
/*********************************************************************/
if (Value != To_Val)
Value->SetValue_pval(To_Val, false); // Convert the updated value
p = Value->GetCharString(Valbuf);
if (strlen(p) > (unsigned)Long) {
sprintf(g->Message, MSG(VALUE_TOO_LONG), p, Name, Long);
longjmp(g->jumper[g->jump_level], 31);
} else if (Flag == 1) {
if (tdbp->Mode == MODE_UPDATE) {
strcpy(g->Message, MSG(NO_SEC_UPDATE));
longjmp(g->jumper[g->jump_level], 31);
} else {
tdbp->Section = p;
return;
} // endif Mode
} else if (Flag == 2) {
if (tdbp->Mode == MODE_UPDATE) {
strcpy(g->Message, MSG(NO_KEY_UPDATE));
longjmp(g->jumper[g->jump_level], 31);
} else {
tdbp->Keycur = p;
return;
} // endif Mode
} else if (!tdbp->Section || !tdbp->Keycur) {
strcpy(g->Message, MSG(SEC_KEY_FIRST));
longjmp(g->jumper[g->jump_level], 31);
} // endif's
/*********************************************************************/
/* Updating must be done only when not in checking pass. */
/*********************************************************************/
if (Status)
WritePrivateProfileString(tdbp->Section, tdbp->Keycur, p, tdbp->Ifile);
} // end of WriteColumn
/* ------------------------ End of System ---------------------------- */

184
storage/connect/tabsys.h Normal file
View File

@@ -0,0 +1,184 @@
/*************** TabSys H Declares Source Code File (.H) ***************/
/* Name: TABSYS.H Version 2.2 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 2004-2013 */
/* */
/* This file contains the XDB system tables classes declares. */
/***********************************************************************/
typedef class INIDEF *PINIDEF;
typedef class TDBINI *PTDBINI;
typedef class INICOL *PINICOL;
typedef class TDBXIN *PTDBXIN;
typedef class XINCOL *PXINCOL;
/* --------------------------- INI classes --------------------------- */
/***********************************************************************/
/* INI, XDB and XCL tables. */
/***********************************************************************/
class DllExport INIDEF : public TABDEF { /* INI table description */
friend class TDBINI;
friend class TDBXIN;
friend class TDBXTB;
friend class TDBRTB;
friend class TDBXCL;
public:
// Constructor
INIDEF(void);
// Implementation
virtual const char *GetType(void) {return "INI";}
// Methods
virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff);
virtual PTDB GetTable(PGLOBAL g, MODE m);
virtual bool DeleteTableFile(PGLOBAL g);
protected:
// Members
char *Fn; /* Path/Name of corresponding file */
char *Xname; /* The eventual table name */
char Subtype; /* I: INI, T: Table, C: Column */
char Layout; /* R: Row, C: Column */
int Ln; /* Length of section list buffer */
}; // end of INIDEF
/***********************************************************************/
/* This is the class declaration for the INI tables. */
/* These are tables represented by a INI like file. */
/***********************************************************************/
class TDBINI : public TDBASE {
friend class INICOL;
public:
// Constructor
TDBINI(PINIDEF tdp);
TDBINI(PTDBINI tdbp);
// Implementation
virtual AMT GetAmType(void) {return TYPE_AM_INI;}
virtual PTDB Duplicate(PGLOBAL g) {return (PTDB)new(g) TDBINI(this);}
// Methods
virtual PTDB CopyOne(PTABS t);
virtual int GetRecpos(void) {return (int)Section;}
virtual int GetProgCur(void) {return N;}
virtual int GetAffectedRows(void) {return 0;}
virtual PSZ GetFile(PGLOBAL g) {return Ifile;}
virtual void SetFile(PGLOBAL g, PSZ fn) {Ifile = fn;}
virtual void ResetDB(void) {Seclist = Section = NULL; N = 0;}
virtual void ResetSize(void) {MaxSize = -1; Seclist = NULL;}
virtual int RowNumber(PGLOBAL g, bool b = false) {return N;}
char *GetSeclist(PGLOBAL g);
// Database routines
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
virtual int GetMaxSize(PGLOBAL g);
virtual bool OpenDB(PGLOBAL g);
virtual int ReadDB(PGLOBAL g);
virtual int WriteDB(PGLOBAL g);
virtual int DeleteDB(PGLOBAL g, int irc);
virtual void CloseDB(PGLOBAL g);
protected:
// Members
char *Ifile; // The INI file
char *Seclist; // The section list
char *Section; // The current section
int Seclen; // Length of seclist buffer
int N; // The current section index
}; // end of class TDBINI
/***********************************************************************/
/* Class INICOL: XDB table access method column descriptor. */
/***********************************************************************/
class INICOL : public COLBLK {
public:
// Constructors
INICOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am = "INI");
INICOL(INICOL *colp, PTDB tdbp); // Constructor used in copy process
// Implementation
virtual int GetAmType(void) {return TYPE_AM_INI;}
virtual void SetTo_Val(PVAL valp) {To_Val = valp;}
// Methods
virtual bool SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check);
virtual void ReadColumn(PGLOBAL g);
virtual void WriteColumn(PGLOBAL g);
virtual void AllocBuf(PGLOBAL g);
protected:
// Default constructor not to be used
INICOL(void) {}
// Members
char *Valbuf; // To the key value buffer
int Flag; // Tells what set in value
int Long; // Buffer length
PVAL To_Val; // To value used for Update/Insert
}; // end of class INICOL
/* --------------------------- XINI class ---------------------------- */
/***********************************************************************/
/* This is the class declaration for the XINI tables. */
/* These are tables represented by a INI like file */
/* having 3 columns Section, Key, and Value. */
/***********************************************************************/
class TDBXIN : public TDBINI {
friend class XINCOL;
public:
// Constructor
TDBXIN(PINIDEF tdp);
TDBXIN(PTDBXIN tdbp);
// Implementation
virtual AMT GetAmType(void) {return TYPE_AM_INI;}
virtual PTDB Duplicate(PGLOBAL g) {return (PTDB)new(g) TDBXIN(this);}
// Methods
virtual PTDB CopyOne(PTABS t);
virtual int GetRecpos(void);
virtual bool SetRecpos(PGLOBAL g, int recpos);
virtual void ResetDB(void)
{Seclist = Section = Keycur = NULL; N = 0; Oldsec = -1;}
char *GetKeylist(PGLOBAL g, char *sec);
// Database routines
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
virtual int GetMaxSize(PGLOBAL g);
virtual bool OpenDB(PGLOBAL g);
virtual int ReadDB(PGLOBAL g);
virtual int WriteDB(PGLOBAL g);
virtual int DeleteDB(PGLOBAL g, int irc);
protected:
// Members
char *Keylist; // The key list
char *Keycur; // The current key
int Keylen; // Length of keylist buffer
short Oldsec; // Last current section
}; // end of class TDBXIN
/***********************************************************************/
/* Class XINCOL: XIN table access method column descriptor. */
/***********************************************************************/
class XINCOL : public INICOL {
public:
// Constructors
XINCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am = "INI");
XINCOL(XINCOL *colp, PTDB tdbp); // Constructor used in copy process
// Implementation
// Methods
virtual void ReadColumn(PGLOBAL g);
virtual void WriteColumn(PGLOBAL g);
protected:
// Default constructor not to be used
XINCOL(void) {}
// Members
}; // end of class XINICOL

777
storage/connect/tabtbl.cpp Normal file
View File

@@ -0,0 +1,777 @@
/************* TabTbl C++ Program Source Code File (.CPP) **************/
/* PROGRAM NAME: TABTBL */
/* ------------- */
/* Version 1.3 */
/* */
/* COPYRIGHT: */
/* ---------- */
/* (C) Copyright to PlugDB Software Development 2008-2012 */
/* Author: Olivier BERTRAND */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
/* This program are the TDBTBL class DB routines. */
/* */
/* WHAT YOU NEED TO COMPILE THIS PROGRAM: */
/* -------------------------------------- */
/* */
/* REQUIRED FILES: */
/* --------------- */
/* TABTBL.CPP - Source code */
/* PLGDBSEM.H - DB application declaration file */
/* TABDOS.H - TABDOS classes declaration file */
/* TABTBL.H - TABTBL classes declaration file */
/* GLOBAL.H - Global declaration file */
/* */
/* REQUIRED LIBRARIES: */
/* ------------------- */
/* Large model C library */
/* */
/* REQUIRED PROGRAMS: */
/* ------------------ */
/* IBM, Borland, GNU or Microsoft C++ Compiler and Linker */
/* */
/***********************************************************************/
/***********************************************************************/
/* Include relevant section of system dependant header files. */
/***********************************************************************/
//#include "sql_base.h"
#include "my_global.h"
#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 "table.h" // MySQL table definitions
#include "global.h" // global declarations
#include "plgdbsem.h" // DB application declarations
#include "reldef.h" // DB definition declares
//#include "filter.h" // FILTER classes dcls
#include "filamtxt.h"
#include "tabcol.h"
#include "tabdos.h" // TDBDOS and DOSCOL class dcls
#include "tabtbl.h" // TDBTBL and TBLCOL classes dcls
#include "ha_connect.h"
#include "mycat.h" // For GetHandler
extern "C" int trace;
int open_table_def(THD *thd, TABLE_SHARE *share, uint db_flags);
/* ---------------------------- Class TBLDEF ---------------------------- */
/**************************************************************************/
/* Constructor. */
/**************************************************************************/
TBLDEF::TBLDEF(void)
{
To_Tables = NULL;
Ntables = 0;
Pseudo = 3;
} // end of TBLDEF constructor
/**************************************************************************/
/* DefineAM: define specific AM block values from XDB file. */
/**************************************************************************/
bool TBLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
{
char *tablist, *dbname;
Desc = "Table list table";
tablist = Cat->GetStringCatInfo(g, Name, "Tablist", "");
dbname = Cat->GetStringCatInfo(g, Name, "Database", NULL);
Ntables = 0;
if (*tablist) {
char *p, *pn, *pdb;
PTBL *ptbl = &To_Tables, tbl;
for (pdb = tablist; ;) {
if ((p = strchr(pdb, ',')))
*p = 0;
// Analyze the table name, it has the format:
// [dbname.]tabname
if ((pn = strchr(pdb, '.'))) {
*pn++ = 0;
} else {
pn = pdb;
pdb = dbname;
} // endif p
// Allocate the TBLIST block for that table
tbl = (PTBL)PlugSubAlloc(g, NULL, sizeof(TBLIST));
tbl->Next = NULL;
tbl->Name = pn;
tbl->DB = pdb;
if (trace)
htrc("TBL: Name=%s db=%s\n", tbl->Name, SVP(tbl->DB));
// Link the blocks
*ptbl = tbl;
ptbl = &tbl->Next;
Ntables++;
if (p)
pdb = pn + strlen(pn) + 1;
else
break;
} // endfor pdb
Maxerr = Cat->GetIntCatInfo(Name, "Maxerr", 0);
Accept = (Cat->GetBoolCatInfo(Name, "Accept", 0) != 0);
} // endif fsec || tablist
return FALSE;
} // end of DefineAM
/***********************************************************************/
/* GetTable: makes a new Table Description Block. */
/***********************************************************************/
PTDB TBLDEF::GetTable(PGLOBAL g, MODE m)
{
PTDB tdbp;
/*********************************************************************/
/* Allocate a TDB of the proper type. */
/* Column blocks will be allocated only when needed. */
/*********************************************************************/
tdbp = new(g) TDBTBL(this);
return tdbp;
} // end of GetTable
/* ------------------------- Class TDBTBL ---------------------------- */
/***********************************************************************/
/* TDBTBL constructors. */
/***********************************************************************/
TDBTBL::TDBTBL(PTBLDEF tdp) : TDBASE(tdp)
{
Tablist = NULL;
CurTable = NULL;
Tdbp = NULL;
Accept = tdp->Accept;
Maxerr = tdp->Maxerr;
Nbf = 0;
Rows = 0;
Crp = 0;
// NTables = 0;
// iTable = 0;
} // end of TDBTBL standard constructor
/***********************************************************************/
/* Allocate TBL column description block. */
/***********************************************************************/
PCOL TDBTBL::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
{
return new(g) TBLCOL(cdp, this, cprec, n);
} // end of MakeCol
/***********************************************************************/
/* InsertSpecialColumn: Put a special column ahead of the column list.*/
/***********************************************************************/
PCOL TDBTBL::InsertSpecialColumn(PGLOBAL g, PCOL scp)
{
PCOL colp;
if (!scp->IsSpecial())
return NULL;
if (scp->GetAmType() == TYPE_AM_TABID)
// This special column is handled locally
colp = new((TIDBLK*)scp) TBTBLK(scp->GetValue());
else // Other special columns are treated normally
colp = scp;
colp->SetNext(Columns);
Columns = colp;
return colp;
} // end of InsertSpecialColumn
/***********************************************************************/
/* Get the PTDB of a table of the list. */
/***********************************************************************/
PTDB TDBTBL::GetSubTable(PGLOBAL g, PTBL tblp, PTABLE tabp)
{
char *db, key[128];
uint k, flags;
PTDB tdbp = NULL;
TABLE_LIST table_list;
TABLE_SHARE *s;
PCATLG cat = To_Def->GetCat();
PHC hc = ((MYCAT*)cat)->GetHandler();
THD *thd = (hc->GetTable())->in_use;
if (!thd)
return NULL; // Should not happen anymore
if (tblp->DB)
db = tblp->DB;
else
db = (char*)hc->GetDBName(NULL);
table_list.init_one_table(db, strlen(db),
tblp->Name, strlen(tblp->Name),
NULL, TL_IGNORE);
k = sprintf(key, "%s\0%s\0", db, tblp->Name);
if (!(s = alloc_table_share(&table_list, key, k))) {
strcpy(g->Message, "Error allocating share\n");
return NULL;
} // endif s
// 1 8 16
//flags = READ_ALL | DONT_OPEN_TABLES | DONT_OPEN_MASTER_REG;
//flags = 25;
flags = 24;
if (!open_table_def(thd, s, flags)) {
hc->tshp = s;
tdbp = cat->GetTable(g, tabp);
hc->tshp = NULL;
} else
sprintf(g->Message, "Error %d opening share\n", s->error);
if (trace && tdbp)
htrc("Subtable %s in %s\n",
tblp->Name, SVP(((PTDBASE)tdbp)->GetDef()->GetDB()));
free_table_share(s);
return tdbp;
} // end of GetSubTable
/***********************************************************************/
/* Initializes the table table list. */
/***********************************************************************/
bool TDBTBL::InitTableList(PGLOBAL g)
{
char *colname;
int n, colpos;
PTBL tblp;
PTABLE tabp;
PTDB tdbp;
PCOL colp;
PTBLDEF tdp = (PTBLDEF)To_Def;
// PlugSetPath(filename, Tdbp->GetFile(g), Tdbp->GetPath());
for (n = 0, tblp = tdp->GetTables(); tblp; tblp = tblp->Next) {
if (TestFil(g, To_Filter, tblp)) {
// Table or named view
tabp = new(g) XTAB(tblp->Name);
tabp->SetQualifier(tblp->DB);
// Get the table description block of this table
if (!(tdbp = GetSubTable(g, tblp, tabp))) {
if (++Nbf > Maxerr)
return TRUE; // Error return
else
continue; // Skip this table
} // endif tdbp
// We must allocate subtable columns before GetMaxSize is called
// because some (PLG, ODBC?) need to have their columns attached.
// Real initialization will be done later.
for (PCOL cp = Columns; cp; cp = cp->GetNext())
if (!cp->IsSpecial()) {
colname = cp->GetName();
colpos = ((PTBLCOL)cp)->Colnum;
// We try first to get the column by name
if (!(colp = tdbp->ColDB(g, colname, 0)) && colpos)
// When unsuccessful, if a column number was specified
// try to get the column by its position in the table
colp = tdbp->ColDB(g, NULL, colpos);
if (!colp) {
if (!Accept) {
sprintf(g->Message, MSG(NO_MATCHING_COL),
colname, tdbp->GetName());
return TRUE; // Error return
} // endif !Accept
} else // this is needed in particular by PLG tables
colp->SetColUse(cp->GetColUse());
} // endif !special
if (Tablist)
Tablist->Link(tabp);
else
Tablist = tabp;
n++;
} // endif filp
} // endfor tblp
//NumTables = n;
To_Filter = NULL; // To avoid doing it several times
return FALSE;
} // end of InitTableList
/***********************************************************************/
/* Test the tablename against the pseudo "local" filter. */
/***********************************************************************/
bool TDBTBL::TestFil(PGLOBAL g, PFIL filp, PTBL tblp)
{
char *fil, op[8], tn[NAME_LEN];
bool neg;
if (!filp)
return TRUE;
else if (strstr(filp, " OR ") || strstr(filp, " AND "))
return TRUE; // Not handled yet
else
fil = filp + (*filp == '(' ? 1 : 0);
if (sscanf(fil, "TABID %s", op) != 1)
return TRUE; // ignore invalid filter
if ((neg = !strcmp(op, "NOT")))
strcpy(op, "IN");
if (!strcmp(op, "=")) {
// Temporarily, filter must be "TABID = 'value'" only
if (sscanf(fil, "TABID = '%[^']'", tn) != 1)
return TRUE; // ignore invalid filter
return !stricmp(tn, tblp->Name);
} else if (!strcmp(op, "IN")) {
char *p, *tnl = (char*)PlugSubAlloc(g, NULL, strlen(fil) - 10);
int n;
if (neg)
n = sscanf(fil, "TABID NOT IN (%[^)])", tnl);
else
n = sscanf(fil, "TABID IN (%[^)])", tnl);
if (n != 1)
return TRUE; // ignore invalid filter
while (tnl) {
if ((p = strchr(tnl, ',')))
*p++ = 0;
if (sscanf(tnl, "'%[^']'", tn) != 1)
return TRUE; // ignore invalid filter
else if (!stricmp(tn, tblp->Name))
return !neg; // Found
tnl = p;
} // endwhile
return neg; // Not found
} // endif op
return TRUE; // invalid operator
} // end of TestFil
/***********************************************************************/
/* TBL GetProgMax: get the max value for progress information. */
/***********************************************************************/
int TDBTBL::GetProgMax(PGLOBAL g)
{
PTABLE tblp;
int n, pmx = 0;
if (!Tablist && InitTableList(g))
return -1;
for (tblp = Tablist; tblp; tblp = tblp->GetNext())
if ((n = tblp->GetTo_Tdb()->GetProgMax(g)) > 0)
pmx += n;
return pmx;
} // end of GetProgMax
/***********************************************************************/
/* TBL GetProgCur: get the current value for progress information. */
/***********************************************************************/
int TDBTBL::GetProgCur(void)
{
return Crp + Tdbp->GetProgCur();
} // end of GetProgCur
#if 0
/***********************************************************************/
/* TBL Cardinality: returns table cardinality in number of rows. */
/* This function can be called with a null argument to test the */
/* availability of Cardinality implementation (1 yes, 0 no). */
/* Can be used on Multiple FIX table only. */
/***********************************************************************/
int TDBTBL::Cardinality(PGLOBAL g)
{
if (!g)
return Tdbp->Cardinality(g);
if (!Tablist && InitTableList(g))
return -1;
int n, card = 0;
for (int i = 0; i < NumFiles; i++) {
Tdbp->SetFile(g, Filenames[i]);
Tdbp->ResetSize();
if ((n = Tdbp->Cardinality(g)) < 0) {
// strcpy(g->Message, MSG(BAD_CARDINALITY));
return -1;
} // endif n
card += n;
} // endfor i
return card;
} // end of Cardinality
#endif // 0
/***********************************************************************/
/* Sum up the sizes of all sub-tables. */
/***********************************************************************/
int TDBTBL::GetMaxSize(PGLOBAL g)
{
if (MaxSize < 0) {
PTABLE tblp;
int mxsz;
if (!Tablist && InitTableList(g))
return 0; // Cannot be calculated at this stage
// if (Use == USE_OPEN) {
// strcpy(g->Message, MSG(MAXSIZE_ERROR));
// return -1;
// } else
MaxSize = 0;
for (tblp = Tablist; tblp; tblp = tblp->GetNext()) {
if ((mxsz = tblp->GetTo_Tdb()->GetMaxSize(g)) < 0) {
MaxSize = -1;
return mxsz;
} // endif mxsz
MaxSize += mxsz;
} // endfor i
} // endif MaxSize
return MaxSize;
} // end of GetMaxSize
/***********************************************************************/
/* Reset read/write position values. */
/***********************************************************************/
void TDBTBL::ResetDB(void)
{
for (PCOL colp = Columns; colp; colp = colp->GetNext())
if (colp->GetAmType() == TYPE_AM_TABID)
colp->COLBLK::Reset();
for (PTABLE tblp = Tablist; tblp; tblp = tblp->GetNext())
((PTDBASE)tblp->GetTo_Tdb())->ResetDB();
Tdbp = (PTDBASE)Tablist->GetTo_Tdb();
Crp = 0;
} // end of ResetDB
/***********************************************************************/
/* Returns RowId if b is false or Rownum if b is true. */
/***********************************************************************/
int TDBTBL::RowNumber(PGLOBAL g, bool b)
{
return Tdbp->RowNumber(g) + ((b) ? 0 : Rows);
} // end of RowNumber
/***********************************************************************/
/* TBL Access Method opening routine. */
/* Open first file, other will be opened sequencially when reading. */
/***********************************************************************/
bool TDBTBL::OpenDB(PGLOBAL g)
{
if (trace)
htrc("TBL OpenDB: tdbp=%p tdb=R%d use=%d key=%p mode=%d\n",
this, Tdb_No, Use, To_Key_Col, Mode);
if (Use == USE_OPEN) {
/*******************************************************************/
/* Table already open, replace it at its beginning. */
/*******************************************************************/
ResetDB();
return Tdbp->OpenDB(g); // Re-open fist table
} // endif use
#if 0
/*********************************************************************/
/* Direct access needed for join or sorting. */
/*********************************************************************/
if (NeedIndexing(g)) {
// Direct access of TBL tables is not implemented yet
strcpy(g->Message, MSG(NO_MUL_DIR_ACC));
return TRUE;
} // endif NeedIndexing
#endif // 0
/*********************************************************************/
/* When GetMaxsize was called, To_Filter was not set yet. */
/*********************************************************************/
if (To_Filter && Tablist) {
Tablist = NULL;
Nbf = 0;
} // endif To_Filter
/*********************************************************************/
/* Open the first table of the list. */
/*********************************************************************/
if (!Tablist && InitTableList(g)) // done in GetMaxSize
return TRUE;
if ((CurTable = Tablist)) {
Tdbp = (PTDBASE)CurTable->GetTo_Tdb();
Tdbp->SetMode(Mode);
// Tdbp->ResetDB();
// Tdbp->ResetSize();
// Check and initialize the subtable columns
for (PCOL cp = Columns; cp; cp = cp->GetNext())
if (cp->GetAmType() == TYPE_AM_TABID)
cp->COLBLK::Reset();
else if (((PTBLCOL)cp)->Init(g))
return TRUE;
if (trace)
htrc("Opening subtable %s\n", Tdbp->GetName());
// Now we can safely open the table
if (Tdbp->OpenDB(g))
return TRUE;
} // endif *Tablist
Use = USE_OPEN;
return FALSE;
} // end of OpenDB
/***********************************************************************/
/* ReadDB: Data Base read routine for MUL access method. */
/***********************************************************************/
int TDBTBL::ReadDB(PGLOBAL g)
{
int rc;
if (!CurTable)
return RC_EF;
else if (To_Kindex) {
/*******************************************************************/
/* Reading is by an index table. */
/*******************************************************************/
strcpy(g->Message, MSG(NO_INDEX_READ));
rc = RC_FX;
} else {
/*******************************************************************/
/* Now start the reading process. */
/*******************************************************************/
retry:
rc = Tdbp->ReadDB(g);
if (rc == RC_EF) {
// Total number of rows met so far
Rows += Tdbp->RowNumber(g) - 1;
Crp += Tdbp->GetProgMax(g);
if ((CurTable = CurTable->GetNext())) {
/***************************************************************/
/* Continue reading from next table file. */
/***************************************************************/
Tdbp->CloseDB(g);
Tdbp = (PTDBASE)CurTable->GetTo_Tdb();
// Check and initialize the subtable columns
for (PCOL cp = Columns; cp; cp = cp->GetNext())
if (cp->GetAmType() == TYPE_AM_TABID)
cp->COLBLK::Reset();
else if (((PTBLCOL)cp)->Init(g))
return RC_FX;
if (trace)
htrc("Opening subtable %s\n", Tdbp->GetName());
// Now we can safely open the table
if (Tdbp->OpenDB(g)) // Open next table
return RC_FX;
goto retry;
} // endif iFile
} else if (rc == RC_FX)
strcat(strcat(strcat(g->Message, " ("), Tdbp->GetName()), ")");
} // endif To_Kindex
return rc;
} // end of ReadDB
/***********************************************************************/
/* Data Base write routine for MUL access method. */
/***********************************************************************/
int TDBTBL::WriteDB(PGLOBAL g)
{
strcpy(g->Message, MSG(TABMUL_READONLY));
return RC_FX; // NIY
} // end of WriteDB
/***********************************************************************/
/* Data Base delete line routine for MUL access method. */
/***********************************************************************/
int TDBTBL::DeleteDB(PGLOBAL g, int irc)
{
strcpy(g->Message, MSG(TABMUL_READONLY));
return RC_FX; // NIY
} // end of DeleteDB
/***********************************************************************/
/* Data Base close routine for MUL access method. */
/***********************************************************************/
void TDBTBL::CloseDB(PGLOBAL g)
{
if (Tdbp)
Tdbp->CloseDB(g);
} // end of CloseDB
/* ---------------------------- TBLCOL ------------------------------- */
/***********************************************************************/
/* TBLCOL public constructor. */
/***********************************************************************/
TBLCOL::TBLCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am)
: COLBLK(cdp, tdbp, i)
{
if (cprec) {
Next = cprec->GetNext();
cprec->SetNext(this);
} else {
Next = tdbp->GetColumns();
tdbp->SetColumns(this);
} // endif cprec
// Set additional Dos access method information for column.
Long = cdp->GetLong(); // ???
//strcpy(F_Date, cdp->F_Date);
Colp = NULL;
To_Val = NULL;
Pseudo = FALSE;
Colnum = cdp->GetOffset(); // If columns are retrieved by number
if (trace)
htrc(" making new %sCOL C%d %s at %p\n", am, Index, Name, this);
} // end of TBLCOL constructor
#if 0
/***********************************************************************/
/* TBLCOL public constructor. */
/***********************************************************************/
TBLCOL::TBLCOL(SPCBLK *scp, PTDB tdbp) : COLBLK(scp->GetName(), tdbp, 0)
{
// Set additional TBL access method information for pseudo column.
Is_Key = Was_Key = scp->IsKey();
Long = scp->GetLength();
Buf_Type = scp->GetResultType();
*Format.Type = (Buf_Type == TYPE_INT) ? 'N' : 'C';
Format.Length = Long;
Colp = NULL;
To_Val = NULL;
Pseudo = TRUE;
} // end of TBLCOL constructor
/***********************************************************************/
/* TBLCOL constructor used for copying columns. */
/* tdbp is the pointer to the new table descriptor. */
/***********************************************************************/
TBLCOL::TBLCOL(TBLCOL *col1, PTDB tdbp) : COLBLK(col1, tdbp)
{
Long = col1->Long;
Colp = col1->Colp;
To_Val = col1->To_Val;
Pseudo = col1->Pseudo;
} // end of TBLCOL copy constructor
#endif
/***********************************************************************/
/* TBLCOL initialization routine. */
/* Look for the matching column in the current table. */
/***********************************************************************/
bool TBLCOL::Init(PGLOBAL g)
{
PTDBTBL tdbp = (PTDBTBL)To_Tdb;
To_Val = NULL;
if (!(Colp = tdbp->Tdbp->ColDB(g, Name, 0)) && Colnum)
Colp = tdbp->Tdbp->ColDB(g, NULL, Colnum);
if (Colp) {
Colp->InitValue(g); // May not have been done elsewhere
To_Val = Colp->GetValue();
} else if (!tdbp->Accept) {
sprintf(g->Message, MSG(NO_MATCHING_COL), Name, tdbp->Tdbp->GetName());
return TRUE;
} else
Value->Reset();
return FALSE;
} // end of Init
/***********************************************************************/
/* ReadColumn: */
/***********************************************************************/
void TBLCOL::ReadColumn(PGLOBAL g)
{
if (trace)
htrc("TBL ReadColumn: name=%s\n", Name);
if (Colp) {
Colp->ReadColumn(g);
Value->SetValue_pval(To_Val);
} // endif Colp
} // end of ReadColumn
/* ---------------------------- TBTBLK ------------------------------- */
/***********************************************************************/
/* ReadColumn: */
/***********************************************************************/
void TBTBLK::ReadColumn(PGLOBAL g)
{
if (trace)
htrc("TBT ReadColumn: name=%s\n", Name);
Value->SetValue_psz((char*)((PTDBTBL)To_Tdb)->Tdbp->GetName());
} // end of ReadColumn
/* ------------------------------------------------------------------- */

162
storage/connect/tabtbl.h Normal file
View File

@@ -0,0 +1,162 @@
/*************** TabTbl H Declares Source Code File (.H) ***************/
/* Name: TABTBL.H Version 1.2 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 2008-2012 */
/* */
/* This file contains the TDBTBL classes declares. */
/***********************************************************************/
//#include "osutil.h"
#include "block.h"
#include "colblk.h"
typedef class TBLDEF *PTBLDEF;
typedef class TDBTBL *PTDBTBL;
typedef class TBLCOL *PTBLCOL;
/***********************************************************************/
/* Defines the structure used for multiple tables. */
/***********************************************************************/
typedef struct _tablist *PTBL;
typedef struct _tablist {
PTBL Next;
char *Name;
char *DB;
} TBLIST;
/***********************************************************************/
/* TBL table. */
/***********************************************************************/
class DllExport TBLDEF : public TABDEF { /* Logical table description */
friend class TDBTBL;
public:
// Constructor
TBLDEF(void);
// Implementation
virtual const char *GetType(void) {return "TBL";}
PTBL GetTables(void) {return To_Tables;}
//int GetNtables(void) {return Ntables;}
// Methods
virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff);
virtual PTDB GetTable(PGLOBAL g, MODE m);
protected:
// Members
PTBL To_Tables; /* To the list of tables */
bool Accept; /* TRUE if bad tables are accepted */
int Maxerr; /* Maximum number of bad tables */
int Ntables; /* Number of tables */
}; // end of TBLDEF
/***********************************************************************/
/* This is the TBL Access Method class declaration. */
/***********************************************************************/
class DllExport TDBTBL : public TDBASE {
friend class TBLCOL;
friend class TBTBLK;
friend class TDBPLG;
public:
// Constructor
TDBTBL(PTBLDEF tdp = NULL);
//TDBTBL(PTDBTBL tdbp);
// Implementation
virtual AMT GetAmType(void) {return TYPE_AM_TBL;}
//virtual PTDB Duplicate(PGLOBAL g)
// {return (PTDB)new(g) TDBTBL(this);}
// Methods
virtual void ResetDB(void);
//virtual PTABLE GetTablist(void) {return (PSZ)Tablist;}
//virtual PTDB CopyOne(PTABS t);
virtual int GetRecpos(void) {return Rows;}
virtual int GetBadLines(void) {return (int)Nbf;}
// Database routines
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
virtual int GetMaxSize(PGLOBAL g);
virtual int GetProgMax(PGLOBAL g);
virtual int GetProgCur(void);
virtual int RowNumber(PGLOBAL g, bool b = FALSE);
virtual PCOL InsertSpecialColumn(PGLOBAL g, PCOL scp);
virtual bool OpenDB(PGLOBAL g);
virtual int ReadDB(PGLOBAL g);
virtual int WriteDB(PGLOBAL g);
virtual int DeleteDB(PGLOBAL g, int irc);
virtual void CloseDB(PGLOBAL g);
protected:
// Internal functions
PTDB GetSubTable(PGLOBAL g, PTBL tblp, PTABLE tabp);
bool InitTableList(PGLOBAL g);
bool TestFil(PGLOBAL g, PFIL filp, PTBL tblp);
// Members
PTABLE Tablist; // Points to the table list
PTABLE CurTable; // Points to the current table
PTDBASE Tdbp; // Current table PTDB
bool Accept; // TRUE if bad tables are accepted
int Maxerr; // Maximum number of bad tables
int Nbf; // Number of bad connections
int Rows; // Used for RowID
int Crp; // Used for CurPos
}; // end of class TDBTBL
/***********************************************************************/
/* Class TBLCOL: TBL access method column descriptor. */
/* This A.M. is used for TBL tables. */
/***********************************************************************/
class DllExport TBLCOL : public COLBLK {
friend class TDBTBL;
public:
// Constructors
TBLCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am = "TBL");
TBLCOL(TBLCOL *colp, PTDB tdbp); // Constructor used in copy process
//TBLCOL(SPCBLK *colp, PTDB tdbp); // Constructor used for pseudo columns
// Implementation
virtual int GetAmType(void) {return TYPE_AM_TBL;}
// Methods
virtual bool IsSpecial(void) {return Pseudo;}
virtual void ReadColumn(PGLOBAL g);
//virtual void WriteColumn(PGLOBAL g);
// void Print(PGLOBAL g, FILE *, UINT);
bool Init(PGLOBAL g);
protected:
// Default constructor not to be used
TBLCOL(void) {}
// Members
PCOL Colp; // Points to matching table column
PVAL To_Val; // To the matching column value
bool Pseudo; // TRUE for special columns
int Colnum; // Used when retrieving columns by number
}; // end of class TBLCOL
/***********************************************************************/
/* Class TBTBLK: TDBPLG TABID special column descriptor. */
/***********************************************************************/
class TBTBLK : public TIDBLK {
public:
// The constructor must restore Value because XOBJECT has a void
// constructor called by default that set Value to NULL
TBTBLK(PVAL valp) {Value = valp;}
// Methods
virtual void ReadColumn(PGLOBAL g);
// Fake operator new used to change TIDBLK into SDTBLK
void * operator new(size_t size, TIDBLK *sp) {return sp;}
#if !defined(__BORLANDC__)
// Avoid warning C4291 by defining a matching dummy delete operator
void operator delete(void *, TIDBLK*) {}
#endif
protected:
// Must not have additional members
}; // end of class TBTBLK

563
storage/connect/tabvct.cpp Normal file
View File

@@ -0,0 +1,563 @@
/************* TabVct C++ Program Source Code File (.CPP) **************/
/* PROGRAM NAME: TABVCT */
/* ------------- */
/* Version 3.7 */
/* */
/* COPYRIGHT: */
/* ---------- */
/* (C) Copyright to the author Olivier BERTRAND 1999-2012 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
/* This is the TDBVCT and VCTCOL classes implementation routines. */
/* */
/* WHAT YOU NEED TO COMPILE THIS PROGRAM: */
/* -------------------------------------- */
/* */
/* REQUIRED FILES: */
/* --------------- */
/* TABVCT.C - Source code */
/* PLGDBSEM.H - DB application declaration file */
/* TABDOS.H - TABDOS classes declaration file */
/* GLOBAL.H - Global declaration file */
/* */
/* REQUIRED LIBRARIES: */
/* ------------------- */
/* Large model C library */
/* */
/* REQUIRED PROGRAMS: */
/* ------------------ */
/* IBM, Borland, GNU or Microsoft C++ Compiler and Linker */
/* */
/***********************************************************************/
/***********************************************************************/
/* Include relevant MariaDB header file. */
/***********************************************************************/
#include "my_global.h"
#if defined(WIN32)
#include <io.h>
#include <fcntl.h>
#if defined(__BORLANDC__)
#define __MFC_COMPAT__ // To define min/max as macro
#endif
//#include <windows.h>
#include <sys/stat.h>
#else
#if defined(UNIX)
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
//#define strerror(X) _strerror(X)
#define NO_ERROR 0
#else
#include <io.h>
#endif
#include <fcntl.h>
#endif
/***********************************************************************/
/* Include application header files: */
/* global.h is header containing all global declarations. */
/* plgdbsem.h is header containing the DB application declarations. */
/* tabdos.h is header containing the TABDOS class declarations. */
/***********************************************************************/
#include "global.h"
#include "plgdbsem.h"
#include "reldef.h"
#include "osutil.h"
#include "filamvct.h"
#include "tabdos.h"
#include "tabvct.h"
#include "valblk.h"
#if defined(UNIX)
//add dummy strerror (NGC)
char *strerror(int num);
#endif // UNIX
/***********************************************************************/
/* Char VCT column blocks are right filled with blanks (blank = true) */
/* Conversion of block values allowed conditionally for insert only. */
/***********************************************************************/
PVBLK AllocValBlock(PGLOBAL, void *, int, int, int, int,
bool check = true, bool blank = true);
/* --------------------------- Class VCTDEF -------------------------- */
/***********************************************************************/
/* DefineAM: define specific AM block values from XDB file. */
/***********************************************************************/
bool VCTDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
{
DOSDEF::DefineAM(g, "BIN", poff);
Estimate = Cat->GetIntCatInfo(Name, "Estimate", 0);
Split = Cat->GetIntCatInfo(Name, "Split", (Estimate) ? 0 : 1);
Header = Cat->GetIntCatInfo(Name, "Header", 0);
// CONNECT must have Block/Last info for VEC tables
if (Estimate && !Split && !Header)
Header = 2;
Recfm = RECFM_VCT;
// For packed files the logical record length is calculated in poff
if (poff != Lrecl) {
Lrecl = poff;
Cat->SetIntCatInfo(Name, "Lrecl", poff);
} // endif poff
Padded = false;
Blksize = 0;
return false;
} // end of DefineAM
/***********************************************************************/
/* Erase: This was made a separate routine because a strange thing */
/* happened when DeleteTablefile was defined for the VCTDEF class: */
/* when called from Catalog, the DOSDEF routine was still called even */
/* for a VCTDEF class. It also minimizes the specific code. */
/***********************************************************************/
bool VCTDEF::Erase(char *filename)
{
bool rc = false;
if (Split) {
char fpat[_MAX_PATH];
int i;
PCOLDEF cdp;
MakeFnPattern(fpat);
for (i = 1, cdp = To_Cols; cdp; i++, cdp = cdp->GetNext()) {
sprintf(filename, fpat, i);
//#if defined(WIN32)
// rc |= !DeleteFile(filename);
//#else // UNIX
rc |= remove(filename);
//#endif // UNIX
} // endfor cdp
} else {
rc = DOSDEF::Erase(filename);
if (Estimate && Header == 2) {
PlugSetPath(filename, Fn, GetPath());
strcat(PlugRemoveType(filename, filename), ".blk");
rc |= remove(filename);
} // endif Header
} // endif Split
return rc; // Return true if error
} // end of Erase
/***********************************************************************/
/* Prepare the column file name pattern for a split table. */
/* This function returns the number of columns of the table. */
/***********************************************************************/
int VCTDEF::MakeFnPattern(char *fpat)
{
char pat[8];
#if !defined(UNIX)
char drive[_MAX_DRIVE];
#else
char *drive = NULL;
#endif
char direc[_MAX_DIR];
char fname[_MAX_FNAME];
char ftype[_MAX_EXT]; // File extention
int n, m, ncol = 0;
PCOLDEF cdp;
for (cdp = To_Cols; cdp; cdp = cdp->GetNext())
ncol++;
for (n = 1, m = ncol; m /= 10; n++) ;
sprintf(pat, "%%0%dd", n);
_splitpath(Fn, drive, direc, fname, ftype);
strcat(fname, pat);
_makepath(fpat, drive, direc, fname, ftype);
PlugSetPath(fpat, fpat, GetPath());
return ncol;
} // end of MakeFnPattern
/***********************************************************************/
/* GetTable: makes a new Table Description Block. */
/***********************************************************************/
PTDB VCTDEF::GetTable(PGLOBAL g, MODE mode)
{
/*********************************************************************/
/* Allocate a TDB of the proper type. */
/* Column blocks will be allocated only when needed. */
/*********************************************************************/
// Mapping not used for insert (except for true VEC not split tables)
// or when UseTemp is forced
bool map = Mapped && (Estimate || mode != MODE_INSERT) &&
!(PlgGetUser(g)->UseTemp == TMP_FORCE &&
(mode == MODE_UPDATE || mode == MODE_DELETE));
PTXF txfp;
PTDB tdbp;
if (Multiple) {
strcpy(g->Message, MSG(NO_MUL_VCT));
return NULL;
} // endif Multiple
if (Split) {
if (map)
txfp = new(g) VMPFAM(this);
else
txfp = new(g) VECFAM(this);
} else if (Huge)
txfp = new(g) BGVFAM(this);
else if (map)
txfp = new(g) VCMFAM(this);
else
txfp = new(g) VCTFAM(this);
tdbp = new(g) TDBVCT(this, txfp);
/*********************************************************************/
/* For block tables, get eventually saved optimization values. */
/*********************************************************************/
if (mode != MODE_INSERT)
if (tdbp->GetBlockValues(g))
return NULL;
return tdbp;
} // end of GetTable
/* --------------------------- Class TDBVCT -------------------------- */
/***********************************************************************/
/* Implementation of the TDBVCT class. */
/***********************************************************************/
TDBVCT::TDBVCT(PVCTDEF tdp, PTXF txfp) : TDBFIX(tdp, txfp)
{
To_SetCols = NULL;
} // end of TDBVCT standard constructor
TDBVCT::TDBVCT(PGLOBAL g, PTDBVCT tdbp) : TDBFIX(g, tdbp)
{
To_SetCols = tdbp->To_SetCols;
} // end of TDBVCT copy constructor
// Method
PTDB TDBVCT::CopyOne(PTABS t)
{
PTDB tp;
PVCTCOL cp1, cp2;
PGLOBAL g = t->G; // Is this really useful ???
tp = new(g) TDBVCT(g, this);
for (cp1 = (PVCTCOL)Columns; cp1; cp1 = (PVCTCOL)cp1->Next) {
cp2 = new(g) VCTCOL(cp1, tp); // Make a copy
NewPointer(t, cp1, cp2);
} // endfor cp1
return tp;
} // end of CopyOne
/***********************************************************************/
/* Allocate VCT column description block. */
/***********************************************************************/
PCOL TDBVCT::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
{
return new(g) VCTCOL(g, cdp, this, cprec, n);
} // end of MakeCol
/***********************************************************************/
/* VCT Access Method opening routine. */
/* New method now that this routine is called recursively (last table */
/* first in reverse order): index blocks are immediately linked to */
/* join block of next table if it exists or else are discarted. */
/***********************************************************************/
bool TDBVCT::OpenDB(PGLOBAL g)
{
#ifdef DEBTRACE
htrc("VCT OpenDB: tdbp=%p tdb=R%d use=%d key=%p mode=%d\n",
this, Tdb_No, Use, To_Key_Col, Mode);
#endif
if (Use == USE_OPEN) {
/*******************************************************************/
/* Table already open, just replace it at its beginning. */
/*******************************************************************/
if (To_Kindex)
// Table is to be accessed through a sorted index table
To_Kindex->Reset();
Txfp->Rewind();
return false;
} // endif Use
/*********************************************************************/
/* Insert is not handled using file mapping. */
/*********************************************************************/
if (Mode == MODE_INSERT && !((PVCTDEF)To_Def)->GetEstimate() &&
Txfp->GetAmType() == TYPE_AM_VMP) {
if (!((PVCTFAM)Txfp)->Split) {
Txfp = new(g) VCTFAM((PVCTDEF)To_Def);
Txfp->SetTdbp(this);
} else {
Txfp = new(g) VECFAM((PVCTDEF)To_Def);
Txfp->SetTdbp(this);
} // endif Split
} // endif Mode
/*********************************************************************/
/* Open according to input/output mode required and */
/* allocate the block buffers for columns used in the query. */
/*********************************************************************/
if (Txfp->OpenTableFile(g))
return true;
// This was not done in previous version
Use = USE_OPEN; // Do it now in case we are recursively called
/*********************************************************************/
/* Reset buffer access according to indexing and to mode. */
/*********************************************************************/
Txfp->ResetBuffer(g);
return false;
} // end of OpenDB
/***********************************************************************/
/* Data Base read routine for VCT access method. */
/* This routine just set the new block index and record position. */
/* For index accessed tables the physical reading is deferred to the */
/* ReadColumn routine so only really used column are physically read. */
/***********************************************************************/
int TDBVCT::ReadDB(PGLOBAL g)
{
#ifdef DEBTRACE
fprintf(debug,
"VCT ReadDB: R%d Mode=%d CurBlk=%d CurNum=%d key=%p link=%p Kindex=%p\n",
GetTdb_No(), Mode, Txfp->CurBlk, Txfp->CurNum,
To_Key_Col, To_Link, To_Kindex);
#endif
if (To_Kindex) {
/*******************************************************************/
/* Reading is by an index table. */
/*******************************************************************/
int recpos = To_Kindex->Fetch(g);
switch (recpos) {
case -1: // End of file reached
return RC_EF;
case -2: // No match for join
return RC_NF;
case -3: // Same record as last non null one
// num_there++;
return RC_OK;
default:
/***************************************************************/
/* Set the file position according to record to read. */
/***************************************************************/
if (SetRecpos(g, recpos))
return RC_FX;
} // endswitch recpos
} // endif To_Kindex
return ReadBuffer(g);
} // end of ReadDB
/***********************************************************************/
/* Data Base close routine for VEC access method. */
/***********************************************************************/
void TDBVCT::CloseDB(PGLOBAL g)
{
if (To_Kindex) {
To_Kindex->Close();
To_Kindex = NULL;
} // endif
Txfp->CloseTableFile(g);
} // end of CloseDB
// ------------------------ VCTCOL functions ----------------------------
/***********************************************************************/
/* VCTCOL public constructor. */
/***********************************************************************/
VCTCOL::VCTCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i)
: DOSCOL(g, cdp, tdbp, cprec, i, "VCT")
{
Deplac = cdp->GetPoff();
Clen = cdp->GetClen(); // Length of the field in the file
ColBlk = -1;
ColPos = -1;
Blk = NULL;
Modif = 0;
} // end of VCTCOL constructor
/***********************************************************************/
/* VCTCOL constructor used for copying columns. */
/* tdbp is the pointer to the new table descriptor. */
/***********************************************************************/
VCTCOL::VCTCOL(VCTCOL *col1, PTDB tdbp) : DOSCOL(col1, tdbp)
{
ColBlk = col1->ColBlk;
ColPos = col1->ColPos;
Blk = col1->Blk; // Should be NULL when copying ????
Modif = col1->Modif; // Should be 0 ????
} // end of VCTCOL copy constructor
/***********************************************************************/
/* SetBuffer: allocate and set the buffers needed for write operation.*/
/***********************************************************************/
bool VCTCOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check)
{
// Eventual conversion will be done when setting ValBlk from Value.
Value = value; // Force To_Val == Value
if (DOSCOL::SetBuffer(g, value, ok, check))
return true;
if (To_Tdb->GetMode() != MODE_INSERT) {
// Allocate the block buffer to use for read/writing except when
// updating a mapped VCT table and Ok is true.
PTDBVCT tdbp = (PTDBVCT)To_Tdb;
if (tdbp->Txfp->GetAmType() == TYPE_AM_VMP && ok) {
Blk = AllocValBlock(g, (void*)1, Buf_Type, tdbp->Txfp->Nrec,
Format.Length,
Format.Prec, check);
Status |= BUF_MAPPED; // Will point into mapped file
} else
Blk = AllocValBlock(g, NULL, Buf_Type, tdbp->Txfp->Nrec,
Format.Length,
Format.Prec, check);
} // endif Mode
return false;
} // end of SetBuffer
/***********************************************************************/
/* ReadBlock: Indicate it is Ok to make updates. */
/***********************************************************************/
void VCTCOL::SetOk(void)
{
if (((PTDBVCT)To_Tdb)->Txfp->GetAmType() == TYPE_AM_VMP)
Status |= BUF_MAPPED;
Status |= BUF_EMPTY;
Modif = 0;
} // end of SetOk
/***********************************************************************/
/* ReadBlock: Read column values from current block. */
/***********************************************************************/
void VCTCOL::ReadBlock(PGLOBAL g)
{
PVCTFAM txfp = (PVCTFAM)((PTDBVCT)To_Tdb)->Txfp;
#if defined(_DEBUG)
if (!Blk) {
strcpy(g->Message, MSG(TO_BLK_IS_NULL));
longjmp(g->jumper[g->jump_level], 58);
} // endif
#endif
/*********************************************************************/
/* Read column block according to used access method. */
/*********************************************************************/
if (txfp->ReadBlock(g, this))
longjmp(g->jumper[g->jump_level], 6);
ColBlk = txfp->CurBlk;
ColPos = -1; // Any invalid position
} // end of ReadBlock
/***********************************************************************/
/* WriteBlock: Write back current column values for one block. */
/* Note: the test of Status is meant to prevent physical writing of */
/* the block during the checking loop in mode Update. It is set to */
/* BUF_EMPTY when reopening the table between the two loops. */
/***********************************************************************/
void VCTCOL::WriteBlock(PGLOBAL g)
{
if (Modif && (Status & BUF_EMPTY)) {
PVCTFAM txfp = (PVCTFAM)((PTDBVCT)To_Tdb)->Txfp;
#if defined(_DEBUG)
if (!Blk) {
strcpy(g->Message, MSG(BLK_IS_NULL));
longjmp(g->jumper[g->jump_level], 56);
} // endif
#endif
/*******************************************************************/
/* Write column block according to used access method. */
/*******************************************************************/
if (txfp->WriteBlock(g, this))
longjmp(g->jumper[g->jump_level], 6);
Modif = 0;
} // endif Modif
} // end of WriteBlock
/***********************************************************************/
/* ReadColumn: what this routine does is to check whether a column */
/* block has been read from the file, then to extract from it the */
/* field corresponding to this column and convert it to buffer type. */
/***********************************************************************/
void VCTCOL::ReadColumn(PGLOBAL g)
{
PTXF txfp = ((PTDBVCT)To_Tdb)->Txfp;
#if defined(_DEBUG) || defined(DEBTRACE)
assert (!To_Kcol);
#endif
#ifdef DEBTRACE
fprintf(debug,
"VCT ReadColumn: col %s R%d coluse=%.4X status=%.4X buf_type=%d\n",
Name, To_Tdb->GetTdb_No(), ColUse, Status, Buf_Type);
#endif
if (ColBlk != txfp->CurBlk)
ReadBlock(g);
else if (ColPos == txfp->CurNum)
return; // Value is already there
//ColBlk = txfp->CurBlk; done in ReadBlock
ColPos = txfp->CurNum;
Value->SetValue_pvblk(Blk, ColPos);
} // end of ReadColumn
/***********************************************************************/
/* WriteColumn: Modifications are written back into column buffer. */
/* On each change of block the buffer is written back to file and */
/* in mode Insert the buffer is filled with the block to update. */
/***********************************************************************/
void VCTCOL::WriteColumn(PGLOBAL g)
{
PTXF txfp = ((PTDBVCT)To_Tdb)->Txfp;;
#ifdef DEBTRACE
fprintf(debug,
"VCT WriteColumn: col %s R%d coluse=%.4X status=%.4X buf_type=%d\n",
Name, To_Tdb->GetTdb_No(), ColUse, Status, Buf_Type);
#endif
ColBlk = txfp->CurBlk;
ColPos = txfp->CurNum;
Blk->SetValue(Value, ColPos);
Modif++;
} // end of WriteColumn
/* ------------------------ End of TabVct ---------------------------- */

123
storage/connect/tabvct.h Normal file
View File

@@ -0,0 +1,123 @@
/*************** TabVct H Declares Source Code File (.H) ***************/
/* Name: TABVCT.H Version 3.4 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 1999-2011 */
/* */
/* This file contains the TDBVCT class declares. */
/***********************************************************************/
#ifndef __TABVCT__
#define __TABVCT__
#include "tabfix.h"
#if defined(UNIX)
//#include <string.h.SUNWCCh>
#endif
typedef class TDBVCT *PTDBVCT;
typedef class VCTCOL *PVCTCOL;
/***********************************************************************/
/* VCT table. */
/***********************************************************************/
class DllExport VCTDEF : public DOSDEF { /* Logical table description */
friend class VCTFAM;
friend class VECFAM;
friend class VMPFAM;
public:
// Constructor
VCTDEF(void) {Split = Estimate = Header = 0;}
// Implementation
virtual const char *GetType(void) {return "VCT";}
int GetEstimate(void) {return Estimate;}
// Methods
virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff);
virtual PTDB GetTable(PGLOBAL g, MODE mode);
protected:
// Specific file erase routine for vertical tables
virtual bool Erase(char *filename);
int MakeFnPattern(char *fpat);
// Members
int Split; /* Columns in separate files */
int Estimate; /* Estimated maximum size of table */
int Header; /* 0: no, 1: separate, 2: in data file */
}; // end of VCTDEF
/***********************************************************************/
/* This is the DOS/UNIX Access Method class declaration for files */
/* in blocked vector format. In each block containing "Elements" */
/* records, values of each columns are consecutively stored (vector). */
/***********************************************************************/
class DllExport TDBVCT : public TDBFIX {
friend class VCTCOL;
friend class VCTFAM;
friend class VCMFAM;
friend class VECFAM;
friend class VMPFAM;
public:
// Constructors
TDBVCT(PVCTDEF tdp, PTXF txfp);
TDBVCT(PGLOBAL g, PTDBVCT tdbp);
// Implementation
virtual AMT GetAmType(void) {return TYPE_AM_VCT;}
virtual PTDB Duplicate(PGLOBAL g)
{return (PTDB)new(g) TDBVCT(g, this);}
// Methods
virtual PTDB CopyOne(PTABS t);
// Database routines
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
virtual bool OpenDB(PGLOBAL g);
virtual int ReadDB(PGLOBAL g);
virtual void CloseDB(PGLOBAL g);
protected:
// Members
}; // end of class TDBVCT
/***********************************************************************/
/* Class VCTCOL: VCT access method column descriptor. */
/* This A.M. is used for file having column wise organization. */
/***********************************************************************/
class DllExport VCTCOL : public DOSCOL {
friend class TDBVCT;
friend class VCTFAM;
friend class VCMFAM;
friend class VECFAM;
friend class VMPFAM;
friend class BGVFAM;
public:
// Constructors
VCTCOL(PGLOBAL g, PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i);
VCTCOL(VCTCOL *colp, PTDB tdbp); // Constructor used in copy process
// Implementation
virtual int GetAmType(void) {return TYPE_AM_VCT;}
// Methods
virtual void ReadColumn(PGLOBAL g);
virtual void WriteColumn(PGLOBAL g);
virtual bool SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check);
virtual void SetOk(void);
protected:
virtual void ReadBlock(PGLOBAL g);
virtual void WriteBlock(PGLOBAL g);
VCTCOL(void) {} // Default constructor not to be used
// Members
PVBLK Blk; // Block buffer
int Clen; // Internal length in table
int ColBlk; // Block pointed by column
int ColPos; // Last position read
int Modif; // Number of modified lines in block
}; // end of class VCTCOL
#endif // __TABVCT__

840
storage/connect/tabwmi.cpp Normal file
View File

@@ -0,0 +1,840 @@
/***********************************************************************/
/* TABWMI: Author Olivier Bertrand -- PlugDB -- 2012 */
/* TABWMI: Virtual table to get WMI information. */
/***********************************************************************/
#if !defined(WIN32)
#error This is a WIN32 only table type
#endif // !WIN32
#include "my_global.h"
#include <stdio.h>
#include "global.h"
#include "plgdbsem.h"
//#include "catalog.h"
#include "reldef.h"
#include "xtable.h"
#include "colblk.h"
#include "filter.h"
//#include "xindex.h"
#include "tabwmi.h"
#include "valblk.h"
#include "plgcnx.h" // For DB types
#include "resource.h"
/* -------------- Implementation of the WMI classes ------------------ */
/***********************************************************************/
/* DefineAM: define specific AM values for WMI table. */
/***********************************************************************/
bool WMIDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
{
Nspace = Cat->GetStringCatInfo(g, Name, "Namespace", "Root\\CimV2");
Wclass = Cat->GetStringCatInfo(g, Name, "Class",
(!stricmp(Nspace, "root\\cimv2") ? "ComputerSystemProduct" :
!stricmp(Nspace, "root\\cli") ? "Msft_CliAlias" : ""));
if (!*Wclass) {
sprintf(g->Message, "Missing class name for %s", Nspace);
return true;
} else if (!strchr(Wclass, '_')) {
char *p = (char*)PlugSubAlloc(g, NULL, strlen(Wclass) + 7);
Wclass = strcat(strcpy(p, "Win32_"), Wclass);
} // endif Wclass
if (!(Info = Cat->GetBoolCatInfo(Name, "Info", false)))
Ems = Cat->GetIntCatInfo(Name, "Estimate", 100);
return false;
} // end of DefineAM
/***********************************************************************/
/* GetTable: makes a new TDB of the proper type. */
/***********************************************************************/
PTDB WMIDEF::GetTable(PGLOBAL g, MODE m)
{
if (Info)
return new(g) TDBWCL(this);
else
return new(g) TDBWMI(this);
} // end of GetTable
/* ------------------------------------------------------------------- */
/***********************************************************************/
/* Implementation of the TDBWMI class. */
/***********************************************************************/
TDBWMI::TDBWMI(PWMIDEF tdp) : TDBASE(tdp)
{
Svc = NULL;
Enumerator = NULL;
ClsObj = NULL;
Nspace = tdp->Nspace;
Wclass = tdp->Wclass;
ObjPath = NULL;
Kvp = NULL;
Ems = tdp->Ems;
Kcol = NULL;
Vbp = NULL;
Init = false;
Done = false;
Res = 0;
Rc = 0;
N = -1;
} // end of TDBWMI constructor
/***********************************************************************/
/* Allocate WMI column description block. */
/***********************************************************************/
PCOL TDBWMI::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
{
PCOL colp;
colp = new(g) WMICOL(cdp, this, n);
if (cprec) {
colp->SetNext(cprec->GetNext());
cprec->SetNext(colp);
} else {
colp->SetNext(Columns);
Columns = colp;
} // endif cprec
return colp;
} // end of MakeCol
/***********************************************************************/
/* Initialize: Initialize WMI operations. */
/***********************************************************************/
bool TDBWMI::Initialize(PGLOBAL g)
{
if (Init)
return false;
// Initialize COM.
Res = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
if (FAILED(Res)) {
sprintf(g->Message, "Failed to initialize COM library. "
"Error code = %p", Res);
return true; // Program has failed.
} // endif Res
// Obtain the initial locator to Windows Management
// on a particular host computer.
IWbemLocator *loc; // Initial Windows Management locator
Res = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER,
IID_IWbemLocator, (LPVOID*) &loc);
if (FAILED(Res)) {
sprintf(g->Message, "Failed to create Locator. "
"Error code = %p", Res);
CoUninitialize();
return true; // Program has failed.
} // endif Res
// Connect to the specified namespace with the
// current user and obtain pointer to Svc
// to make IWbemServices calls.
Res = loc->ConnectServer(_bstr_t(Nspace),
NULL, NULL,0, NULL, 0, 0, &Svc);
if (FAILED(Res)) {
sprintf(g->Message, "Could not connect. Error code = %p", Res);
loc->Release();
CoUninitialize();
return true; // Program has failed.
} // endif hres
loc->Release(); // Not used anymore
// Set the IWbemServices proxy so that impersonation
// of the user (client) occurs.
Res = CoSetProxyBlanket(Svc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE,
NULL, RPC_C_AUTHN_LEVEL_CALL,
RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE);
if (FAILED(Res)) {
sprintf(g->Message, "Could not set proxy. Error code = 0x", Res);
Svc->Release();
CoUninitialize();
return true; // Program has failed.
} // endif Res
Init = true;
return false;
} // end of Initialize
/***********************************************************************/
/* Changes '\' into '\\' in the filter. */
/***********************************************************************/
void TDBWMI::DoubleSlash(PGLOBAL g)
{
if (To_Filter && strchr(To_Filter, '\\')) {
char *buf = (char*)PlugSubAlloc(g, NULL, strlen(To_Filter) * 2);
int i = 0, k = 0;
do {
if (To_Filter[i] == '\\')
buf[k++] = '\\';
buf[k++] = To_Filter[i];
} while (To_Filter[i++]);
To_Filter = buf;
} // endif To_Filter
} // end of DoubleSlash
/***********************************************************************/
/* MakeWQL: make the WQL statement use with WMI ExecQuery. */
/***********************************************************************/
char *TDBWMI::MakeWQL(PGLOBAL g)
{
char *colist, *wql/*, *pw = NULL*/;
int len, ncol = 0;
bool first = true, noloc = false;
PCOL colp;
// Normal WQL statement to retrieve results
for (colp = Columns; colp; colp = colp->GetNext())
if (!colp->IsSpecial() && (colp->GetColUse(U_P | U_J_EXT) || noloc))
ncol++;
if (ncol) {
colist = (char*)PlugSubAlloc(g, NULL, (NAM_LEN + 4) * ncol);
for (colp = Columns; colp; colp = colp->GetNext())
if (!colp->IsSpecial()) {
if (colp->GetResultType() == TYPE_DATE)
((DTVAL*)colp->GetValue())->SetFormat(g, "YYYYMMDDhhmmss", 19);
if (colp->GetColUse(U_P | U_J_EXT) || noloc) {
if (first) {
strcpy(colist, colp->GetName());
first = false;
} else
strcat(strcat(colist, ", "), colp->GetName());
} // endif ColUse
} // endif Special
} else {
// ncol == 0 can occur for queries such that sql count(*) from...
// for which we will count the rows from sql * from...
colist = (char*)PlugSubAlloc(g, NULL, 2);
strcpy(colist, "*");
} // endif ncol
// Below 14 is length of 'select ' + length of ' from ' + 1
len = (strlen(colist) + strlen(Wclass) + 14);
len += (To_Filter ? strlen(To_Filter) + 7 : 0);
wql = (char*)PlugSubAlloc(g, NULL, len);
strcat(strcat(strcpy(wql, "SELECT "), colist), " FROM ");
strcat(wql, Wclass);
if (To_Filter)
strcat(strcat(wql, " WHERE "), To_Filter);
return wql;
} // end of MakeWQL
/***********************************************************************/
/* GetWMIInfo: Get info for the WMI class. */
/***********************************************************************/
bool TDBWMI::GetWMIInfo(PGLOBAL g)
{
if (Done)
return false;
char *cmd = MakeWQL(g);
if (cmd == NULL) {
sprintf(g->Message, "Error making WQL statement");
Svc->Release();
CoUninitialize();
return true; // Program has failed.
} // endif cmd
// Query for Wclass in Nspace
Rc = Svc->ExecQuery(bstr_t("WQL"), bstr_t(cmd),
// WBEM_FLAG_BIDIRECTIONAL | WBEM_FLAG_RETURN_IMMEDIATELY,
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL, &Enumerator);
if (FAILED(Rc)) {
sprintf(g->Message, "Query %s failed. Error code = %p", cmd, Rc);
Svc->Release();
CoUninitialize();
return true; // Program has failed.
} // endif Rc
Done = true;
return false;
} // end of GetWMIInfo
/***********************************************************************/
/* WMI: Get the number returned instances. */
/***********************************************************************/
int TDBWMI::GetMaxSize(PGLOBAL g)
{
if (MaxSize < 0) {
/*******************************************************************/
/* Loop enumerating to get the count. This is prone to last a */
/* very long time for some classes such as DataFile, this is why */
/* we just return an estimated value that will be ajusted later. */
/*******************************************************************/
MaxSize = Ems;
#if 0
if (Initialize(g))
return -1;
else if (GetWMIInfo(g))
return -1;
else
MaxSize = 0;
PDBUSER dup = PlgGetUser(g);
while (Enumerator) {
Res = Enumerator->Next(WBEM_INFINITE, 1, &ClsObj, &Rc);
if (Rc == 0)
break;
MaxSize++;
} // endwile Enumerator
Res = Enumerator->Reset();
#endif // 0
} // endif MaxSize
return MaxSize;
} // end of GetMaxSize
/***********************************************************************/
/* When making a Kindex, must provide the Key column info. */
/***********************************************************************/
int TDBWMI::GetRecpos(void)
{
if (!Kcol || !Vbp)
return N;
Kcol->Reset();
Kcol->Eval(NULL);
Vbp->SetValue(Kcol->GetValue(), N);
return N;
} // end of GetRecpos
/***********************************************************************/
/* WMI Access Method opening routine. */
/***********************************************************************/
bool TDBWMI::OpenDB(PGLOBAL g)
{
if (Use == USE_OPEN) {
/*******************************************************************/
/* Table already open. */
/*******************************************************************/
Res = Enumerator->Reset();
N = 0;
return false;
} // endif use
if (Mode != MODE_READ) {
/*******************************************************************/
/* WMI tables cannot be modified. */
/*******************************************************************/
strcpy(g->Message, "WMI tables are read only");
return true;
} // endif Mode
if (!To_Filter && !stricmp(Wclass, "CIM_Datafile")
&& !stricmp(Nspace, "root\\cimv2")) {
strcpy(g->Message,
"Would last forever when not filtered, use DIR table instead");
return true;
} else
DoubleSlash(g);
/*********************************************************************/
/* Initialize the WMI processing. */
/*********************************************************************/
if (Initialize(g))
return true;
else
return GetWMIInfo(g);
} // end of OpenDB
/***********************************************************************/
/* Data Base read routine for WMI access method. */
/***********************************************************************/
int TDBWMI::ReadDB(PGLOBAL g)
{
Res = Enumerator->Next(WBEM_INFINITE, 1, &ClsObj, &Rc);
if (Rc == 0)
return RC_EF;
N++;
return RC_OK;
} // end of ReadDB
/***********************************************************************/
/* WriteDB: Data Base write routine for WMI access methods. */
/***********************************************************************/
int TDBWMI::WriteDB(PGLOBAL g)
{
strcpy(g->Message, "WMI tables are read only");
return RC_FX;
} // end of WriteDB
/***********************************************************************/
/* Data Base delete line routine for WMI access methods. */
/***********************************************************************/
int TDBWMI::DeleteDB(PGLOBAL g, int irc)
{
strcpy(g->Message, "Delete not enabled for WMI tables");
return RC_FX;
} // end of DeleteDB
/***********************************************************************/
/* Data Base close routine for WMI access method. */
/***********************************************************************/
void TDBWMI::CloseDB(PGLOBAL g)
{
// Cleanup
if (ClsObj)
ClsObj->Release();
if (Enumerator)
Enumerator->Release();
if (Svc)
Svc->Release();
CoUninitialize();
} // end of CloseDB
// ------------------------ WMICOL functions ----------------------------
/***********************************************************************/
/* WMICOL public constructor. */
/***********************************************************************/
WMICOL::WMICOL(PCOLDEF cdp, PTDB tdbp, int n)
: COLBLK(cdp, tdbp, n)
{
Tdbp = (PTDBWMI)tdbp;
VariantInit(&Prop);
Ctype = CIM_ILLEGAL;
Res = 0;
} // end of WMICOL constructor
#if 0
/***********************************************************************/
/* WMICOL constructor used for copying columns. */
/* tdbp is the pointer to the new table descriptor. */
/***********************************************************************/
WMICOL::WMICOL(WMICOL *col1, PTDB tdbp) : COLBLK(col1, tdbp)
{
} // end of WMICOL copy constructor
#endif // 0
/***********************************************************************/
/* Read the next WMI address elements. */
/***********************************************************************/
void WMICOL::ReadColumn(PGLOBAL g)
{
// Get the value of the Name property
Res = Tdbp->ClsObj->Get(_bstr_t(Name), 0, &Prop, &Ctype, 0);
switch (Prop.vt) {
case VT_EMPTY:
case VT_NULL:
case VT_VOID:
Value->Reset();
break;
case VT_BSTR:
Value->SetValue_psz(_com_util::ConvertBSTRToString(Prop.bstrVal));
break;
case VT_I4:
case VT_UI4:
Value->SetValue(Prop.lVal);
break;
case VT_I2:
case VT_UI2:
Value->SetValue(Prop.iVal);
break;
case VT_INT:
case VT_UINT:
Value->SetValue((int)Prop.intVal);
break;
case VT_BOOL:
Value->SetValue(((int)Prop.boolVal) ? 1 : 0);
break;
case VT_R8:
Value->SetValue(Prop.dblVal);
break;
case VT_R4:
Value->SetValue((double)Prop.fltVal);
break;
case VT_DATE:
switch (Value->GetType()) {
case TYPE_DATE:
{SYSTEMTIME stm;
struct tm ptm;
int rc = VariantTimeToSystemTime(Prop.date, &stm);
ptm.tm_year = stm.wYear;
ptm.tm_mon = stm.wMonth;
ptm.tm_mday = stm.wDay;
ptm.tm_hour = stm.wHour;
ptm.tm_min = stm.wMinute;
ptm.tm_sec = stm.wSecond;
((DTVAL*)Value)->MakeTime(&ptm);
}break;
case TYPE_STRING:
{SYSTEMTIME stm;
char buf[24];
int rc = VariantTimeToSystemTime(Prop.date, &stm);
sprintf(buf, "%02d/%02d/%d %02d:%02d:%02d",
stm.wDay, stm.wMonth, stm.wYear,
stm.wHour, stm.wMinute, stm.wSecond);
Value->SetValue_psz(buf);
}break;
default:
Value->SetValue((double)Prop.fltVal);
} // endswitch Type
break;
default:
// This will reset numeric column value
Value->SetValue_psz("Type not supported");
break;
} // endswitch vt
VariantClear(&Prop);
} // end of ReadColumn
/* ---------------------------TDBWCL class --------------------------- */
/***********************************************************************/
/* Implementation of the TDBWCL class. */
/***********************************************************************/
TDBWCL::TDBWCL(PWMIDEF tdp) : TDBASE(tdp)
{
Svc = NULL;
ClsObj = NULL;
Propname = NULL;
Nspace = tdp->Nspace;
Wclass = tdp->Wclass;
Init = false;
Done = false;
Res = 0;
N = -1;
Lng = 0;
Typ = 0;
Prec = 0;
} // end of TDBWCL constructor
/***********************************************************************/
/* Allocate WCL column description block. */
/***********************************************************************/
PCOL TDBWCL::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
{
PWCLCOL colp;
colp = (PWCLCOL)new(g) WCLCOL(cdp, this, n);
if (cprec) {
colp->SetNext(cprec->GetNext());
cprec->SetNext(colp);
} else {
colp->SetNext(Columns);
Columns = colp;
} // endif cprec
if (!colp->Flag) {
if (!stricmp(colp->Name, "Column_Name"))
colp->Flag = 1;
else if (!stricmp(colp->Name, "Data_Type"))
colp->Flag = 2;
else if (!stricmp(colp->Name, "Type_Name"))
colp->Flag = 3;
else if (!stricmp(colp->Name, "Precision"))
colp->Flag = 4;
else if (!stricmp(colp->Name, "Length"))
colp->Flag = 5;
else if (!stricmp(colp->Name, "Scale"))
colp->Flag = 6;
} // endif Flag
return colp;
} // end of MakeCol
/***********************************************************************/
/* Initialize: Initialize WMI operations. */
/***********************************************************************/
bool TDBWCL::Initialize(PGLOBAL g)
{
if (Init)
return false;
// Initialize COM.
Res = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
if (FAILED(Res)) {
sprintf(g->Message, "Failed to initialize COM library. "
"Error code = %p", Res);
return true; // Program has failed.
} // endif Res
// Obtain the initial locator to Windows Management
// on a particular host computer.
IWbemLocator *loc; // Initial Windows Management locator
Res = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER,
IID_IWbemLocator, (LPVOID*) &loc);
if (FAILED(Res)) {
sprintf(g->Message, "Failed to create Locator. "
"Error code = %p", Res);
CoUninitialize();
return true; // Program has failed.
} // endif Res
// Connect to the specified namespace with the
// current user and obtain pointer to Svc
// to make IWbemServices calls.
Res = loc->ConnectServer(_bstr_t(Nspace),
NULL, NULL,0, NULL, 0, 0, &Svc);
if (FAILED(Res)) {
sprintf(g->Message, "Could not connect. Error code = %p", Res);
loc->Release();
CoUninitialize();
return true; // Program has failed.
} // endif hres
loc->Release(); // Not used anymore
// Perform a full class object retrieval
Res = Svc->GetObject(bstr_t(Wclass), 0, 0, &ClsObj, 0);
if (FAILED(Res)) {
sprintf(g->Message, "failed GetObject %s in %s\n", Wclass, Nspace);
Svc->Release();
Svc = NULL; // MUST be set to NULL (why?)
return true;
} // endif res
Init = true;
return false;
} // end of Initialize
/***********************************************************************/
/* WCL: Get the number of properties. */
/***********************************************************************/
int TDBWCL::GetMaxSize(PGLOBAL g)
{
if (MaxSize < 0) {
VARIANT val;
if (Initialize(g))
return -1;
Res = ClsObj->Get(bstr_t("__Property_Count"), 0, &val, NULL, NULL);
if (FAILED(Res)) {
sprintf(g->Message, "failed Get(Property_Count) res=%d\n", Res);
return -1;
} // endif Res
MaxSize = val.lVal;
} // endif MaxSize
return MaxSize;
} // end of GetMaxSize
/***********************************************************************/
/* WCL Access Method opening routine. */
/***********************************************************************/
bool TDBWCL::OpenDB(PGLOBAL g)
{
if (Use == USE_OPEN) {
/*******************************************************************/
/* Table already open. */
/*******************************************************************/
ClsObj->BeginEnumeration(WBEM_FLAG_NONSYSTEM_ONLY);
N = 0;
return false;
} // endif use
if (Mode != MODE_READ) {
/*******************************************************************/
/* WMI tables cannot be modified. */
/*******************************************************************/
strcpy(g->Message, "WCL tables are read only");
return true;
} // endif Mode
/*********************************************************************/
/* Initialize the WMI processing. */
/*********************************************************************/
if (Initialize(g))
return true;
Res = ClsObj->BeginEnumeration(WBEM_FLAG_NONSYSTEM_ONLY);
if (FAILED(Res)) {
sprintf(g->Message, "failed BeginEnumeration hr=%d\n", Res);
return NULL;
} // endif hr
return false;
} // end of OpenDB
/***********************************************************************/
/* Data Base read routine for WCL access method. */
/***********************************************************************/
int TDBWCL::ReadDB(PGLOBAL g)
{
VARIANT val;
CIMTYPE type;
Res = ClsObj->Next(0, &Propname, &val, &type, NULL);
if (FAILED(Res)) {
sprintf(g->Message, "failed getting Next hr=%d\n", Res);
return RC_FX;
} else if (Res == WBEM_S_NO_MORE_DATA) {
VariantClear(&val);
return RC_EF;
} // endif res
Prec = 0;
switch (type) {
case CIM_STRING:
Typ = TYPE_STRING;
Lng = 255;
Prec = 1; // Case insensitive
break;
case CIM_SINT32:
case CIM_UINT32:
case CIM_BOOLEAN:
Typ = TYPE_INT;
Lng = 9;
break;
case CIM_SINT8:
case CIM_UINT8:
case CIM_SINT16:
case CIM_UINT16:
Typ = TYPE_SHORT;
Lng = 6;
break;
case CIM_REAL64:
case CIM_REAL32:
Prec = 2;
case CIM_SINT64:
case CIM_UINT64:
Typ = TYPE_FLOAT;
Lng = 15;
break;
case CIM_DATETIME:
Typ = TYPE_DATE;
Lng = 19;
break;
case CIM_CHAR16:
Typ = TYPE_STRING;
Lng = 16;
break;
case CIM_EMPTY:
Typ = TYPE_STRING;
Lng = 24; // ???
break;
default:
return RC_NF;
} // endswitch type
N++;
return RC_OK;
} // end of ReadDB
/***********************************************************************/
/* WriteDB: Data Base write routine for WCL access methods. */
/***********************************************************************/
int TDBWCL::WriteDB(PGLOBAL g)
{
strcpy(g->Message, "WCL tables are read only");
return RC_FX;
} // end of WriteDB
/***********************************************************************/
/* Data Base delete line routine for WCL access methods. */
/***********************************************************************/
int TDBWCL::DeleteDB(PGLOBAL g, int irc)
{
strcpy(g->Message, "Delete not enabled for WCL tables");
return RC_FX;
} // end of DeleteDB
/***********************************************************************/
/* Data Base close routine for WMI access method. */
/***********************************************************************/
void TDBWCL::CloseDB(PGLOBAL g)
{
// Cleanup
if (ClsObj)
ClsObj->Release();
if (Svc)
Svc->Release();
CoUninitialize();
} // end of CloseDB
// ------------------------ WCLCOL functions ----------------------------
/***********************************************************************/
/* WCLCOL public constructor. */
/***********************************************************************/
WCLCOL::WCLCOL(PCOLDEF cdp, PTDB tdbp, int n)
: COLBLK(cdp, tdbp, n)
{
Tdbp = (PTDBWCL)tdbp;
Flag = cdp->GetOffset();
Res = 0;
} // end of WMICOL constructor
/***********************************************************************/
/* Read the next WCL elements. */
/***********************************************************************/
void WCLCOL::ReadColumn(PGLOBAL g)
{
// Get the value of the Name property
switch (Flag) {
case 1:
Value->SetValue_psz(_com_util::ConvertBSTRToString(Tdbp->Propname));
break;
case 2:
Value->SetValue(Tdbp->Typ);
break;
case 3:
Value->SetValue_psz(GetTypeName(Tdbp->Typ));
break;
case 4:
case 5:
Value->SetValue(Tdbp->Lng);
break;
case 6:
Value->SetValue(Tdbp->Prec);
break;
default:
Value->Reset();
} // endswitch Flag
} // end of ReadColumn

191
storage/connect/tabwmi.h Normal file
View File

@@ -0,0 +1,191 @@
// TABWMI.H Olivier Bertrand 2012
// WMI: Virtual table to Get WMI information
#define _WIN32_DCOM
#include <wbemidl.h>
# pragma comment(lib, "wbemuuid.lib")
#include <iostream>
using namespace std;
#include <comdef.h>
/***********************************************************************/
/* Definitions. */
/***********************************************************************/
typedef class WMIDEF *PWMIDEF;
typedef class TDBWMI *PTDBWMI;
typedef class WMICOL *PWMICOL;
typedef class TDBWCL *PTDBWCL;
typedef class WCLCOL *PWCLCOL;
/* -------------------------- WMI classes ---------------------------- */
/***********************************************************************/
/* WMI: Virtual table to get the WMI information. */
/***********************************************************************/
class WMIDEF : public TABDEF { /* Logical table description */
friend class TDBWMI;
friend class TDBWCL;
public:
// Constructor
WMIDEF(void)
{Pseudo = 3; Nspace = NULL; Wclass = NULL; Ems = 0; Info = false;}
// Implementation
virtual const char *GetType(void) {return "WMI";}
// Methods
virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff);
virtual PTDB GetTable(PGLOBAL g, MODE m);
virtual bool DeleteTableFile(PGLOBAL g) {return true;}
protected:
// Members
char *Nspace;
char *Wclass;
int Ems;
bool Info;
}; // end of WMIDEF
/***********************************************************************/
/* This is the class declaration for the WMI table. */
/***********************************************************************/
class TDBWMI : public TDBASE {
friend class WMICOL;
public:
// Constructor
TDBWMI(PWMIDEF tdp);
// Implementation
virtual AMT GetAmType(void) {return TYPE_AM_WMI;}
// Methods
virtual int GetRecpos(void);
virtual int GetProgCur(void) {return N;}
virtual int RowNumber(PGLOBAL g, bool b = false) {return N + 1;}
// Database routines
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
virtual int GetMaxSize(PGLOBAL g);
virtual bool OpenDB(PGLOBAL g);
virtual int ReadDB(PGLOBAL g);
virtual int WriteDB(PGLOBAL g);
virtual int DeleteDB(PGLOBAL g, int irc);
virtual void CloseDB(PGLOBAL g);
protected:
// Specific routines
bool Initialize(PGLOBAL g);
char *MakeWQL(PGLOBAL g);
void DoubleSlash(PGLOBAL g);
bool GetWMIInfo(PGLOBAL g);
// Members
IWbemServices *Svc; // IWbemServices pointer
IEnumWbemClassObject *Enumerator;
IWbemClassObject *ClsObj;
char *Nspace; // Namespace
char *Wclass; // Class name
char *ObjPath; // Used for direct access
char *Kvp; // Itou
int Ems; // Estimated max size
PCOL Kcol; // Key column
HRESULT Res;
PVBLK Vbp;
bool Init;
bool Done;
ULONG Rc;
int N; // Row number
}; // end of class TDBWMI
/***********************************************************************/
/* Class WMICOL: WMI Address column. */
/***********************************************************************/
class WMICOL : public COLBLK {
friend class TDBWMI;
public:
// Constructors
WMICOL(PCOLDEF cdp, PTDB tdbp, int n);
// Implementation
virtual int GetAmType(void) {return TYPE_AM_WMI;}
// Methods
virtual void ReadColumn(PGLOBAL g);
protected:
WMICOL(void) {} // Default constructor not to be used
// Members
PTDBWMI Tdbp; // Points to WMI table block
VARIANT Prop; // Property value
CIMTYPE Ctype; // CIM Type
HRESULT Res;
}; // end of class WMICOL
/***********************************************************************/
/* This is the class declaration for the WCL table. */
/***********************************************************************/
class TDBWCL : public TDBASE {
friend class WCLCOL;
public:
// Constructor
TDBWCL(PWMIDEF tdp);
// Implementation
virtual AMT GetAmType(void) {return TYPE_AM_WMI;}
// Methods
virtual int GetRecpos(void) {return N;}
virtual int GetProgCur(void) {return N;}
virtual int RowNumber(PGLOBAL g, bool b = false) {return N + 1;}
// Database routines
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
virtual int GetMaxSize(PGLOBAL g);
virtual bool OpenDB(PGLOBAL g);
virtual int ReadDB(PGLOBAL g);
virtual int WriteDB(PGLOBAL g);
virtual int DeleteDB(PGLOBAL g, int irc);
virtual void CloseDB(PGLOBAL g);
protected:
// Specific routines
bool Initialize(PGLOBAL g);
// Members
IWbemServices *Svc; // IWbemServices pointer
IWbemClassObject *ClsObj;
BSTR Propname;
char *Nspace; // Namespace
char *Wclass; // Class name
HRESULT Res;
bool Init;
bool Done;
int N; // Row number
int Lng;
int Typ;
int Prec;
}; // end of class TDBWCL
/***********************************************************************/
/* Class WMICOL: WMI Address column. */
/***********************************************************************/
class WCLCOL : public COLBLK {
friend class TDBWCL;
public:
// Constructors
WCLCOL(PCOLDEF cdp, PTDB tdbp, int n);
// Implementation
virtual int GetAmType(void) {return TYPE_AM_WMI;}
// Methods
virtual void ReadColumn(PGLOBAL g);
protected:
WCLCOL(void) {} // Default constructor not to be used
// Members
PTDBWCL Tdbp; // Points to WMI table block
HRESULT Res;
int Flag;
}; // end of class WCLCOL

1709
storage/connect/tabxml.cpp Normal file

File diff suppressed because it is too large Load Diff

246
storage/connect/tabxml.h Normal file
View File

@@ -0,0 +1,246 @@
/*************** Tabxml H Declares Source Code File (.H) ***************/
/* Name: TABXML.H Version 1.6 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 2007-2013 */
/* */
/* This file contains the XML table classes declares. */
/***********************************************************************/
#define TYPE_AM_XML (AMT)127
typedef class XMLDEF *PXMLDEF;
typedef class TDBXML *PTDBXML;
typedef class XMLCOL *PXMLCOL;
// These functions are exported from the Extended.dll
//PTABDEF __stdcall GetXML(PGLOBAL g, void *memp);
/* --------------------------- XML classes --------------------------- */
/***********************************************************************/
/* XML table. */
/***********************************************************************/
class DllExport XMLDEF : public TABDEF { /* Logical table description */
friend class TDBXML;
public:
// Constructor
XMLDEF(void);
// Implementation
virtual const char *GetType(void) {return "XML";}
// Methods
virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff);
virtual PTDB GetTable(PGLOBAL g, MODE m);
virtual bool DeleteTableFile(PGLOBAL g);
protected:
// Members
char *Fn; /* Path/Name of corresponding file */
char *Encoding; /* New XML table file encoding */
char *Tabname; /* Name of Table node */
char *Rowname; /* Name of first level nodes */
char *Colname; /* Name of second level nodes */
char *Mulnode; /* Name of multiple node */
char *XmlDB; /* Name of XML DB node */
char *Nslist; /* List of namespaces to register */
char *DefNs; /* Dummy name of default namespace */
char *Attrib; /* Table node attributes */
char *Hdattr; /* Header node attributes */
int Coltype; /* Default column type */
int Limit; /* Limit of multiple values */
int Header; /* n first rows are header rows */
bool Xpand; /* Put multiple tags in several rows */
bool Usedom; /* True: DOM, False: libxml2 */
bool Skipnull; /* True: skip writing null nodes */
}; // end of XMLDEF
#if defined(INCLUDE_TDBXML)
/***********************************************************************/
/* This is the class declaration for the simple XML tables. */
/***********************************************************************/
class DllExport TDBXML : public TDBASE {
friend class XMLCOL;
friend class XMULCOL;
friend class XPOSCOL;
public:
// Constructor
TDBXML(PXMLDEF tdp);
TDBXML(PTDBXML tdbp);
// Implementation
virtual AMT GetAmType(void) {return TYPE_AM_XML;}
virtual PTDB Duplicate(PGLOBAL g) {return (PTDB)new(g) TDBXML(this);}
// Methods
virtual PTDB CopyOne(PTABS t);
virtual int GetRecpos(void);
virtual int GetProgCur(void) {return N;}
virtual PSZ GetFile(PGLOBAL g) {return Xfile;}
virtual void SetFile(PGLOBAL g, PSZ fn) {Xfile = fn;}
virtual void ResetDB(void) {N = 0;}
virtual void ResetSize(void) {MaxSize = -1;}
virtual int RowNumber(PGLOBAL g, bool b = false);
int LoadTableFile(PGLOBAL g);
bool Initialize(PGLOBAL g);
bool SetTabNode(PGLOBAL g);
void SetNodeAttr(PGLOBAL g, char *attr, PXNODE node);
bool CheckRow(PGLOBAL g, bool b);
// Database routines
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
virtual PCOL InsertSpecialColumn(PGLOBAL g, PCOL colp);
//virtual int GetMaxSame(PGLOBAL g) {return (Xpand) ? Limit : 1;}
virtual int Cardinality(PGLOBAL g);
virtual int GetMaxSize(PGLOBAL g);
//virtual bool NeedIndexing(PGLOBAL g);
virtual bool OpenDB(PGLOBAL g);
virtual int ReadDB(PGLOBAL g);
virtual int WriteDB(PGLOBAL g);
virtual int DeleteDB(PGLOBAL g, int irc);
virtual void CloseDB(PGLOBAL g);
virtual int CheckWrite(PGLOBAL g) {Checked = true; return 0;}
protected:
// Members
PXDOC Docp;
PXNODE Root;
PXNODE Curp;
PXNODE DBnode;
PXNODE TabNode;
PXNODE RowNode;
PXNODE ColNode;
PXLIST Nlist;
PXLIST Clist;
PFBLOCK To_Xb; // Pointer to XML file block
PCOL Colp; // The multiple column
bool Changed; // After Update, Insert or Delete
bool Checked; // After Update check pass
bool NextSame; // Same next row
bool Xpand; // Put multiple tags in several rows
bool NewRow; // True when inserting a new row
bool Hasnod; // True if rows have subnodes
bool Write; // True for Insert and Update
bool Usedom; // True for DOM, False for libxml2
bool Bufdone; // True when column buffers allocated
bool Nodedone; // True when column nodes allocated
bool Skipnull; // True to skip writing nullnodes
bool Void; // True if the file does not exist
char *Xfile; // The XML file
char *Enc; // New XML table file encoding
char *Tabname; // Name of Table node
char *Rowname; // Name of first level nodes
char *Colname; // Name of second level nodes
char *Mulnode; // Name of multiple node
char *XmlDB; // Name of XML DB node
char *Nslist; // List of namespaces to register
char *DefNs; // Dummy name of default namespace
char *Attrib; // Table node attribut(s)
char *Hdattr; // Header node attribut(s)
int Coltype; // Default column type
int Limit; // Limit of multiple values
int Header; // n first rows are header rows
int Nrow; // The table cardinality
int Irow; // The current row index
int Nsub; // The current subrow index
int N; // The current Rowid
}; // end of class TDBXML
/***********************************************************************/
/* Class XMLCOL: XDB table access method column descriptor. */
/***********************************************************************/
class XMLCOL : public COLBLK {
public:
// Constructors
XMLCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am = "XML");
XMLCOL(XMLCOL *colp, PTDB tdbp); // Constructor used in copy process
// Implementation
virtual int GetAmType(void) {return TYPE_AM_XML;}
virtual void SetTo_Val(PVAL valp) {To_Val = valp;}
bool ParseXpath(PGLOBAL g, bool mode);
// Methods
virtual bool SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check);
virtual void ReadColumn(PGLOBAL g);
virtual void WriteColumn(PGLOBAL g);
bool AllocBuf(PGLOBAL g, bool mode);
void AllocNodes(PGLOBAL g, PXDOC dp);
protected:
//xmlNodePtr SelectSingleNode(xmlNodePtr node, char *name);
// Default constructor not to be used
XMLCOL(void) : COLBLK(1) {}
// Members
PXLIST Nl;
PXLIST Nlx;
PXNODE ColNode;
PXNODE ValNode;
PXNODE Cxnp;
PXNODE Vxnp;
PXATTR Vxap;
PXATTR AttNode;
PTDBXML Tdbp;
char *Valbuf; // To the node value buffer
char *Xname; // The node or attribute name
char* *Nodes; // The intermediate nodes
int Type; // 0: Attribute, 1: Tag, 2: position
int Nod; // The number of intermediate nodes
int Inod; // Index of multiple node
int Rank; // Position
bool Mul; // true for multiple column
bool Checked; // Was checked while Updating
int Long; // Buffer length
int Nx; // The last read row
int Sx; // The last read sub-row
PVAL To_Val; // To value used for Update/Insert
}; // end of class XMLCOL
/***********************************************************************/
/* Derived class XMLCOLX: used to replace a multiple XMLCOL by the */
/* derived class XMULCOL that has specialize read and write functions.*/
/* Note: this works only if the members of the derived class are the */
/* same than the ones of the original class (NO added members). */
/***********************************************************************/
class XMLCOLX : public XMLCOL {
public:
// Fake operator new used to change a filter into a derived filter
void * operator new(size_t size, PXMLCOL colp) {return colp;}
#if !defined(__BORLANDC__)
// Avoid warning C4291 by defining a matching dummy delete operator
void operator delete(void *, PXMLCOL) {}
#endif
}; // end of class XMLCOLX
/***********************************************************************/
/* Class XMULCOL: XML table access method multiple column descriptor. */
/***********************************************************************/
class XMULCOL : public XMLCOLX {
public:
// The constructor must restore Value because XOBJECT has a void
// constructor called by default that set Value to NULL
XMULCOL(PVAL valp) {Value = valp; Mul = true;}
// Methods
virtual void ReadColumn(PGLOBAL g);
virtual void WriteColumn(PGLOBAL g);
}; // end of class XMULCOL
/***********************************************************************/
/* Class XPOSCOL: XML table column accessed by position. */
/***********************************************************************/
class XPOSCOL : public XMLCOLX {
public:
// The constructor must restore Value because XOBJECT has a void
// constructor called by default that set Value to NULL
XPOSCOL(PVAL valp) {Value = valp;}
// Methods
virtual void ReadColumn(PGLOBAL g);
virtual void WriteColumn(PGLOBAL g);
}; // end of class XPOSCOL
#endif // INCLUDE_TDBXML

View File

@@ -0,0 +1,155 @@
/* Copyright (C) Olivier Bertrand 2004 - 2012
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/**
@file user_connect.cc
@brief
Implements the user_connect class.
@details
To support multi_threading, each query creates and use a PlugDB "user"
that is a connection with its personnal memory allocation.
@note
*/
/****************************************************************************/
/* Author: Olivier Bertrand -- bertrandop@gmail.com -- 2004-2012 */
/****************************************************************************/
#ifdef USE_PRAGMA_IMPLEMENTATION
#pragma implementation // gcc: Class implementation
#endif
#define DONT_DEFINE_VOID
#define MYSQL_SERVER
#include "sql_class.h"
#undef OFFSET
#define NOPARSE
#include "osutil.h"
#include "global.h"
#include "plgdbsem.h"
#include "user_connect.h"
#include "mycat.h"
extern "C" char plgxini[];
extern int xtrace;
/****************************************************************************/
/* Initialize the user_connect static member. */
/****************************************************************************/
PCONNECT user_connect::to_users= NULL;
/****************************************************************************/
/* CONNECT functions called externally. */
/****************************************************************************/
PGLOBAL CntExit(PGLOBAL g);
/* -------------------------- class user_connect -------------------------- */
/****************************************************************************/
/* Constructor. */
/****************************************************************************/
user_connect::user_connect(THD *thd, const char *dbn)
{
thdp= thd;
next= NULL;
previous= NULL;
g= NULL;
tabp= NULL;
last_query_id= 0;
count= 0;
// Statistics
nrd= fnd= nfd= 0;
bzero((char*) &tb1, sizeof(struct timeb));
bzero((char*) &tb2, sizeof(struct timeb));
} // end of user_connect constructor
/****************************************************************************/
/* Destructor. */
/****************************************************************************/
user_connect::~user_connect()
{
// Terminate CONNECT and Plug-like environment, should return NULL
g= CntExit(g);
} // end of user_connect destructor
/****************************************************************************/
/* Initialization. */
/****************************************************************************/
bool user_connect::user_init(PHC hc)
{
// Initialize Plug-like environment
PACTIVITY ap= NULL;
PDBUSER dup= NULL;
// Areasize= 64M because of VEC tables. Should be parameterisable
g= PlugInit(NULL, 67108864);
// Check whether the initialization is complete
if (!g || !g->Sarea || PlugSubSet(g, g->Sarea, g->Sarea_Size)
|| !(dup= PlgMakeUser(g))) {
if (g)
printf("%s\n", g->Message);
int rc= PlugExit(g);
g= NULL;
free(dup);
return true;
} // endif g->
dup->Catalog= new MYCAT(hc);
ap= new ACTIVITY;
memset(ap, 0, sizeof(ACTIVITY));
strcpy(ap->Ap_Name, "CONNECT");
g->Activityp= ap;
g->Activityp->Aptr= dup;
next= to_users;
to_users= this;
if (next)
next->previous= this;
last_query_id= thdp->query_id;
count= 1;
return false;
} // end of user_init
/****************************************************************************/
/* Check whether we begin a new query and if so cleanup the previous one. */
/****************************************************************************/
bool user_connect::CheckCleanup(void)
{
if (thdp->query_id > last_query_id) {
PlugCleanup(g, true);
PlugSubSet(g, g->Sarea, g->Sarea_Size);
last_query_id= thdp->query_id;
if (xtrace)
printf("=====> Begin new query %d\n", last_query_id);
return true;
} // endif query_id
return false;
} // end of CheckCleanup

View File

@@ -0,0 +1,80 @@
/* Copyright (C) Olivier Bertrand 2004 - 2011
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/** @file user_connect.h
@brief
Declaration of the user_connect class.
@note
@see
/sql/handler.h and /storage/connect/user_connect.cc
*/
#ifdef USE_PRAGMA_INTERFACE
#pragma interface /* gcc class implementation */
#endif
#if defined(WIN32)
#include <sys\timeb.h>
#else
#include <sys/timeb.h>
#endif // UBUNTU
/*****************************************************************************/
/* This is the global structure having all CONNECT information. */
/*****************************************************************************/
//typedef struct _global *PGLOBAL;
typedef class user_connect *PCONNECT;
typedef class ha_connect *PHC;
static int connect_done_func(void *);
/*****************************************************************************/
/* The CONNECT users. There should be one by connected users. */
/*****************************************************************************/
class user_connect
{
friend class ha_connect;
friend int connect_done_func(void *);
public:
// Constructor
user_connect(THD *thd, const char *dbn);
// Destructor
virtual ~user_connect();
// Implementation
bool user_init(ha_connect *hc);
bool CheckCleanup(void);
bool CheckQueryID(void) {return thdp->query_id > last_query_id;}
bool CheckQuery(query_id_t vid) {return last_query_id > vid;}
protected:
// Members
static PCONNECT to_users; // To the chain of users
THD *thdp; // To the user thread
PCONNECT next; // Next user in chain
PCONNECT previous; // Previous user in chain
PGLOBAL g; // The common handle to CONNECT
//char dbname[32]; // The DBCONNECT database
PTDBDOS tabp; // The table used on create
query_id_t last_query_id; // the latest user query id
int count; // if used by several handlers
// Statistics
ulong nrd, fnd, nfd;
struct timeb tb1, tb2;
}; // end of user_connect class definition

1212
storage/connect/valblk.cpp Normal file

File diff suppressed because it is too large Load Diff

308
storage/connect/valblk.h Normal file
View File

@@ -0,0 +1,308 @@
/*************** Valblk H Declares Source Code File (.H) ***************/
/* Name: VALBLK.H Version 1.6 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 2005-2012 */
/* */
/* This file contains the VALBLK and derived classes declares. */
/***********************************************************************/
/***********************************************************************/
/* Include required application header files */
/* assert.h is header required when using the assert function. */
/* block.h is header containing Block global declarations. */
/***********************************************************************/
#ifndef __VALBLK__H__
#define __VALBLK__H__
#include "value.h"
/***********************************************************************/
/* Utility used to allocate value blocks. */
/***********************************************************************/
DllExport PVBLK AllocValBlock(PGLOBAL, void*, int, int, int, int, bool, bool);
/***********************************************************************/
/* Class VALBLK represent a base class for variable blocks. */
/***********************************************************************/
class VALBLK : public BLOCK {
//friend void SemColData(PGLOBAL g, PSEM semp);
public:
// Constructors
VALBLK(void *mp, int type, int nval)
{Blkp = mp; Type = type; Nval = nval; Check = true;}
// Implementation
int GetNval(void) {return Nval;}
void SetNval(int n) {Nval = n;}
void *GetValPointer(void) {return Blkp;}
void SetValPointer(void *mp) {Blkp = mp;}
int GetType(void) {return Type;}
void SetCheck(bool b) {Check = b;}
virtual void Init(PGLOBAL g, bool check) = 0;
virtual int GetVlen(void) = 0;
virtual PSZ GetCharValue(int n);
virtual short GetShortValue(int n) = 0;
virtual int GetIntValue(int n) = 0;
virtual double GetFloatValue(int n) = 0;
virtual void ReAlloc(void *mp, int n) {Blkp = mp; Nval = n;}
virtual void Reset(int n) = 0;
virtual bool SetFormat(PGLOBAL g, PSZ fmt, int len, int year = 0);
virtual void SetPrec(int p) {}
virtual bool IsCi(void) {return false;}
// Methods
virtual void SetValue(short sval, int n) {assert(false);}
virtual void SetValue(int lval, int n) {assert(false);}
virtual void SetValue(PSZ sp, int n) {assert(false);}
virtual void SetValue(PVAL valp, int n) = 0;
virtual void SetMin(PVAL valp, int n) = 0;
virtual void SetMax(PVAL valp, int n) = 0;
virtual void SetValue(PVBLK pv, int n1, int n2) = 0;
virtual void SetValues(PVBLK pv, int i, int n) = 0;
virtual void AddMinus1(PVBLK pv, int n1, int n2) {assert(false);}
virtual void Move(int i, int j) = 0;
virtual int CompVal(PVAL vp, int n) = 0;
virtual int CompVal(int i1, int i2) = 0;
virtual void *GetValPtr(int n) = 0;
virtual void *GetValPtrEx(int n) = 0;
virtual int Find(PVAL vp) = 0;
virtual int GetMaxLength(void) = 0;
bool Locate(PVAL vp, int& i);
protected:
#if defined(_DEBUG) || defined(DEBTRACE)
void ChkIndx(int n);
void ChkPrm(PVAL v, int n);
void ChkTyp(PVAL v);
void ChkTyp(PVBLK vb);
#endif // _DEBUG) || DEBTRACE
// Members
PGLOBAL Global; // Used for messages and allocation
void *Blkp; // To value block
int Type; // Type of individual values
int Nval; // Max number of values in block
bool Check; // If true SetValue types must match
}; // end of class VALBLK
/***********************************************************************/
/* Class CHRBLK: represent a block of fixed length strings. */
/***********************************************************************/
class CHRBLK : public VALBLK {
public:
// Constructors
CHRBLK(void *mp, int size, int len, int prec, bool b);
// Implementation
virtual void Init(PGLOBAL g, bool check);
virtual int GetVlen(void) {return Long;}
virtual PSZ GetCharValue(int n);
virtual short GetShortValue(int n);
virtual int GetIntValue(int n);
virtual double GetFloatValue(int n);
virtual void Reset(int n);
virtual void SetPrec(int p) {Ci = (p != 0);}
virtual bool IsCi(void) {return Ci;}
// Methods
virtual void SetValue(PSZ sp, int n);
virtual void SetValue(PVAL valp, int n);
virtual void SetMin(PVAL valp, int n);
virtual void SetMax(PVAL valp, int n);
virtual void SetValue(PVBLK pv, int n1, int n2);
virtual void SetValues(PVBLK pv, int k, int n);
virtual void Move(int i, int j);
virtual int CompVal(PVAL vp, int n);
virtual int CompVal(int i1, int i2);
virtual void *GetValPtr(int n);
virtual void *GetValPtrEx(int n);
virtual int Find(PVAL vp);
virtual int GetMaxLength(void);
protected:
// Members
char* const &Chrp; // Pointer to char buffer
PSZ Valp; // Used to make a zero ended value
bool Blanks; // True for right filling with blanks
bool Ci; // True if case insensitive
int Long; // Length of each string
}; // end of class CHRBLK
/***********************************************************************/
/* Class STRBLK: represent a block of string pointers. */
/* Currently this class is used only by the DECODE scalar function */
/* and by the MyColumn function to store date formats. */
/***********************************************************************/
class STRBLK : public VALBLK {
public:
// Constructors
STRBLK(PGLOBAL g, void *mp, int size);
// Implementation
virtual void Init(PGLOBAL g, bool check);
virtual int GetVlen(void) {return sizeof(PSZ);}
virtual PSZ GetCharValue(int n) {return Strp[n];}
virtual short GetShortValue(int n) {return (short)atoi(Strp[n]);}
virtual int GetIntValue(int n) {return atol(Strp[n]);}
virtual double GetFloatValue(int n) {return atof(Strp[n]);}
virtual void Reset(int n) {Strp[n] = NULL;}
// Methods
virtual void SetValue(PSZ sp, int n);
virtual void SetValue(PVAL valp, int n);
virtual void SetMin(PVAL valp, int n);
virtual void SetMax(PVAL valp, int n);
virtual void SetValue(PVBLK pv, int n1, int n2);
virtual void SetValues(PVBLK pv, int k, int n);
virtual void Move(int i, int j);
virtual int CompVal(PVAL vp, int n);
virtual int CompVal(int i1, int i2);
virtual void *GetValPtr(int n);
virtual void *GetValPtrEx(int n);
virtual int Find(PVAL vp);
virtual int GetMaxLength(void);
protected:
// Members
PSZ* const &Strp; // Pointer to PSZ buffer
}; // end of class STRBLK
/***********************************************************************/
/* Class SHRBLK: represents a block of int integer values. */
/***********************************************************************/
class SHRBLK : public VALBLK {
public:
// Constructors
SHRBLK(void *mp, int size);
// Implementation
virtual void Init(PGLOBAL g, bool check);
virtual int GetVlen(void) {return sizeof(short);}
//virtual PSZ GetCharValue(int n);
virtual short GetShortValue(int n) {return Shrp[n];}
virtual int GetIntValue(int n) {return (int)Shrp[n];}
virtual double GetFloatValue(int n) {return (double)Shrp[n];}
virtual void Reset(int n) {Shrp[n] = 0;}
// Methods
virtual void SetValue(PSZ sp, int n);
virtual void SetValue(short sval, int n) {Shrp[n] = sval;}
virtual void SetValue(int lval, int n) {Shrp[n] = (short)lval;}
virtual void SetValue(PVAL valp, int n);
virtual void SetMin(PVAL valp, int n);
virtual void SetMax(PVAL valp, int n);
virtual void SetValue(PVBLK pv, int n1, int n2);
virtual void SetValues(PVBLK pv, int k, int n);
virtual void AddMinus1(PVBLK pv, int n1, int n2);
virtual void Move(int i, int j);
virtual int CompVal(PVAL vp, int n);
virtual int CompVal(int i1, int i2);
virtual void *GetValPtr(int n);
virtual void *GetValPtrEx(int n);
virtual int Find(PVAL vp);
virtual int GetMaxLength(void);
protected:
// Members
short* const &Shrp;
}; // end of class SHRBLK
/***********************************************************************/
/* Class LNGBLK: represents a block of int integer values. */
/***********************************************************************/
class LNGBLK : public VALBLK {
public:
// Constructors
LNGBLK(void *mp, int size);
// Implementation
virtual void Init(PGLOBAL g, bool check);
virtual int GetVlen(void) {return sizeof(int);}
//virtual PSZ GetCharValue(int n);
virtual short GetShortValue(int n) {return (short)Lngp[n];}
virtual int GetIntValue(int n) {return Lngp[n];}
virtual double GetFloatValue(int n) {return (double)Lngp[n];}
virtual void Reset(int n) {Lngp[n] = 0;}
// Methods
virtual void SetValue(PSZ sp, int n);
virtual void SetValue(short sval, int n) {Lngp[n] = (int)sval;}
virtual void SetValue(int lval, int n) {Lngp[n] = lval;}
virtual void SetValue(PVAL valp, int n);
virtual void SetMin(PVAL valp, int n);
virtual void SetMax(PVAL valp, int n);
virtual void SetValue(PVBLK pv, int n1, int n2);
virtual void SetValues(PVBLK pv, int k, int n);
virtual void AddMinus1(PVBLK pv, int n1, int n2);
virtual void Move(int i, int j);
virtual int CompVal(PVAL vp, int n);
virtual int CompVal(int i1, int i2);
virtual void *GetValPtr(int n);
virtual void *GetValPtrEx(int n);
virtual int Find(PVAL vp);
virtual int GetMaxLength(void);
protected:
// Members
int* const &Lngp;
}; // end of class LNGBLK
/***********************************************************************/
/* Class DATBLK: represents a block of time stamp values. */
/***********************************************************************/
class DATBLK : public LNGBLK {
public:
// Constructor
DATBLK(void *mp, int size);
// Implementation
virtual bool SetFormat(PGLOBAL g, PSZ fmt, int len, int year = 0);
// Methods
virtual void SetValue(PSZ sp, int n);
protected:
// Members
PVAL Dvalp; // Date value used to convert string
}; // end of class DATBLK
/***********************************************************************/
/* Class DBLBLK: represents a block of double float values. */
/***********************************************************************/
class DBLBLK : public VALBLK {
public:
// Constructors
DBLBLK(void *mp, int size, int prec);
// Implementation
virtual void Init(PGLOBAL g, bool check);
virtual int GetVlen(void) {return sizeof(double);}
//virtual PSZ GetCharValue(int n);
virtual short GetShortValue(int n) {return (short)Dblp[n];}
virtual int GetIntValue(int n) {return (int)Dblp[n];}
virtual double GetFloatValue(int n) {return Dblp[n];}
virtual void Reset(int n) {Dblp[n] = 0.0;}
virtual void SetPrec(int p) {Prec = p;}
// Methods
virtual void SetValue(PSZ sp, int n);
virtual void SetValue(PVAL valp, int n);
virtual void SetMin(PVAL valp, int n);
virtual void SetMax(PVAL valp, int n);
virtual void SetValue(PVBLK pv, int n1, int n2);
virtual void SetValues(PVBLK pv, int k, int n);
virtual void Move(int i, int j);
virtual int CompVal(PVAL vp, int n);
virtual int CompVal(int i1, int i2);
virtual void *GetValPtr(int n);
virtual void *GetValPtrEx(int n);
virtual int Find(PVAL vp);
virtual int GetMaxLength(void);
protected:
// Members
double* const &Dblp;
int Prec;
}; // end of class DBLBLK
#endif // __VALBLK__H__

4099
storage/connect/value.cpp Normal file

File diff suppressed because it is too large Load Diff

496
storage/connect/value.h Normal file
View File

@@ -0,0 +1,496 @@
/**************** Value H Declares Source Code File (.H) ***************/
/* Name: VALUE.H Version 1.6 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 2001-2012 */
/* */
/* This file contains the VALUE and derived classes declares. */
/***********************************************************************/
/***********************************************************************/
/* Include required application header files */
/* assert.h is header required when using the assert function. */
/* block.h is header containing Block global declarations. */
/***********************************************************************/
#ifndef __VALUE__H__
#define __VALUE__H__
#include "assert.h"
#include "block.h"
/***********************************************************************/
/* Types used in some class definitions. */
/***********************************************************************/
enum CONV {CNV_ANY = 0, /* Convert to any type */
CNV_CHAR = 1, /* Convert to character type */
CNV_NUM = 2}; /* Convert to numeric type */
/***********************************************************************/
/* Types used in some class definitions. */
/***********************************************************************/
class CONSTANT; // For friend setting
typedef struct _datpar *PDTP; // For DTVAL
/***********************************************************************/
/* Utilities used to test types and to allocated values. */
/***********************************************************************/
int GetPLGType(int);
short GetSQLType(int);
int GetSQLCType(int);
PVAL AllocateValue(PGLOBAL, void *, short);
// Exported functions
DllExport PSZ GetTypeName(int);
DllExport int GetTypeSize(int, int);
DllExport int TranslateSQLType(int stp, int prec, int& len);
DllExport char *GetFormatType(int);
DllExport int GetFormatType(char);
DllExport int GetDBType(int);
DllExport bool IsTypeChar(int type);
DllExport bool IsTypeNum(int type);
DllExport int ConvertType(int, int, CONV, bool match = false);
DllExport PVAL AllocateValue(PGLOBAL, PVAL, int = TYPE_VOID);
DllExport PVAL AllocateValue(PGLOBAL, int, int len = 0, int prec = 2,
PSZ dom = NULL, PCATLG cat = NULL);
/***********************************************************************/
/* Class VALUE represents a constant or variable of any valid type. */
/***********************************************************************/
class DllExport VALUE : public BLOCK {
friend class CONSTANT; // The only object allowed to use SetConstFormat
public:
// Constructors
// Implementation
virtual bool IsTypeNum(void) = 0;
virtual bool IsZero(void) = 0;
virtual bool IsCi(void) {return false;}
virtual void Reset(void) = 0;
virtual int GetSize(void) = 0;
virtual int GetValLen(void) = 0;
virtual int GetValPrec(void) = 0;
virtual int GetLength(void) {return 1;}
virtual PSZ GetCharValue(void) {assert(false); return NULL;}
virtual short GetShortValue(void) {assert(false); return 0;}
virtual int GetIntValue(void) = 0;
virtual double GetFloatValue(void) = 0;
virtual void *GetTo_Val(void) = 0;
int GetType(void) {return Type;}
int GetClen(void) {return Clen;}
void SetGlobal(PGLOBAL g) {Global = g;}
// Methods
virtual bool SetValue_pval(PVAL valp, bool chktype = false) = 0;
virtual void SetValue_char(char *p, int n) = 0;
virtual void SetValue_psz(PSZ s) = 0;
virtual void SetValue_bool(bool b) {assert(false);}
virtual void SetValue(short i) {assert(false);}
virtual void SetValue(int n) {assert(false);}
virtual void SetValue(double f) {assert(false);}
virtual void SetValue_pvblk(PVBLK blk, int n) = 0;
virtual void SetBinValue(void *p) = 0;
virtual bool GetBinValue(void *buf, int buflen, bool go) = 0;
virtual void GetBinValue(void *buf, int len) = 0;
virtual bool IsEqual(PVAL vp, bool chktype) = 0;
virtual int CompareValue(PVAL vp) = 0;
virtual BYTE TestValue(PVAL vp);
virtual void Divide(int cnt) {assert(false);}
virtual void StdVar(PVAL vp, int cnt, bool b) {assert(false);}
virtual void Add(int lv) {assert(false);}
virtual void Add(PVAL vp) {assert(false);}
virtual void Add(PVBLK vbp, int i) {assert(false);}
virtual void Add(PVBLK vbp, int j, int k) {assert(false);}
virtual void Add(PVBLK vbp, int *x, int j, int k) {assert(false);}
virtual void AddSquare(PVAL vp) {assert(false);}
virtual void AddSquare(PVBLK vbp, int i) {assert(false);}
virtual void AddSquare(PVBLK vbp, int j, int k) {assert(false);}
virtual void Times(PVAL vp) {assert(false);}
virtual void SetMin(PVAL vp) = 0;
virtual void SetMin(PVBLK vbp, int i) = 0;
virtual void SetMin(PVBLK vbp, int j, int k) = 0;
virtual void SetMin(PVBLK vbp, int *x, int j, int k) = 0;
virtual void SetMax(PVAL vp) = 0;
virtual void SetMax(PVBLK vbp, int i) = 0;
virtual void SetMax(PVBLK vbp, int j, int k) = 0;
virtual void SetMax(PVBLK vbp, int *x, int j, int k) = 0;
virtual char *ShowValue(char *buf, int len = 0) = 0;
virtual char *GetCharString(char *p) = 0;
virtual char *GetShortString(char *p, int n) {return "#####";}
virtual char *GetIntString(char *p, int n) = 0;
virtual char *GetFloatString(char *p, int n, int prec) = 0;
virtual bool Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op) = 0;
virtual int GetTime(PGLOBAL g, PVAL *vp, int np) = 0;
virtual bool FormatValue(PVAL vp, char *fmt) = 0;
char *ShowTypedValue(PGLOBAL g, char *buf, int typ, int n, int p);
protected:
virtual bool SetConstFormat(PGLOBAL, FORMAT&) = 0;
// Constructor used by derived classes
VALUE(int type) : Type(type) {}
// Members
PGLOBAL Global; // To reduce arglist
//const int Type; // The value type
int Type; // The value type
int Clen; // Internal value length
}; // end of class VALUE
/***********************************************************************/
/* Class STRING: represents zero terminated strings. */
/***********************************************************************/
class STRING : public VALUE {
friend class SFROW;
public:
// Constructors
STRING(PSZ s);
STRING(PGLOBAL g, PSZ s, int n, int c = 0);
STRING(PGLOBAL g, short i);
STRING(PGLOBAL g, int n);
STRING(PGLOBAL g, double f);
// Implementation
virtual bool IsTypeNum(void) {return false;}
virtual bool IsZero(void) {return (Strp) ? strlen(Strp) == 0 : true;}
virtual bool IsCi(void) {return Ci;}
virtual void Reset(void) {*Strp = '\0';}
virtual int GetValLen(void) {return Len;}
virtual int GetValPrec() {return (Ci) ? 1 : 0;}
virtual int GetLength(void) {return Len;}
virtual int GetSize(void) {return (Strp) ? strlen(Strp) : 0;}
virtual PSZ GetCharValue(void) {return Strp;}
virtual short GetShortValue(void) {return (short)atoi(Strp);}
virtual int GetIntValue(void) {return atol(Strp);}
virtual double GetFloatValue(void) {return atof(Strp);}
virtual void *GetTo_Val(void) {return Strp;}
// Methods
virtual bool SetValue_pval(PVAL valp, bool chktype);
virtual void SetValue_char(char *p, int n);
virtual void SetValue_psz(PSZ s);
virtual void SetValue_pvblk(PVBLK blk, int n);
virtual void SetValue(short i);
virtual void SetValue(int n);
virtual void SetValue(double f);
virtual void SetBinValue(void *p);
virtual bool GetBinValue(void *buf, int buflen, bool go);
virtual void GetBinValue(void *buf, int len);
virtual char *ShowValue(char *buf, int);
virtual char *GetCharString(char *p);
virtual char *GetShortString(char *p, int n);
virtual char *GetIntString(char *p, int n);
virtual char *GetFloatString(char *p, int n, int prec = -1);
virtual bool IsEqual(PVAL vp, bool chktype);
virtual int CompareValue(PVAL vp);
virtual BYTE TestValue(PVAL vp);
virtual void SetMin(PVAL vp);
virtual void SetMin(PVBLK vbp, int i);
virtual void SetMin(PVBLK vbp, int j, int k);
virtual void SetMin(PVBLK vbp, int *x, int j, int k);
virtual void SetMax(PVAL vp);
virtual void SetMax(PVBLK vbp, int i);
virtual void SetMax(PVBLK vbp, int j, int k);
virtual void SetMax(PVBLK vbp, int *x, int j, int k);
virtual bool SetConstFormat(PGLOBAL, FORMAT&);
virtual bool Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op);
virtual int GetTime(PGLOBAL g, PVAL *vp, int np);
virtual bool FormatValue(PVAL vp, char *fmt);
virtual void Print(PGLOBAL g, FILE *, uint);
virtual void Print(PGLOBAL g, char *, uint);
protected:
// Default constructor not to be used
STRING(void) : VALUE(TYPE_ERROR) {}
// Members
PSZ Strp;
int Len;
bool Ci; // true if case insensitive
}; // end of class STRING
/***********************************************************************/
/* Class SHVAL: represents short integer values. */
/***********************************************************************/
class SHVAL : public VALUE {
public:
// Constructors
SHVAL(PSZ s);
SHVAL(short n);
SHVAL(int n);
SHVAL(double f);
// Implementation
virtual bool IsTypeNum(void) {return true;}
virtual bool IsZero(void) {return Sval == 0;}
virtual void Reset(void) {Sval = 0;}
virtual int GetValLen(void);
virtual int GetValPrec() {return 0;}
virtual int GetSize(void) {return sizeof(short);}
//virtual PSZ GetCharValue(void) {}
virtual short GetShortValue(void) {return Sval;}
virtual int GetIntValue(void) {return (int)Sval;}
virtual double GetFloatValue(void) {return (double)Sval;}
virtual void *GetTo_Val(void) {return &Sval;}
// Methods
virtual bool SetValue_pval(PVAL valp, bool chktype);
virtual void SetValue_char(char *p, int n);
virtual void SetValue_psz(PSZ s);
virtual void SetValue_bool(bool b) {Sval = (b) ? 1 : 0;}
virtual void SetValue(short i) {Sval = i;}
virtual void SetValue(int n) {Sval = (short)n;}
virtual void SetValue_pvblk(PVBLK blk, int n);
virtual void SetBinValue(void *p);
virtual bool GetBinValue(void *buf, int buflen, bool go);
virtual void GetBinValue(void *buf, int len);
virtual char *ShowValue(char *buf, int);
virtual char *GetCharString(char *p);
virtual char *GetShortString(char *p, int n);
virtual char *GetIntString(char *p, int n);
virtual char *GetFloatString(char *p, int n, int prec = -1);
virtual bool IsEqual(PVAL vp, bool chktype);
virtual int CompareValue(PVAL vp);
virtual void Divide(int cnt);
virtual void StdVar(PVAL vp, int cnt, bool b);
virtual void Add(int lv) {Sval += (short)lv;}
virtual void Add(PVAL vp);
virtual void Add(PVBLK vbp, int i);
virtual void Add(PVBLK vbp, int j, int k);
virtual void Add(PVBLK vbp, int *x, int j, int k);
virtual void AddSquare(PVAL vp);
virtual void AddSquare(PVBLK vbp, int i);
virtual void AddSquare(PVBLK vbp, int j, int k);
virtual void Times(PVAL vp);
virtual void SetMin(PVAL vp);
virtual void SetMin(PVBLK vbp, int i);
virtual void SetMin(PVBLK vbp, int j, int k);
virtual void SetMin(PVBLK vbp, int *x, int j, int k);
virtual void SetMax(PVAL vp);
virtual void SetMax(PVBLK vbp, int i);
virtual void SetMax(PVBLK vbp, int j, int k);
virtual void SetMax(PVBLK vbp, int *x, int j, int k);
virtual bool SetConstFormat(PGLOBAL, FORMAT&);
virtual bool Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op);
virtual int GetTime(PGLOBAL g, PVAL *vp, int np) {return 0;}
virtual bool FormatValue(PVAL vp, char *fmt);
virtual void Print(PGLOBAL g, FILE *, uint);
virtual void Print(PGLOBAL g, char *, uint);
protected:
short SafeAdd(short n1, short n2);
short SafeMult(short n1, short n2);
// Default constructor not to be used
SHVAL(void) : VALUE(TYPE_ERROR) {}
// Members
short Sval;
}; // end of class SHVAL
/***********************************************************************/
/* Class INTVAL: represents int integer values. */
/***********************************************************************/
class DllExport INTVAL : public VALUE {
public:
// Constructors
INTVAL(PSZ s);
INTVAL(short i);
INTVAL(int n);
INTVAL(double f);
// Implementation
virtual bool IsTypeNum(void) {return true;}
virtual bool IsZero(void) {return Ival == 0;}
virtual void Reset(void) {Ival = 0;}
virtual int GetValLen(void);
virtual int GetValPrec() {return 0;}
virtual int GetSize(void) {return sizeof(int);}
//virtual PSZ GetCharValue(void) {}
virtual short GetShortValue(void) {return (short)Ival;}
virtual int GetIntValue(void) {return Ival;}
virtual double GetFloatValue(void) {return (double)Ival;}
virtual void *GetTo_Val(void) {return &Ival;}
// Methods
virtual bool SetValue_pval(PVAL valp, bool chktype);
virtual void SetValue_char(char *p, int n);
virtual void SetValue_psz(PSZ s);
virtual void SetValue_bool(bool b) {Ival = (b) ? 1 : 0;}
virtual void SetValue(short i) {Ival = (int)i;}
virtual void SetValue(int n) {Ival = n;}
virtual void SetValue(double f) {Ival = (int)f;}
virtual void SetValue_pvblk(PVBLK blk, int n);
virtual void SetBinValue(void *p);
virtual bool GetBinValue(void *buf, int buflen, bool go);
virtual void GetBinValue(void *buf, int len);
virtual char *ShowValue(char *buf, int);
virtual char *GetCharString(char *p);
virtual char *GetShortString(char *p, int n);
virtual char *GetIntString(char *p, int n);
virtual char *GetFloatString(char *p, int n, int prec = -1);
virtual bool IsEqual(PVAL vp, bool chktype);
virtual int CompareValue(PVAL vp);
virtual void Divide(int cnt);
virtual void StdVar(PVAL vp, int cnt, bool b);
virtual void Add(int lv) {Ival += lv;}
virtual void Add(PVAL vp);
virtual void Add(PVBLK vbp, int i);
virtual void Add(PVBLK vbp, int j, int k);
virtual void Add(PVBLK vbp, int *x, int j, int k);
virtual void AddSquare(PVAL vp);
virtual void AddSquare(PVBLK vbp, int i);
virtual void AddSquare(PVBLK vbp, int j, int k);
virtual void Times(PVAL vp);
virtual void SetMin(PVAL vp);
virtual void SetMin(PVBLK vbp, int i);
virtual void SetMin(PVBLK vbp, int j, int k);
virtual void SetMin(PVBLK vbp, int *x, int j, int k);
virtual void SetMax(PVAL vp);
virtual void SetMax(PVBLK vbp, int i);
virtual void SetMax(PVBLK vbp, int j, int k);
virtual void SetMax(PVBLK vbp, int *x, int j, int k);
virtual bool SetConstFormat(PGLOBAL, FORMAT&);
virtual bool Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op);
virtual int GetTime(PGLOBAL g, PVAL *vp, int np);
virtual bool FormatValue(PVAL vp, char *fmt);
virtual void Print(PGLOBAL g, FILE *, uint);
virtual void Print(PGLOBAL g, char *, uint);
protected:
int SafeAdd(int n1, int n2);
int SafeMult(int n1, int n2);
// Default constructor not to be used
INTVAL(void) : VALUE(TYPE_ERROR) {}
// Members
int Ival;
}; // end of class INTVAL
/***********************************************************************/
/* Class DTVAL: represents a time stamp value. */
/***********************************************************************/
class DllExport DTVAL : public INTVAL {
public:
// Constructors
DTVAL(PGLOBAL g, int n, int p, PSZ fmt);
DTVAL(PGLOBAL g, PSZ s, int n);
DTVAL(PGLOBAL g, short i);
DTVAL(PGLOBAL g, int n);
DTVAL(PGLOBAL g, double f);
// Implementation
virtual bool SetValue_pval(PVAL valp, bool chktype);
virtual void SetValue_char(char *p, int n);
virtual void SetValue_psz(PSZ s);
virtual void SetValue_pvblk(PVBLK blk, int n);
virtual char *GetCharString(char *p);
virtual char *ShowValue(char *buf, int);
virtual bool Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op);
virtual int GetTime(PGLOBAL g, PVAL *vp, int np);
virtual bool FormatValue(PVAL vp, char *fmt);
bool SetFormat(PGLOBAL g, PSZ fmt, int len, int year = 0);
bool SetFormat(PGLOBAL g, PVAL valp);
bool IsFormatted(void) {return Pdtp != NULL;}
bool GetTmMember(OPVAL op, int& mval);
bool DateDiff(DTVAL *dtp, OPVAL op, int& tdif);
bool MakeTime(struct tm *ptm);
static void SetTimeShift(void);
static int GetShift(void) {return Shift;}
// Methods
bool MakeDate(PGLOBAL g, int *val, int nval);
bool WeekNum(PGLOBAL g, int& nval);
struct tm *GetGmTime(void);
protected:
// Default constructor not to be used
DTVAL(void) : INTVAL() {}
// Members
static int Shift; // Time zone shift in seconds
PDTP Pdtp; // To the DATPAR structure
char *Sdate; // Utility char buffer
//struct tm *DateTime; // Utility (not used yet)
int DefYear; // Used by ExtractDate
int Len; // Used by CHAR scalar function
}; // end of class DTVAL
/***********************************************************************/
/* Class DFVAL: represents double float values. */
/***********************************************************************/
class DFVAL : public VALUE {
public:
// Constructors
DFVAL(PSZ s, int prec = 2);
DFVAL(short i, int prec = 2);
DFVAL(int n, int prec = 2);
DFVAL(double f, int prec = 2);
// Implementation
virtual bool IsTypeNum(void) {return true;}
virtual bool IsZero(void) {return Fval == 0.0;}
virtual void Reset(void) {Fval = 0.0;}
virtual int GetValLen(void);
virtual int GetValPrec() {return Prec;}
virtual int GetSize(void) {return sizeof(double);}
//virtual PSZ GetCharValue(void) {}
virtual short GetShortValue(void) {return (short)Fval;}
virtual int GetIntValue(void) {return (int)Fval;}
virtual double GetFloatValue(void) {return Fval;}
virtual void *GetTo_Val(void) {return &Fval;}
void SetPrec(int prec) {Prec = prec;}
// Methods
virtual bool SetValue_pval(PVAL valp, bool chktype);
virtual void SetValue_char(char *p, int n);
virtual void SetValue_psz(PSZ s);
virtual void SetValue(short i) {Fval = (double)i;}
virtual void SetValue(int n) {Fval = (double)n;}
virtual void SetValue(double f) {Fval = f;}
virtual void SetValue_pvblk(PVBLK blk, int n);
virtual void SetBinValue(void *p);
virtual bool GetBinValue(void *buf, int buflen, bool go);
virtual void GetBinValue(void *buf, int len);
virtual char *ShowValue(char *buf, int);
virtual char *GetCharString(char *p);
virtual char *GetShortString(char *p, int n);
virtual char *GetIntString(char *p, int n);
virtual char *GetFloatString(char *p, int n, int prec = -1);
virtual bool IsEqual(PVAL vp, bool chktype);
virtual int CompareValue(PVAL vp);
virtual void Divide(int cnt);
virtual void StdVar(PVAL vp, int cnt, bool b);
virtual void Add(PVAL vp);
virtual void Add(PVBLK vbp, int i);
virtual void Add(PVBLK vbp, int j, int k);
virtual void Add(PVBLK vbp, int *x, int j, int k);
virtual void AddSquare(PVAL vp);
virtual void AddSquare(PVBLK vbp, int i);
virtual void AddSquare(PVBLK vbp, int j, int k);
virtual void Times(PVAL vp);
virtual void SetMin(PVAL vp);
virtual void SetMin(PVBLK vbp, int i);
virtual void SetMin(PVBLK vbp, int j, int k);
virtual void SetMin(PVBLK vbp, int *x, int j, int k);
virtual void SetMax(PVAL vp);
virtual void SetMax(PVBLK vbp, int i);
virtual void SetMax(PVBLK vbp, int j, int k);
virtual void SetMax(PVBLK vbp, int *x, int j, int k);
virtual bool SetConstFormat(PGLOBAL, FORMAT&);
virtual bool Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op);
virtual int GetTime(PGLOBAL g, PVAL *vp, int np);
virtual bool FormatValue(PVAL vp, char *fmt);
virtual void Print(PGLOBAL g, FILE *, uint);
virtual void Print(PGLOBAL g, char *, uint);
// Specific function
void Divide(double div) {Fval /= div;}
protected:
// Default constructor not to be used
DFVAL(void) : VALUE(TYPE_ERROR) {}
// Members
double Fval;
int Prec;
}; // end of class DFVAL
#endif

3126
storage/connect/xindex.cpp Normal file

File diff suppressed because it is too large Load Diff

487
storage/connect/xindex.h Normal file
View File

@@ -0,0 +1,487 @@
/*************** Xindex H Declares Source Code File (.H) ***************/
/* Name: XINDEX.H Version 3.4 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 2004 - 2012 */
/* */
/* This file contains the XINDEX class declares. */
/***********************************************************************/
#ifndef __XINDEX_H__
#define __XINDEX_H__
#include "block.h"
#include "csort.h" /* Base class declares */
#include "xtable.h"
#include "valblk.h"
enum IDT {TYPE_IDX_ERROR = 0, /* Type not defined */
TYPE_IDX_INDX = 4, /* Permanent standard index */
TYPE_IDX_XROW = 5}; /* Permanent row index */
typedef struct mem_map *MMP;
typedef class INDEXDEF *PIXDEF;
typedef class KPARTDEF *PKPDEF;
typedef class XINDEX *PXINDEX;
typedef class XLOAD *PXLOAD;
typedef class KXYCOL *PXCOL;
/***********************************************************************/
/* Structures used when checking for possible indexing */
/***********************************************************************/
typedef struct index_col *PICOL;
typedef struct index_val *PIVAL;
typedef struct index_def *PINDX;
typedef struct indx_used *PXUSED;
typedef struct index_val : public BLOCK {
index_val(PXOB xp) {Next = NULL; Xval = xp; Kp = NULL;}
PIVAL Next; // Next value
PXOB Xval; // To value or array
int *Kp; // The coordonates in a LSTBLK
} IVAL;
typedef struct index_col : public BLOCK {
index_col(PCOL cp)
{Next = Nxtgrp = NULL; Colp = cp; Ngrp = N = 0; Vals = NULL;}
PICOL Next; // Next column
PICOL Nxtgrp; // Next group
PCOL Colp; // The column
PIVAL Vals; // To column values
int Ngrp; // Group number of values
int N; // Column number of values
} ICOL;
typedef struct index_def : public BLOCK {
index_def(PIXDEF xdp)
{Next = NULL; Pxdf = xdp; Cols = NULL; Alloc = false;}
PINDX Next;
PIXDEF Pxdf;
PICOL Cols;
bool Alloc; // Must allocate values
} INDX;
/***********************************************************************/
/* Index definition block. */
/***********************************************************************/
class DllExport INDEXDEF : public BLOCK { /* Index description block */
friend class PLUGCAT;
friend class DOSDEF;
friend int PlgMakeIndex(PGLOBAL g, PSZ name, PIXDEF pxdf, bool add);
public:
// Constructor
INDEXDEF(char *name, bool uniq = false, int n = 0);
// Implementation
PIXDEF GetNext(void) {return Next;}
void SetNext(PIXDEF pxdf) {Next = pxdf;}
PSZ GetName(void) {return (PSZ)Name;}
bool IsUnique(void) {return Unique;}
bool IsAuto(void) {return AutoInc;}
void SetAuto(bool b) {AutoInc = b;}
void SetInvalid(bool b) {Invalid = b;}
int GetNparts(void) {return Nparts;}
int GetID(void) {return ID;}
void SetID(int n) {ID = n;}
PKPDEF GetToKeyParts(void) {return ToKeyParts;}
void SetToKeyParts(PKPDEF kp) {ToKeyParts = kp;}
void SetNParts(uint np) {Nparts = (signed)np;}
void SetMaxSame(int mxs) {MaxSame = mxs;}
void SetMxsame(PXINDEX x);
int GetOffset(void) {return Offset;}
void SetOffset(int off) {Offset = off;}
int GetOffhigh(void) {return Offhigh;}
void SetOffhigh(int hof) {Offhigh = hof;}
int GetSize(void) {return Size;}
void SetSize(int size) {Size = size;}
int GetMaxSame(void) {return MaxSame;}
bool Define(PGLOBAL g, void *memp, PTABDEF dfp, LPCSTR p);
PIXDEF GetIndexOf(PCOL colp, bool hd = false);
int IsIndexOf(PCOL colp);
PKXBASE CheckIndexing(PGLOBAL g, PTDBDOS tdbp);
PINDX CheckAND(PGLOBAL g, PINDX pix1, PINDX pix2);
PINDX CheckOR(PGLOBAL g, PINDX pix1, PINDX pix2);
PINDX CheckEQ(PGLOBAL g, PTDB tdbp, PXOB *arg, int op, int *kp = NULL);
bool TestEQ(PGLOBAL g, PTDB tdbp, PXOB *arg, int op, bool b = false);
protected:
PIXDEF Next; /* To next block */
PKPDEF ToKeyParts; /* To the key part definitions */
char *Name; /* Index name */
bool Unique; /* true if defined as unique */
bool Invalid; /* true if marked as Invalid */
bool AutoInc; /* true if unique key in auto increment */
int Nparts; /* Number of key parts */
int ID; /* Index ID number */
int Offset; /* Offset in index file */
int Offhigh; /* Offset high in big index file */
int Size; /* Size of index file */
int MaxSame; /* Max number of same values */
}; // end of INDEXDEF
typedef struct indx_used : public BLOCK {
indx_used(PTDB tp, PIXDEF xdp, PCOL *cp, int k)
{Tname = (char*)tp->GetName(); Xname = xdp->GetName(); Cp = cp; K = k;}
PXUSED Next;
char *Tname;
PSZ Xname;
PCOL *Cp;
int K;
} XUSED;
/***********************************************************************/
/* Index Key Part definition block. */
/***********************************************************************/
class DllExport KPARTDEF : public BLOCK { /* Index Key Part desc block */
friend class INDEXDEF;
friend class XINDEX;
friend class PLUGCAT;
friend class DOSDEF;
friend int PlgMakeIndex(PGLOBAL g, PSZ name, PIXDEF pxdf, bool add);
public:
KPARTDEF(PSZ name, int n); // Constructor
// Implementation
PKPDEF GetNext(void) {return Next;}
PSZ GetName(void) {return (PSZ)Name;}
int GetNcol(void) {return Ncol;}
void SetNext(PKPDEF pkdf) {Next = pkdf;}
void SetKlen(int len) {Klen = len;}
void SetMxsame(int mxs) {Mxsame = mxs;}
protected:
PKPDEF Next; /* To next block */
PSZ Name; /* Field name */
int Mxsame; /* Field max same values */
int Ncol; /* Field number */
int Klen; /* Key length */
}; // end of KPARTDEF
/***********************************************************************/
/* This is the XDB Index virtual base class declaration. */
/***********************************************************************/
class DllExport XXBASE : public CSORT, public BLOCK {
friend class INDEXDEF;
friend class KXYCOL;
public:
// Constructor
XXBASE(PTDBDOS tbxp, bool b);
// Implementation
virtual IDT GetType(void) = 0;
virtual void Reset(void) = 0;
virtual bool IsMul(void) {return false;}
virtual bool IsRandom(void) {return true;}
virtual bool HaveSame(void) {return false;}
virtual int GetCurPos(void) {return Cur_K;}
virtual void SetNval(int n) {assert(n == 1);}
virtual void SetOp(OPVAL op) {Op = op;}
int GetNdif(void) {return Ndif;}
int GetNum_K(void) {return Num_K;}
int GetCur_K(void) {return Cur_K;}
int GetID(void) {return ID;}
void SetID(int id) {ID = id;}
void SetNth(int n) {Nth = n;}
int *GetPof(void) {return Pof;}
int *GetPex(void) {return Pex;}
void FreeIndex(void) {PlgDBfree(Index);}
// Methods
virtual void Print(PGLOBAL g, FILE *f, uint n);
virtual void Print(PGLOBAL g, char *ps, uint z);
virtual bool Init(PGLOBAL g) = 0;
virtual int MaxRange(void) {return 1;}
virtual int Fetch(PGLOBAL g) = 0;
virtual bool NextVal(bool eq) {return true;}
virtual int FastFind(int nk) = 0;
virtual bool Reorder(PGLOBAL g) {return true;}
virtual int Range(PGLOBAL g, int limit = 0, bool incl = true)
{return -1;} // Means error
virtual int Qcompare(int *, int *) = 0;
virtual int GroupSize(void) {return 1;}
virtual void Close(void) = 0;
protected:
// Members
PTDBASE Tbxp; // Points to calling table TDB
PXCOL To_KeyCol; // To KeyCol class list
MBLOCK Record; // Record allocation block
int* &To_Rec; // We are using ftell, fseek
int Cur_K; // Index of current record
int Old_K; // Index of last record
int Num_K; // Size of Rec_K pointer array
int Ndif; // Number of distinct values
int Bot; // Bottom of research index
int Top; // Top of research index
int Inf, Sup; // Used for block optimization
OPVAL Op; // Search operator
bool Mul; // true if multiple
bool Srtd; // true for sorted column
int Val_K; // Index of current value
int Nblk; // Number of blocks
int Sblk; // Block size
int Thresh; // Thresh for sorting join indexes
int ID; // Index ID number
int Nth; // Nth constant to fetch
}; // end of class XXBASE
/***********************************************************************/
/* This is the standard (multicolumn) Index class declaration. */
/***********************************************************************/
class DllExport XINDEX : public XXBASE {
friend class KXYCOL;
public:
// Constructor
XINDEX(PTDBDOS tdbp, PIXDEF xdp, PXLOAD pxp,
PCOL *cp, PXOB *xp = NULL, int k = 0);
// Implementation
virtual IDT GetType(void) {return TYPE_IDX_INDX;}
virtual bool IsMul(void) {return (Nval < Nk) ? true : Mul;}
virtual bool HaveSame(void) {return Op == OP_SAME;}
virtual int GetCurPos(void) {return (Pex) ? Pex[Cur_K] : Cur_K;}
virtual void SetNval(int n) {Nval = n;}
int GetMaxSame(void) {return MaxSame;}
int GetDefoff(void) {return Defoff;}
int GetDefhigh(void) {return Defhigh;}
int GetSize(void) {return Size;}
// Methods
virtual void Reset(void);
virtual bool Init(PGLOBAL g);
virtual int Qcompare(int *, int *);
virtual int Fetch(PGLOBAL g);
virtual int FastFind(int nk);
virtual int GroupSize(void);
virtual int Range(PGLOBAL g, int limit = 0, bool incl = true);
virtual int MaxRange(void) {return MaxSame;}
virtual int ColMaxSame(PXCOL kp);
virtual void Close(void);
virtual bool NextVal(bool eq);
virtual bool Make(PGLOBAL g, PIXDEF sxp);
virtual bool SaveIndex(PGLOBAL g, PIXDEF sxp);
virtual bool Reorder(PGLOBAL g);
bool GetAllSizes(PGLOBAL g, int &ndif, int &numk);
protected:
bool NextValDif(void);
// Members
PIXDEF Xdp; // To index definition
PTDBDOS Tdbp; // Points to calling table TDB
PXLOAD X; // To XLOAD class
PXCOL To_LastCol; // To the last key part block
PXCOL To_LastVal; // To the last used key part block
PCOL *To_Cols; // To array of indexed columns
PXOB *To_Vals; // To array of column values
int Nk; // The number of indexed columns
int Nval; // The number of used columns
int Incr; // Increment of record position
int Defoff; // Offset of definition in index file
int Defhigh; // High order of offset big value
int Size; // Size of definition in index file
int MaxSame; // Max number of same values
}; // end of class XINDEX
/***********************************************************************/
/* This is the fast single column index class declaration. */
/***********************************************************************/
class DllExport XINDXS : public XINDEX {
friend class KXYCOL;
public:
// Constructor
XINDXS(PTDBDOS tdbp, PIXDEF xdp, PXLOAD pxp, PCOL *cp, PXOB *xp = NULL);
// Implementation
virtual void SetNval(int n) {assert(n == 1);}
// Methods
virtual int Qcompare(int *, int *);
virtual int Fetch(PGLOBAL g);
virtual int FastFind(int nk);
virtual bool NextVal(bool eq);
virtual int Range(PGLOBAL g, int limit = 0, bool incl = true);
virtual int GroupSize(void);
protected:
// Members
}; // end of class XINDXS
/***********************************************************************/
/* This is the saving/loading index utility base class. */
/***********************************************************************/
class DllExport XLOAD : public BLOCK {
friend class XBIGEX;
friend class XBIGXS;
public:
// Constructor
XLOAD(void);
// Methods
virtual bool Open(PGLOBAL g, char *filename, MODE mode) = 0;
virtual bool GetOff(int& low, int& high, PIXDEF sxp) = 0;
virtual bool Seek(PGLOBAL g, int low, int high, int origin) = 0;
virtual bool Read(PGLOBAL g, void *buf, int n, int size) = 0;
virtual int Write(PGLOBAL g, void *buf, int n,
int size, bool& rc) = 0;
virtual void Close(void);
#if defined(XMAP)
virtual void *FileView(PGLOBAL g, char *fn, int loff,
int hoff, int size) = 0;
#endif // XMAP
protected:
// Members
#if defined(WIN32)
HANDLE Hfile; // Handle to file or map
#if defined(XMAP)
void *ViewBase; // Mapped view base address
#endif // XMAP
#else // UNIX
int Hfile; // Descriptor to file or map
#endif // UNIX
}; // end of class XLOAD
/***********************************************************************/
/* This is the saving/loading indexes utility class. */
/***********************************************************************/
class DllExport XFILE : public XLOAD {
public:
// Constructor
XFILE(void);
// Methods
virtual bool Open(PGLOBAL g, char *filename, MODE mode);
virtual bool GetOff(int& low, int& high, PIXDEF sxp);
virtual bool Seek(PGLOBAL g, int low, int high, int origin);
virtual bool Read(PGLOBAL g, void *buf, int n, int size);
virtual int Write(PGLOBAL g, void *buf, int n, int size, bool& rc);
virtual void Close(void);
#if defined(XMAP)
virtual void *FileView(PGLOBAL g, char *fn, int loff,
int hoff, int size);
#endif // XMAP
protected:
// Members
FILE *Xfile; // Index stream file
#if defined(XMAP) && !defined(WIN32)
MMP Mmp; // To UNIX mapped index file
#endif // XMAP
}; // end of class XFILE
/***********************************************************************/
/* This is the saving/loading huge indexes utility class. */
/***********************************************************************/
class DllExport XHUGE : public XLOAD {
public:
// Constructor
XHUGE(void) : XLOAD() {}
// Methods
virtual bool Open(PGLOBAL g, char *filename, MODE mode);
virtual bool GetOff(int& low, int& high, PIXDEF sxp);
virtual bool Seek(PGLOBAL g, int low, int high, int origin);
virtual bool Read(PGLOBAL g, void *buf, int n, int size);
virtual int Write(PGLOBAL g, void *buf, int n, int size, bool& rc);
#if defined(XMAP)
virtual void *FileView(PGLOBAL g, char *fn, int loff,
int hoff, int size);
#endif // XMAP
protected:
// Members
}; // end of class XHUGE
/***********************************************************************/
/* This is the XDB index for columns containing ROWID values. */
/***********************************************************************/
class DllExport XXROW : public XXBASE {
friend class KXYCOL;
public:
// Constructor
XXROW(PTDBDOS tbxp);
// Implementation
virtual IDT GetType(void) {return TYPE_IDX_XROW;}
virtual void Reset(void);
// Methods
virtual bool Init(PGLOBAL g);
virtual int Fetch(PGLOBAL g);
virtual int FastFind(int nk);
virtual int MaxRange(void) {return 1;}
virtual int Range(PGLOBAL g, int limit = 0, bool incl = true);
virtual int Qcompare(int *, int *) {assert(false); return 0;}
virtual void Close(void) {}
protected:
// Members
PTDBDOS Tdbp; // Points to calling table TDB
PVAL Valp; // The value to match in index
}; // end of class XXROW
/***********************************************************************/
/* Definition of class KXYCOL used to store values of indexed columns */
/***********************************************************************/
class KXYCOL: public BLOCK {
friend class INDEXDEF;
friend class XINDEX;
friend class XINDXS;
friend class XBIGEX;
friend class XBIGXS;
friend class TDBDOS;
public:
// Constructors
KXYCOL(PKXBASE kp);
// Implementation
int GetType(void) {return Type;}
void SetValue(PCOL colp, int i);
public:
// Methods
virtual bool Init(PGLOBAL g, PCOL colp, int n, bool sm, int kln);
virtual bool InitFind(PGLOBAL g, PXOB xp);
virtual void ReAlloc(PGLOBAL g, int n);
virtual void FreeData(void);
virtual void FillValue(PVAL valp);
virtual int CompVal(int i);
void InitBinFind(void *vp);
bool MakeBlockArray(PGLOBAL g, int nb, int size);
int Compare(int i1, int i2);
int CompBval(int i);
void Save(int i) {Valp->SetBinValue(Kblp->GetValPtr(i));}
void Restore(int j) {Kblp->SetValue(Valp, j);}
void Move(int j, int k) {Kblp->Move(k, j);}
// Specific functions
#if defined(XMAP)
BYTE *MapInit(PGLOBAL g, PCOL colp, int *n, BYTE *m);
#endif // XMAP
int *MakeOffset(PGLOBAL g, int n);
protected:
// Members
PXCOL Next; // To next in the key part list
PXCOL Previous; // To previous in the key part list
PKXBASE Kxp; // To the INDEX class block
PCOL Colp; // To matching object if a column
bool IsSorted; // true if column is already sorted
bool Asc; // true for ascending sort, false for Desc
MBLOCK Keys; // Data array allocation block
void* &To_Keys; // To data array
PVBLK Kblp; // To Valblock of the data array
MBLOCK Bkeys; // Block array allocation block
void* &To_Bkeys; // To block array
PVBLK Blkp; // To Valblock of the block array
PVAL Valp; // Value use by Find
int Klen; // Length of character string or num value
int Kprec; // The Value(s) precision or CI
int Type; // The Value(s) type
bool Prefix; // Key on CHAR column prefix
MBLOCK Koff; // Offset allocation block
CPINT &Kof; // Reference to offset array
int Val_K; // Index of current column value
int Ndf; // Number of stored values
int Mxs; // Max same for this column
}; // end of class KXYCOL
#endif // __XINDEX_H__

Some files were not shown because too many files have changed in this diff Show More