diff options
Diffstat (limited to 'storage/connect/mycat.cc')
-rw-r--r-- | storage/connect/mycat.cc | 1314 |
1 files changed, 657 insertions, 657 deletions
diff --git a/storage/connect/mycat.cc b/storage/connect/mycat.cc index 073c16f18ec..706f41780fe 100644 --- a/storage/connect/mycat.cc +++ b/storage/connect/mycat.cc @@ -1,657 +1,657 @@ -/* 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.3 */
-/* */
-/* Author: Olivier Bertrand 2012 - 2013 */
-/* */
-/* 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"
-
-/**************************************************************************/
-/* Extern static variables. */
-/**************************************************************************/
-#if defined(WIN32)
-extern "C" HINSTANCE s_hModule; // Saved module handle
-#endif // !WIN32
-
-extern int xtrace;
-
-/**************************************************************************/
-/* 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, ...);
-
-/**************************************************************************/
-/* Allocate the result structure that will contain result data. */
-/**************************************************************************/
-PQRYRES PlgAllocResult(PGLOBAL g, int ncol, int maxres, int ids,
- int *dbtype, int *buftyp, unsigned int *length,
- bool blank = false, bool nonull = false)
- {
- char cname[NAM_LEN+1];
- int i;
- PCOLRES *pcrp, crp;
- PQRYRES qrp;
-
- /************************************************************************/
- /* Allocate the structure used to contain the result set. */
- /************************************************************************/
- qrp = (PQRYRES)PlugSubAlloc(g, NULL, sizeof(QRYRES));
- pcrp = &qrp->Colresp;
- qrp->Continued = false;
- qrp->Truncated = false;
- qrp->Info = false;
- qrp->Suball = true;
- qrp->Maxres = maxres;
- qrp->Maxsize = 0;
- qrp->Nblin = 0;
- qrp->Nbcol = 0; // will be ncol
- qrp->Cursor = 0;
- qrp->BadLines = 0;
-
- for (i = 0; i < ncol; i++) {
- *pcrp = (PCOLRES)PlugSubAlloc(g, NULL, sizeof(COLRES));
- crp = *pcrp;
- pcrp = &crp->Next;
- crp->Colp = NULL;
- crp->Ncol = ++qrp->Nbcol;
- crp->Type = buftyp[i];
- crp->Length = length[i];
- crp->Clen = GetTypeSize(crp->Type, length[i]);
- crp->Prec = 0;
- crp->DBtype = dbtype[i];
-
- if (ids > 0) {
-#if defined(XMSG)
- // Get header from message file
- strncpy(cname, PlugReadMessage(g, ids + crp->Ncol, NULL), NAM_LEN);
- cname[NAM_LEN] = 0; // for truncated long names
-#elif defined(WIN32)
- // Get header from ressource file
- LoadString(s_hModule, ids + crp->Ncol, cname, sizeof(cname));
-#else // !WIN32
- GetRcString(ids + crp->Ncol, cname, sizeof(cname));
-#endif // !WIN32
- crp->Name = (PSZ)PlugSubAlloc(g, NULL, strlen(cname) + 1);
- strcpy(crp->Name, cname);
- } else
- crp->Name = NULL; // Will be set by caller
-
- // Allocate the Value Block that will contain data
- if (crp->Length || nonull)
- crp->Kdata = AllocValBlock(g, NULL, crp->Type, maxres,
- crp->Length, 0, true, blank);
- else
- crp->Kdata = NULL;
-
- if (g->Trace)
- htrc("Column(%d) %s type=%d len=%d value=%p\n",
- crp->Ncol, crp->Name, crp->Type, crp->Length, crp->Kdata);
-
- } // endfor i
-
- *pcrp = NULL;
-
- return qrp;
- } // end of PlgAllocResult
-
-/***********************************************************************/
-/* Get a unique char identifier for types. The letter used are: */
-/* ABCDEF..I.KLM.O..R.T.VWXY.. */
-/***********************************************************************/
-char GetTypeID(char *type)
- {
- return (!type) ? 'D' // DOS (default)
- : (!stricmp(type, "FMT")) ? 'T' // CSV
- : (!stricmp(type, "DIR")) ? 'R' // diR
- : (!stricmp(type, "DBF")) ? 'A' // dbAse
- : (!stricmp(type, "SYS")) ? 'I' // INI
- : (!stricmp(type, "TBL")) ? 'L' // tbL
- : (!stricmp(type, "MYSQL")) ? 'Y' // mYsql
- : (!stricmp(type, "OEM")) ? 'E' : toupper(*type);
- } // end of GetTypeID
-
-/* ------------------------- 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 type
- char tc= GetTypeID(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 'T':
- case 'C':
- // 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)
- {
- char tc;
- 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 */
- /*********************************************************************/
- tc= GetTypeID((char*)am);
-
- switch (tc) {
- case 'F':
- case 'B':
- case 'A':
- case 'D': tdp= new(g) DOSDEF; break;
- case 'T':
- 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 --------------------------- */
+/* 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.3 */ +/* */ +/* Author: Olivier Bertrand 2012 - 2013 */ +/* */ +/* 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" + +/**************************************************************************/ +/* Extern static variables. */ +/**************************************************************************/ +#if defined(WIN32) +extern "C" HINSTANCE s_hModule; // Saved module handle +#endif // !WIN32 + +extern int xtrace; + +/**************************************************************************/ +/* 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, ...); + +/**************************************************************************/ +/* Allocate the result structure that will contain result data. */ +/**************************************************************************/ +PQRYRES PlgAllocResult(PGLOBAL g, int ncol, int maxres, int ids, + int *dbtype, int *buftyp, unsigned int *length, + bool blank = false, bool nonull = false) + { + char cname[NAM_LEN+1]; + int i; + PCOLRES *pcrp, crp; + PQRYRES qrp; + + /************************************************************************/ + /* Allocate the structure used to contain the result set. */ + /************************************************************************/ + qrp = (PQRYRES)PlugSubAlloc(g, NULL, sizeof(QRYRES)); + pcrp = &qrp->Colresp; + qrp->Continued = false; + qrp->Truncated = false; + qrp->Info = false; + qrp->Suball = true; + qrp->Maxres = maxres; + qrp->Maxsize = 0; + qrp->Nblin = 0; + qrp->Nbcol = 0; // will be ncol + qrp->Cursor = 0; + qrp->BadLines = 0; + + for (i = 0; i < ncol; i++) { + *pcrp = (PCOLRES)PlugSubAlloc(g, NULL, sizeof(COLRES)); + crp = *pcrp; + pcrp = &crp->Next; + crp->Colp = NULL; + crp->Ncol = ++qrp->Nbcol; + crp->Type = buftyp[i]; + crp->Length = length[i]; + crp->Clen = GetTypeSize(crp->Type, length[i]); + crp->Prec = 0; + crp->DBtype = dbtype[i]; + + if (ids > 0) { +#if defined(XMSG) + // Get header from message file + strncpy(cname, PlugReadMessage(g, ids + crp->Ncol, NULL), NAM_LEN); + cname[NAM_LEN] = 0; // for truncated long names +#elif defined(WIN32) + // Get header from ressource file + LoadString(s_hModule, ids + crp->Ncol, cname, sizeof(cname)); +#else // !WIN32 + GetRcString(ids + crp->Ncol, cname, sizeof(cname)); +#endif // !WIN32 + crp->Name = (PSZ)PlugSubAlloc(g, NULL, strlen(cname) + 1); + strcpy(crp->Name, cname); + } else + crp->Name = NULL; // Will be set by caller + + // Allocate the Value Block that will contain data + if (crp->Length || nonull) + crp->Kdata = AllocValBlock(g, NULL, crp->Type, maxres, + crp->Length, 0, true, blank); + else + crp->Kdata = NULL; + + if (g->Trace) + htrc("Column(%d) %s type=%d len=%d value=%p\n", + crp->Ncol, crp->Name, crp->Type, crp->Length, crp->Kdata); + + } // endfor i + + *pcrp = NULL; + + return qrp; + } // end of PlgAllocResult + +/***********************************************************************/ +/* Get a unique char identifier for types. The letter used are: */ +/* ABCDEF..I.KLM.O..R.T.VWXY.. */ +/***********************************************************************/ +char GetTypeID(char *type) + { + return (!type) ? 'D' // DOS (default) + : (!stricmp(type, "FMT")) ? 'T' // CSV + : (!stricmp(type, "DIR")) ? 'R' // diR + : (!stricmp(type, "DBF")) ? 'A' // dbAse + : (!stricmp(type, "SYS")) ? 'I' // INI + : (!stricmp(type, "TBL")) ? 'L' // tbL + : (!stricmp(type, "MYSQL")) ? 'Y' // mYsql + : (!stricmp(type, "OEM")) ? 'E' : toupper(*type); + } // end of GetTypeID + +/* ------------------------- 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 type + char tc= GetTypeID(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 'T': + case 'C': + // 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) + { + char tc; + 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 */ + /*********************************************************************/ + tc= GetTypeID((char*)am); + + switch (tc) { + case 'F': + case 'B': + case 'A': + case 'D': tdp= new(g) DOSDEF; break; + case 'T': + 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 --------------------------- */ |