Commit f6ca3b05 authored by Olivier Bertrand's avatar Olivier Bertrand

Bug fixed: Column charset were not handled on read.

Modified: ha_connect.cc (MakeRecord)

Moved PlgAllocResult to plgdbutl.cpp
Modified:
mycat.cpp
plgdbutl.cpp

Continuing implementing the "catalog" tables (ex "info").
Already existing were the ODBC data source table and the
WMI column info table.

The common way to handle them was modified to enable each
table types to send personalized data.

Now takes care of all existing catalog functions for table
types that can retrieve and use such information.

Modified:
ha_connect.cc
odbconn.cpp
tabodbc.h
tabodbc.cpp
tabfmt.h
tabfmt.cpp
tabmysql.h
tabmysql.cpp
tabwmi.h
tabwmi.cpp
myconn.h
myconn.cpp
filamdbf.cpp
plgdbsem.h
reldef.h
reldef.cpp
tabdos.h
tabdos.cpp
tabfix.h
xtable.h
table.cpp
parent b93db097
...@@ -48,8 +48,6 @@ ...@@ -48,8 +48,6 @@
/***********************************************************************/ /***********************************************************************/
#include "global.h" #include "global.h"
#include "plgdbsem.h" #include "plgdbsem.h"
//#include "catalog.h"
//#include "kindex.h"
#include "filamdbf.h" #include "filamdbf.h"
#include "tabdos.h" #include "tabdos.h"
#include "valblk.h" #include "valblk.h"
...@@ -65,12 +63,6 @@ ...@@ -65,12 +63,6 @@
#define DBFTYPE 3 /* value of bits 0 and 1 if .dbf */ #define DBFTYPE 3 /* value of bits 0 and 1 if .dbf */
#define EOH 0x0D /* end-of-header marker in .dbf file */ #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);
extern "C" int trace; // The general trace value extern "C" int trace; // The general trace value
/****************************************************************************/ /****************************************************************************/
...@@ -186,10 +178,12 @@ static int dbfhead(PGLOBAL g, FILE *file, PSZ fn, DBFHEADER *buf) ...@@ -186,10 +178,12 @@ static int dbfhead(PGLOBAL g, FILE *file, PSZ fn, DBFHEADER *buf)
/****************************************************************************/ /****************************************************************************/
PQRYRES DBFColumns(PGLOBAL g, char *fn, BOOL info) PQRYRES DBFColumns(PGLOBAL g, char *fn, BOOL info)
{ {
static int dbtype[] = {DB_CHAR, DB_SHORT, DB_CHAR, static int dbtype[] = {DB_CHAR, DB_SHORT, DB_CHAR,
DB_INT, DB_INT, DB_SHORT}; DB_INT, DB_INT, DB_SHORT};
static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING, static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING,
TYPE_INT, TYPE_INT, TYPE_SHORT}; TYPE_INT, TYPE_INT, TYPE_SHORT};
static XFLD fldtyp[] = {FLD_NAME, FLD_TYPE, FLD_TYPENAME,
FLD_PREC, FLD_LENGTH, FLD_SCALE};
static unsigned int length[] = {11, 6, 8, 10, 10, 6}; static unsigned int length[] = {11, 6, 8, 10, 10, 6};
char buf[2], filename[_MAX_PATH]; char buf[2], filename[_MAX_PATH];
int ncol = sizeof(dbtype) / sizeof(int); int ncol = sizeof(dbtype) / sizeof(int);
...@@ -204,35 +198,41 @@ PQRYRES DBFColumns(PGLOBAL g, char *fn, BOOL info) ...@@ -204,35 +198,41 @@ PQRYRES DBFColumns(PGLOBAL g, char *fn, BOOL info)
if (trace) if (trace)
htrc("DBFColumns: File %s\n", SVP(fn)); htrc("DBFColumns: File %s\n", SVP(fn));
if (!fn) { if (!info) {
strcpy(g->Message, MSG(MISSING_FNAME)); if (!fn) {
return NULL; strcpy(g->Message, MSG(MISSING_FNAME));
} // endif fn return NULL;
} // endif fn
/**************************************************************************/ /************************************************************************/
/* Open the input file. */ /* Open the input file. */
/**************************************************************************/ /************************************************************************/
PlugSetPath(filename, fn, PlgGetDataPath(g)); PlugSetPath(filename, fn, PlgGetDataPath(g));
if (!(infile= global_fopen(g, MSGID_CANNOT_OPEN, filename, "rb"))) if (!(infile= global_fopen(g, MSGID_CANNOT_OPEN, filename, "rb")))
return NULL; return NULL;
/**************************************************************************/ /************************************************************************/
/* Get the first 32 bytes of the header. */ /* Get the first 32 bytes of the header. */
/**************************************************************************/ /************************************************************************/
if ((rc = dbfhead(g, infile, filename, &mainhead)) == RC_FX) { if ((rc = dbfhead(g, infile, filename, &mainhead)) == RC_FX) {
fclose(infile); fclose(infile);
return NULL; return NULL;
} // endif dbfhead } // endif dbfhead
/************************************************************************/
/* Allocate the structures used to refer to the result set. */
/************************************************************************/
fields = mainhead.Fields;
} else
fields = 0;
/**************************************************************************/
/* 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, qrp = PlgAllocResult(g, ncol, fields, IDS_COLUMNS + 3,
dbtype, buftyp, length); dbtype, buftyp, fldtyp, length, true, false);
qrp->Info = info || (rc == RC_INFO); //qrp->Info = info || (rc == RC_INFO);
if (info)
return qrp;
if (trace) { if (trace) {
htrc("Structure of %s\n", filename); htrc("Structure of %s\n", filename);
...@@ -316,6 +316,7 @@ PQRYRES DBFColumns(PGLOBAL g, char *fn, BOOL info) ...@@ -316,6 +316,7 @@ PQRYRES DBFColumns(PGLOBAL g, char *fn, BOOL info)
qrp->Nblin = field; qrp->Nblin = field;
fclose(infile); fclose(infile);
#if 0
if (info) { if (info) {
/************************************************************************/ /************************************************************************/
/* Prepare return message for dbfinfo command. */ /* Prepare return message for dbfinfo command. */
...@@ -330,6 +331,7 @@ PQRYRES DBFColumns(PGLOBAL g, char *fn, BOOL info) ...@@ -330,6 +331,7 @@ PQRYRES DBFColumns(PGLOBAL g, char *fn, BOOL info)
strcat(g->Message, buf); strcat(g->Message, buf);
} // endif info } // endif info
#endif // 0
/**************************************************************************/ /**************************************************************************/
/* Return the result pointer for use by GetData routines. */ /* Return the result pointer for use by GetData routines. */
......
...@@ -138,10 +138,6 @@ ...@@ -138,10 +138,6 @@
#define my_strlwr(p) my_casedn_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)) #define my_stricmp(a,b) my_strcasecmp(default_charset_info, (a), (b))
#if defined (WIN32)
typedef struct _WMIutil *PWMIUT; /* Used to call WMIColumns */
#endif
#ifdef LIBXML2_SUPPORT #ifdef LIBXML2_SUPPORT
void XmlInitParserLib(void); void XmlInitParserLib(void);
void XmlCleanupParserLib(void); void XmlCleanupParserLib(void);
...@@ -1379,9 +1375,6 @@ int ha_connect::MakeRecord(char *buf) ...@@ -1379,9 +1375,6 @@ int ha_connect::MakeRecord(char *buf)
// This is for variable_length rows // This is for variable_length rows
memset(buf, 0, table->s->null_bytes); memset(buf, 0, table->s->null_bytes);
// store needs a charset, why not this one?
charset= table->s->table_charset;
// When sorting read_set selects all columns, so we use def_read_set // When sorting read_set selects all columns, so we use def_read_set
map= (const MY_BITMAP *)&table->def_read_set; map= (const MY_BITMAP *)&table->def_read_set;
...@@ -1389,6 +1382,9 @@ int ha_connect::MakeRecord(char *buf) ...@@ -1389,6 +1382,9 @@ int ha_connect::MakeRecord(char *buf)
for (field= table->field; *field && !rc; field++) { for (field= table->field; *field && !rc; field++) {
fp= *field; fp= *field;
// Default charset
charset= table->s->table_charset;
#if defined(MARIADB) #if defined(MARIADB)
if (fp->vcol_info && !fp->stored_in_db) if (fp->vcol_info && !fp->stored_in_db)
continue; // This is a virtual column continue; // This is a virtual column
...@@ -1409,28 +1405,35 @@ int ha_connect::MakeRecord(char *buf) ...@@ -1409,28 +1405,35 @@ int ha_connect::MakeRecord(char *buf)
value= colp->GetValue(); value= colp->GetValue();
// All this could be better optimized // All this could be better optimized
if (value->GetType() == TYPE_DATE) { switch (value->GetType()) {
if (!sdval) case TYPE_DATE:
sdval= AllocateValue(xp->g, TYPE_STRING, 20); if (!sdval)
sdval= AllocateValue(xp->g, TYPE_STRING, 20);
switch (fp->type()) {
case MYSQL_TYPE_DATE: switch (fp->type()) {
fmt= "%Y-%m-%d"; case MYSQL_TYPE_DATE:
break; fmt= "%Y-%m-%d";
case MYSQL_TYPE_TIME: break;
fmt= "%H:%M:%S"; case MYSQL_TYPE_TIME:
break; fmt= "%H:%M:%S";
default: break;
fmt= "%Y-%m-%d %H:%M:%S"; default:
} // endswitch type fmt= "%Y-%m-%d %H:%M:%S";
} // endswitch type
// Get date in the format required by MySQL fields
value->FormatValue(sdval, fmt); // Get date in the format required by MySQL fields
p= sdval->GetCharValue(); value->FormatValue(sdval, fmt);
} else if (value->GetType() == TYPE_FLOAT) p= sdval->GetCharValue();
p= NULL; break;
else case TYPE_FLOAT:
p= value->GetCharString(val); p= NULL;
break;
case TYPE_STRING:
charset= fp->charset();
// Passthru
default:
p= value->GetCharString(val);
} // endswitch Type
if (p) { if (p) {
if (fp->store(p, strlen(p), charset, CHECK_FIELD_WARN)) { if (fp->store(p, strlen(p), charset, CHECK_FIELD_WARN)) {
...@@ -3253,17 +3256,20 @@ bool ha_connect::add_fields(THD *thd, void *alt_info, ...@@ -3253,17 +3256,20 @@ bool ha_connect::add_fields(THD *thd, void *alt_info,
*/ */
bool ha_connect::pre_create(THD *thd, void *crt_info, void *alt_info) bool ha_connect::pre_create(THD *thd, void *crt_info, void *alt_info)
{ {
char ttp= '?', spc= ',', qch= 0, fnc= 0; char ttp= '?', spc= ',', qch= 0, fnc= '*';
const char *typn= "DOS"; const char *typn= "?";
const char *user; const char *user;
char *fn, *dsn, *tab, *db, *host, *pwd, *prt, *sep; char *fn, *dsn, *tab, *db, *host, *pwd, *prt, *sep, *csn;
#if defined(WIN32) #if defined(WIN32)
char *nsp= NULL, *cls= NULL; char *nsp= NULL, *cls= NULL;
#endif // WIN32 #endif // WIN32
char *supfnc = "*C";
int port= MYSQL_PORT, hdr= 0, mxr= 0; int port= MYSQL_PORT, hdr= 0, mxr= 0;
uint tm;
bool b= false, ok= false, dbf= false; bool b= false, ok= false, dbf= false;
LEX_STRING *comment, *name; LEX_STRING *comment, *name;
HA_CREATE_INFO *create_info= (HA_CREATE_INFO *)crt_info; HA_CREATE_INFO *create_info= (HA_CREATE_INFO *)crt_info;
CHARSET_INFO *cs;
engine_option_value *pov; engine_option_value *pov;
PQRYRES qrp; PQRYRES qrp;
PCOLRES crp; PCOLRES crp;
...@@ -3325,6 +3331,7 @@ bool ha_connect::pre_create(THD *thd, void *crt_info, void *alt_info) ...@@ -3325,6 +3331,7 @@ bool ha_connect::pre_create(THD *thd, void *crt_info, void *alt_info)
else else
ok= true; ok= true;
supfnc = "*CTSD";
break; break;
#endif // ODBC_SUPPORT #endif // ODBC_SUPPORT
case 'A': // DBF case 'A': // DBF
...@@ -3354,6 +3361,13 @@ bool ha_connect::pre_create(THD *thd, void *crt_info, void *alt_info) ...@@ -3354,6 +3361,13 @@ bool ha_connect::pre_create(THD *thd, void *crt_info, void *alt_info)
sprintf(g->Message, "Cannot get column info for table type %s", typn); sprintf(g->Message, "Cannot get column info for table type %s", typn);
} // endif ttp } // endif ttp
// Check for supported catalog function
if (ok && !strchr(supfnc, fnc)) {
sprintf(g->Message, "Unsupported catalog function %c for table type %s",
fnc, typn);
ok= false;
} // endif supfnc
if (ok) { if (ok) {
char *length, *decimals, *cnm, *rem; char *length, *decimals, *cnm, *rem;
int i, len, dec; int i, len, dec;
...@@ -3368,7 +3382,7 @@ bool ha_connect::pre_create(THD *thd, void *crt_info, void *alt_info) ...@@ -3368,7 +3382,7 @@ bool ha_connect::pre_create(THD *thd, void *crt_info, void *alt_info)
switch (ttp) { switch (ttp) {
case 'A': case 'A':
qrp= DBFColumns(g, fn, false); qrp= DBFColumns(g, fn, fnc == 'C');
break; break;
#if defined(ODBC_SUPPORT) #if defined(ODBC_SUPPORT)
case 'O': case 'O':
...@@ -3394,15 +3408,16 @@ bool ha_connect::pre_create(THD *thd, void *crt_info, void *alt_info) ...@@ -3394,15 +3408,16 @@ bool ha_connect::pre_create(THD *thd, void *crt_info, void *alt_info)
#endif // ODBC_SUPPORT #endif // ODBC_SUPPORT
#if defined(MYSQL_SUPPORT) #if defined(MYSQL_SUPPORT)
case 'Y': case 'Y':
qrp= MyColumns(g, host, db, user, pwd, tab, NULL, port, false); qrp= MyColumns(g, host, db, user, pwd, tab,
NULL, port, false, fnc == 'C');
break; break;
#endif // MYSQL_SUPPORT #endif // MYSQL_SUPPORT
case 'C': case 'C':
qrp= CSVColumns(g, fn, spc, qch, hdr, mxr); qrp= CSVColumns(g, fn, spc, qch, hdr, mxr, fnc == 'C');
break; break;
#if defined(WIN32) #if defined(WIN32)
case 'W': case 'W':
qrp= WMIColumns(g, nsp, cls, NULL); qrp= WMIColumns(g, nsp, cls, fnc == 'C');
break; break;
#endif // WIN32 #endif // WIN32
} // endswitch ttp } // endswitch ttp
...@@ -3412,7 +3427,8 @@ bool ha_connect::pre_create(THD *thd, void *crt_info, void *alt_info) ...@@ -3412,7 +3427,8 @@ bool ha_connect::pre_create(THD *thd, void *crt_info, void *alt_info)
return true; return true;
} // endif qrp } // endif qrp
if (fnc) { if (fnc && fnc != '*') {
// Catalog table
for (crp=qrp->Colresp; !b && crp; crp= crp->Next) { for (crp=qrp->Colresp; !b && crp; crp= crp->Next) {
cnm= encode(g, crp->Name); cnm= encode(g, crp->Name);
name= thd->make_lex_string(NULL, cnm, strlen(cnm), true); name= thd->make_lex_string(NULL, cnm, strlen(cnm), true);
...@@ -3425,39 +3441,60 @@ bool ha_connect::pre_create(THD *thd, void *crt_info, void *alt_info) ...@@ -3425,39 +3441,60 @@ bool ha_connect::pre_create(THD *thd, void *crt_info, void *alt_info)
// Now add the field // Now add the field
b= add_fields(thd, alt_info, name, type, length, decimals, b= add_fields(thd, alt_info, name, type, length, decimals,
0, comment, NULL, NULL, NULL); NOT_NULL_FLAG, comment, NULL, NULL, NULL);
} // endfor crp } // endfor crp
} else } else // Not a catalog table
for (i= 0; !b && i < qrp->Nblin; i++) { for (i= 0; !b && i < qrp->Nblin; i++) {
crp= qrp->Colresp; // Column Name rem= "";
cnm= encode(g, crp->Kdata->GetCharValue(i)); length= "";
name= thd->make_lex_string(NULL, cnm, strlen(cnm), true); decimals= NULL;
crp= crp->Next; // Data Type tm= NOT_NULL_FLAG;
type= PLGtoMYSQL(crp->Kdata->GetIntValue(i), true); cs= NULL;
crp= crp->Next; // Type Name
crp= crp->Next; // Precision (length) for (crp= qrp->Colresp; crp; crp= crp->Next)
len= crp->Kdata->GetIntValue(i); switch (crp->Fld) {
length= (char*)PlugSubAlloc(g, NULL, 8); case FLD_NAME:
sprintf(length, "%d", len); cnm= encode(g, crp->Kdata->GetCharValue(i));
crp= crp->Next; // Length name= thd->make_lex_string(NULL, cnm, strlen(cnm), true);
crp= crp->Next; // Scale (precision) break;
case FLD_TYPE:
if ((dec= crp->Kdata->GetIntValue(i))) { type= PLGtoMYSQL(crp->Kdata->GetIntValue(i), true);
decimals= (char*)PlugSubAlloc(g, NULL, 8); break;
sprintf(decimals, "%d", dec); case FLD_PREC:
} else len= crp->Kdata->GetIntValue(i);
decimals= NULL; length= (char*)PlugSubAlloc(g, NULL, 8);
sprintf(length, "%d", len);
if ((crp= crp->Next) && // Remark (comment) break;
(rem= crp->Kdata->GetCharValue(i))) case FLD_SCALE:
comment= thd->make_lex_string(NULL, rem, strlen(rem), true); if ((dec= crp->Kdata->GetIntValue(i))) {
else decimals= (char*)PlugSubAlloc(g, NULL, 8);
comment= thd->make_lex_string(NULL, "", 0, true); sprintf(decimals, "%d", dec);
} else
decimals= NULL;
break;
case FLD_NULL:
if (crp->Kdata->GetIntValue(i))
tm= 0; // Nullable
break;
case FLD_REM:
rem= crp->Kdata->GetCharValue(i);
break;
// case FLD_CHARSET:
// No good because remote table is already translated
// if (*(csn= crp->Kdata->GetCharValue(i)))
// cs= get_charset_by_name(csn, 0);
// break;
} // endswitch Fld
comment= thd->make_lex_string(NULL, rem, strlen(rem), true);
// Now add the field // Now add the field
b= add_fields(thd, alt_info, name, type, length, decimals, b= add_fields(thd, alt_info, name, type, length, decimals,
0, comment, NULL, NULL, NULL); tm, comment, cs, NULL, NULL);
} // endfor i } // endfor i
return b; return b;
......
...@@ -100,84 +100,9 @@ extern int xtrace; ...@@ -100,84 +100,9 @@ extern int xtrace;
/**************************************************************************/ /**************************************************************************/
//bool PlugCheckPattern(PGLOBAL, LPCSTR, LPCSTR); //bool PlugCheckPattern(PGLOBAL, LPCSTR, LPCSTR);
//#if !defined(WIN32) //#if !defined(WIN32)
extern "C" int GetRcString(int id, char *buf, int bufsize);
//#endif // !WIN32 //#endif // !WIN32
//void ptrc(char const *fmt, ...); //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: */ /* Get a unique char identifier for types. The letter used are: */
/* ABCDEF..I.KLM.O..R.T.VWXY.. */ /* ABCDEF..I.KLM.O..R.T.VWXY.. */
...@@ -345,14 +270,14 @@ char *MYCAT::GetStringCatInfo(PGLOBAL g, PSZ name, PSZ what, PSZ sdef) ...@@ -345,14 +270,14 @@ char *MYCAT::GetStringCatInfo(PGLOBAL g, PSZ name, PSZ what, PSZ sdef)
/***********************************************************************/ /***********************************************************************/
int MYCAT::GetColCatInfo(PGLOBAL g, PTABDEF defp) int MYCAT::GetColCatInfo(PGLOBAL g, PTABDEF defp)
{ {
char *type= GetStringCatInfo(g, NULL, "Type", "DOS"); char tc, *type= GetStringCatInfo(g, NULL, "Type", "DOS");
int i, loff, poff, nof, nlg; int i, loff, poff, nof, nlg;
void *field= NULL; void *field= NULL;
PCOLDEF cdp, lcdp= NULL, tocols= NULL; PCOLDEF cdp, lcdp= NULL, tocols= NULL;
PCOLINFO pcf= (PCOLINFO)PlugSubAlloc(g, NULL, sizeof(COLINFO)); PCOLINFO pcf= (PCOLINFO)PlugSubAlloc(g, NULL, sizeof(COLINFO));
// Get a unique char identifier for type // Get a unique char identifier for type
char tc= GetTypeID(type); tc= (!defp->Catfunc) ? GetTypeID(type) : 0;
// Take care of the column definitions // Take care of the column definitions
i= poff= nof= nlg= 0; i= poff= nof= nlg= 0;
......
/************** MyConn C++ Program Source Code File (.CPP) **************/ /************** MyConn C++ Program Source Code File (.CPP) **************/
/* PROGRAM NAME: MYCONN */ /* PROGRAM NAME: MYCONN */
/* ------------- */ /* ------------- */
/* Version 1.5 */ /* Version 1.6 */
/* */ /* */
/* COPYRIGHT: */ /* COPYRIGHT: */
/* ---------- */ /* ---------- */
/* (C) Copyright to the author Olivier BERTRAND 2007-2012 */ /* (C) Copyright to the author Olivier BERTRAND 2007-2013 */
/* */ /* */
/* WHAT THIS PROGRAM DOES: */ /* WHAT THIS PROGRAM DOES: */
/* ----------------------- */ /* ----------------------- */
...@@ -63,13 +63,6 @@ static char *server_groups[] = { ...@@ -63,13 +63,6 @@ static char *server_groups[] = {
extern "C" int trace; extern "C" int trace;
/**************************************************************************/
/* 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 = true, bool nonull = true);
/************************************************************************/ /************************************************************************/
/* MyColumns: constructs the result blocks containing all columns */ /* MyColumns: constructs the result blocks containing all columns */
/* of a MySQL table that will be retrieved by GetData commands. */ /* of a MySQL table that will be retrieved by GetData commands. */
...@@ -78,13 +71,18 @@ PQRYRES PlgAllocResult(PGLOBAL g, int ncol, int maxres, int ids, ...@@ -78,13 +71,18 @@ PQRYRES PlgAllocResult(PGLOBAL g, int ncol, int maxres, int ids,
PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db, PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
const char *user, const char *pwd, const char *user, const char *pwd,
const char *table, const char *colpat, const char *table, const char *colpat,
int port, bool key) int port, bool key, bool info)
{ {
static int dbtype[] = {DB_CHAR, DB_SHORT, DB_CHAR, DB_INT, static int dbtype[] = {DB_CHAR, DB_SHORT, DB_CHAR, DB_INT,
DB_INT, DB_SHORT, DB_CHAR, DB_CHAR}; DB_CHAR, DB_SHORT, DB_SHORT, DB_SHORT,
static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_INT, DB_CHAR, DB_CHAR, DB_CHAR};
TYPE_INT, TYPE_SHORT, TYPE_STRING, TYPE_STRING}; static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_INT,
static unsigned int length[] = {0, 4, 16, 4, 4, 4, 0, 0}; TYPE_STRING, TYPE_SHORT, TYPE_SHORT, TYPE_SHORT,
TYPE_STRING, TYPE_STRING, TYPE_STRING};
static XFLD fldtyp[] = {FLD_NAME, FLD_TYPE, FLD_TYPENAME, FLD_PREC,
FLD_KEY, FLD_SCALE, FLD_RADIX, FLD_NULL,
FLD_REM, FLD_NO, FLD_CHARSET};
static unsigned int length[] = {0, 4, 16, 4, 4, 4, 4, 4, 256, 32, 32};
char *fld, *fmt, cmd[128]; char *fld, *fmt, cmd[128];
int i, n, nf, ncol = sizeof(dbtype) / sizeof(int); int i, n, nf, ncol = sizeof(dbtype) / sizeof(int);
int len, type, prec, rc, k = 0; int len, type, prec, rc, k = 0;
...@@ -92,44 +90,59 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db, ...@@ -92,44 +90,59 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
PCOLRES crp; PCOLRES crp;
MYSQLC myc; MYSQLC myc;
/**********************************************************************/ if (!info) {
/* Open the connection with the MySQL server. */ /********************************************************************/
/**********************************************************************/ /* Open the connection with the MySQL server. */
if (myc.Open(g, host, db, user, pwd, port)) /********************************************************************/
return NULL; if (myc.Open(g, host, db, user, pwd, port))
return NULL;
/**********************************************************************/ /********************************************************************/
/* Do an evaluation of the result size. */ /* Do an evaluation of the result size. */
/**********************************************************************/ /********************************************************************/
sprintf(cmd, "SHOW FULL COLUMNS FROM %s", table); sprintf(cmd, "SHOW FULL COLUMNS FROM %s", table);
strcat(strcat(cmd, " FROM "), (db) ? db : PlgGetUser(g)->DBName); strcat(strcat(cmd, " FROM "), (db) ? db : PlgGetUser(g)->DBName);
if (colpat) if (colpat)
strcat(strcat(cmd, " LIKE "), colpat); strcat(strcat(cmd, " LIKE "), colpat);
if (trace) if (trace)
htrc("MyColumns: cmd='%s'\n", cmd); htrc("MyColumns: cmd='%s'\n", cmd);
if ((n = myc.GetResultSize(g, cmd)) < 0) { if ((n = myc.GetResultSize(g, cmd)) < 0) {
myc.Close(); myc.Close();
return NULL; return NULL;
} // endif n } // endif n
/**********************************************************************/ /********************************************************************/
/* Get the size of the name columns. */ /* Get the size of the name columns. */
/* Note that because the length is 0 for the last 2 columns (comment */ /********************************************************************/
/* and date format) they will be STRBLK instead of CHRBLK. */ length[0] = myc.GetFieldLength(0);
/**********************************************************************/ } else {
length[0] = myc.GetFieldLength(0); n = 0;
length[0] = 128;
} // endif info
if (!key) // We are not called from Create table //if (!key) // We are not called from Create table
ncol--; // No date format column // ncol--; // No date format column yet
/**********************************************************************/ /**********************************************************************/
/* Allocate the structures used to refer to the result set. */ /* Allocate the structures used to refer to the result set. */
/**********************************************************************/ /**********************************************************************/
qrp = PlgAllocResult(g, ncol, n, IDS_COLUMNS + 3, qrp = PlgAllocResult(g, ncol, n, IDS_COLUMNS + 3,
dbtype, buftyp, length); dbtype, buftyp, fldtyp, length, true, true);
// Some columns must be renamed
for (i = 0, crp = qrp->Colresp; crp; crp = crp->Next)
switch (++i) {
case 4: crp->Name = "Length"; break;
case 5: crp->Name = "Key"; break;
case 10: crp->Name = "Date_fmt"; break;
case 11: crp->Name = "Collation"; break;
} // endswitch i
if (info)
return qrp;
/**********************************************************************/ /**********************************************************************/
/* Now get the results into blocks. */ /* Now get the results into blocks. */
...@@ -142,7 +155,7 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db, ...@@ -142,7 +155,7 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
// Get column name // Get column name
fld = myc.GetCharField(0); fld = myc.GetCharField(0);
crp = qrp->Colresp; crp = qrp->Colresp; // Column_Name
crp->Kdata->SetValue(fld, i); crp->Kdata->SetValue(fld, i);
// Get type, type name, and precision // Get type, type name, and precision
...@@ -161,56 +174,45 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db, ...@@ -161,56 +174,45 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
return NULL; return NULL;
} // endif type } // endif type
crp = crp->Next; crp = crp->Next; // Data_Type
crp->Kdata->SetValue(type, i); crp->Kdata->SetValue(type, i);
crp = crp->Next; crp = crp->Next; // Type_Name
crp->Kdata->SetValue(cmd, i); crp->Kdata->SetValue(cmd, i);
if (key && type == TYPE_DATE) { if (type == TYPE_DATE) {
// When creating tables we do need info about date columns // When creating tables we do need info about date columns
fmt = MyDateFmt(cmd); fmt = MyDateFmt(cmd);
len = strlen(fmt); len = strlen(fmt);
} else } else
fmt = NULL; fmt = NULL;
crp = crp->Next; crp = crp->Next; // Precision
crp->Name = "Length";
crp->Kdata->SetValue(len, i); crp->Kdata->SetValue(len, i);
crp = crp->Next;
crp->Name = "Key";
if (key) { crp = crp->Next; // was Length
// Creating a table, we need key info fld = myc.GetCharField(4);
fld = myc.GetCharField(4); crp->Kdata->SetValue(fld, i);
crp->Kdata->SetValue((stricmp(fld, "PRI")) ? 0 : ++k, i);
} else
crp->Kdata->SetValue(len, i);
crp = crp->Next; crp = crp->Next; // Scale
crp->Name = "Prec";
crp->Kdata->SetValue(prec, i); crp->Kdata->SetValue(prec, i);
// Get comment field crp = crp->Next; // Radix
crp = crp->Next; crp->Kdata->SetValue(0, i);
crp->Name = "Comment";
fld = myc.GetCharField(8);
if (fld && strlen(fld)) crp = crp->Next; // Nullable
crp->Kdata->SetValue(fld, i); fld = myc.GetCharField(3);
else crp->Kdata->SetValue((toupper(*fld) == 'Y') ? 1 : 0, i);
crp->Kdata->Reset(i);
if (key) { crp = crp->Next; // Remark
crp = crp->Next; fld = myc.GetCharField(8);
crp->Name = "Date_Fmt"; crp->Kdata->SetValue(fld, i);
if (fmt)
crp->Kdata->SetValue(fmt, i);
else
crp->Kdata->Reset(i);
} // endif key crp = crp->Next; // New
crp->Kdata->SetValue((fmt) ? fmt : "", i);
crp = crp->Next; // New (charset)
fld = myc.GetCharField(2);
crp->Kdata->SetValue(fld, i);
} // endfor i } // endfor i
if (k > 1) { if (k > 1) {
...@@ -234,79 +236,6 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db, ...@@ -234,79 +236,6 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
return qrp; return qrp;
} // end of MyColumns } // end of MyColumns
#if 0
/**************************************************************************/
/* SemMySQLColumns: analyze a MySQL table for column format. */
/**************************************************************************/
void SemMySQLColumns(PGLOBAL g, PSEM semp)
{
PQRYRES qrp;
PPARM pp, parmp = semp->Parmp;
/*********************************************************************/
/* Test passed parameters. */
/*********************************************************************/
sprintf(g->Message, MSG(BAD_PARAMETERS), semp->Name);
semp->Value = g->Message;
semp->Type = TYPE_ERROR;
if (!parmp || parmp->Type != TYPE_LIST)
return;
/*********************************************************************/
/* Analyze the table specifications. */
/*********************************************************************/
PSZ host, db, user, pwd, table;
int port = 0;
host = db = user = pwd = table = NULL;
for (pp = (PPARM)parmp->Value; pp; pp = pp->Next)
switch (pp->Type) {
case TYPE_STRING:
switch (pp->Domain) {
case 5: table = (PSZ)pp->Value; break;
case 7: db = (PSZ)pp->Value; break;
case 30: host = (PSZ)pp->Value; break;
case 31: user = (PSZ)pp->Value; break;
case 32: pwd = (PSZ)pp->Value; break;
default:
return;
} // endswitch Domain
break;
case TYPE_INT:
if (pp->Domain == 33)
port = (int)*(int*)pp->Value;
else
return;
break;
default:
return;
} // endswitch Type
/************************************************************************/
/* Get and store the result pointer for use by GetData routines. */
/************************************************************************/
if (!(qrp = MyColumns(g, host, db, user, pwd, table, NULL, port, TRUE)))
return; // Error in MyColumns
PlgGetUser(g)->Result = qrp;
#if defined(_CONSOLE)
PrintResult(g, semp, qrp);
#else
/************************************************************************/
/* Make as result the qryresult description block. */
/************************************************************************/
semp->Type = TYPE_QRYRES;
semp->Domain = 0;
semp->Value = qrp;
#endif // _CONSOLE
} // end of SemMySQLColumns
#endif // 0
/* -------------------------- Class MYSQLC --------------------------- */ /* -------------------------- Class MYSQLC --------------------------- */
/***********************************************************************/ /***********************************************************************/
......
...@@ -38,7 +38,7 @@ typedef class MYSQLC *PMYC; ...@@ -38,7 +38,7 @@ typedef class MYSQLC *PMYC;
PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db, PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
const char *user, const char *pwd, const char *user, const char *pwd,
const char *table, const char *colpat, const char *table, const char *colpat,
int port, bool key); int port, bool key, bool info);
/* -------------------------- MYCONN class --------------------------- */ /* -------------------------- MYCONN class --------------------------- */
......
...@@ -171,13 +171,6 @@ int TranslateSQLType(int stp, int prec, int& len) ...@@ -171,13 +171,6 @@ int TranslateSQLType(int stp, int prec, int& len)
HENV ODBConn::m_henv = SQL_NULL_HENV; HENV ODBConn::m_henv = SQL_NULL_HENV;
int ODBConn::m_nAlloc = 0; // per-Appl reference to HENV above int ODBConn::m_nAlloc = 0; // per-Appl reference to HENV above
/**************************************************************************/
/* 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 = true, bool nonull = true);
/***********************************************************************/ /***********************************************************************/
/* Allocate the structure used to refer to the result set. */ /* Allocate the structure used to refer to the result set. */
/***********************************************************************/ /***********************************************************************/
...@@ -235,14 +228,18 @@ void ResetNullValues(CATPARM *cap) ...@@ -235,14 +228,18 @@ void ResetNullValues(CATPARM *cap)
PQRYRES ODBCColumns(PGLOBAL g, ODBConn *ocp, char *dsn, char *table, PQRYRES ODBCColumns(PGLOBAL g, ODBConn *ocp, char *dsn, char *table,
char *colpat) char *colpat)
{ {
static int dbtype[] = {DB_CHAR, DB_CHAR, static int dbtype[] = {DB_CHAR, DB_CHAR,
DB_CHAR, DB_SHORT, DB_CHAR, DB_CHAR, DB_SHORT, DB_CHAR,
DB_INT, DB_INT, DB_SHORT, DB_INT, DB_INT, DB_SHORT,
DB_SHORT, DB_SHORT, DB_CHAR}; DB_SHORT, DB_SHORT, DB_CHAR};
static int buftyp[] = {TYPE_STRING, TYPE_STRING, static int buftyp[] = {TYPE_STRING, TYPE_STRING,
TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_STRING, TYPE_SHORT, TYPE_STRING,
TYPE_INT, TYPE_INT, TYPE_SHORT, TYPE_INT, TYPE_INT, TYPE_SHORT,
TYPE_SHORT, TYPE_SHORT, TYPE_STRING}; TYPE_SHORT, TYPE_SHORT, TYPE_STRING};
static XFLD fldtyp[] = {FLD_NO, FLD_NO,
FLD_NAME, FLD_TYPE, FLD_TYPENAME,
FLD_PREC, FLD_LENGTH, FLD_SCALE,
FLD_RADIX, FLD_NULL, FLD_REM};
static unsigned int length[] = {0, 0, 0, 6, 20, 10, 10, 6, 6, 6, 128}; static unsigned int length[] = {0, 0, 0, 6, 20, 10, 10, 6, 6, 6, 128};
int n, ncol = 11; int n, ncol = 11;
int maxres; int maxres;
...@@ -277,7 +274,7 @@ PQRYRES ODBCColumns(PGLOBAL g, ODBConn *ocp, char *dsn, char *table, ...@@ -277,7 +274,7 @@ PQRYRES ODBCColumns(PGLOBAL g, ODBConn *ocp, char *dsn, char *table,
/* Allocate the structures used to refer to the result set. */ /* Allocate the structures used to refer to the result set. */
/************************************************************************/ /************************************************************************/
qrp = PlgAllocResult(g, ncol, maxres, IDS_COLUMNS + 1, qrp = PlgAllocResult(g, ncol, maxres, IDS_COLUMNS + 1,
dbtype, buftyp, length); dbtype, buftyp, NULL, length, true, true);
if (!ocp) // Info table if (!ocp) // Info table
return qrp; return qrp;
...@@ -313,8 +310,8 @@ PQRYRES ODBCColumns(PGLOBAL g, ODBConn *ocp, char *dsn, char *table, ...@@ -313,8 +310,8 @@ PQRYRES ODBCColumns(PGLOBAL g, ODBConn *ocp, char *dsn, char *table,
/**************************************************************************/ /**************************************************************************/
PQRYRES MyODBCCols(PGLOBAL g, char *dsn, char *tab, bool info) PQRYRES MyODBCCols(PGLOBAL g, char *dsn, char *tab, bool info)
{ {
int type, len, prec; // int i, type, len, prec;
PCOLRES crpt, crpl, crpp; // PCOLRES crp, crpt, crpl, crpp;
PQRYRES qrp; PQRYRES qrp;
ODBConn *ocp; ODBConn *ocp;
...@@ -342,6 +339,7 @@ PQRYRES MyODBCCols(PGLOBAL g, char *dsn, char *tab, bool info) ...@@ -342,6 +339,7 @@ PQRYRES MyODBCCols(PGLOBAL g, char *dsn, char *tab, bool info)
if (ocp) if (ocp)
ocp->Close(); ocp->Close();
#if 0
if (!qrp) if (!qrp)
return NULL; // Error in ODBCColumns return NULL; // Error in ODBCColumns
...@@ -371,7 +369,13 @@ PQRYRES MyODBCCols(PGLOBAL g, char *dsn, char *tab, bool info) ...@@ -371,7 +369,13 @@ PQRYRES MyODBCCols(PGLOBAL g, char *dsn, char *tab, bool info)
} // endfor i } // endfor i
crpp->Next = crpp->Next->Next->Next; // Should be Remark crpp->Next = crpp->Next->Next->Next; // Should be Remark
qrp->Nbcol = 7; // Was 11, skipped 4
// Renumber crp's for flag comparison
for (i = 0, crp = qrp->Colresp; crp; crp = crp->Next)
crp->Ncol = ++i;
qrp->Nbcol = i; // Should be 7; was 11, skipped 4
#endif // 0
return qrp; return qrp;
} // end of MyODBCCols } // end of MyODBCCols
...@@ -410,7 +414,8 @@ PQRYRES ODBCDataSources(PGLOBAL g, bool info) ...@@ -410,7 +414,8 @@ PQRYRES ODBCDataSources(PGLOBAL g, bool info)
/************************************************************************/ /************************************************************************/
/* Allocate the structures used to refer to the result set. */ /* Allocate the structures used to refer to the result set. */
/************************************************************************/ /************************************************************************/
qrp = PlgAllocResult(g, ncol, maxres, IDS_DSRC, dbtype, buftyp, length); qrp = PlgAllocResult(g, ncol, maxres, IDS_DSRC,
dbtype, buftyp, NULL, length, true, true);
/************************************************************************/ /************************************************************************/
/* Now get the results into blocks. */ /* Now get the results into blocks. */
...@@ -455,7 +460,8 @@ PQRYRES ODBCDrivers(PGLOBAL g, bool info) ...@@ -455,7 +460,8 @@ PQRYRES ODBCDrivers(PGLOBAL g, bool info)
/************************************************************************/ /************************************************************************/
/* Allocate the structures used to refer to the result set. */ /* Allocate the structures used to refer to the result set. */
/************************************************************************/ /************************************************************************/
qrp = PlgAllocResult(g, ncol, maxres, IDS_DRIVER, dbtype, buftyp, length); qrp = PlgAllocResult(g, ncol, maxres, IDS_DRIVER,
dbtype, buftyp, NULL, length, true, true);
/************************************************************************/ /************************************************************************/
/* Now get the results into blocks. */ /* Now get the results into blocks. */
...@@ -521,7 +527,7 @@ PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *tabpat, bool info) ...@@ -521,7 +527,7 @@ PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *tabpat, bool info)
/* Allocate the structures used to refer to the result set. */ /* Allocate the structures used to refer to the result set. */
/************************************************************************/ /************************************************************************/
qrp = PlgAllocResult(g, ncol, maxres, IDS_TABLES + 1, qrp = PlgAllocResult(g, ncol, maxres, IDS_TABLES + 1,
dbtype, buftyp, length); dbtype, buftyp, NULL, length, true, true);
if (info) if (info)
return qrp; return qrp;
...@@ -606,7 +612,7 @@ PQRYRES ODBCPrimaryKeys(PGLOBAL g, ODBConn *op, char *dsn, char *table) ...@@ -606,7 +612,7 @@ PQRYRES ODBCPrimaryKeys(PGLOBAL g, ODBConn *op, char *dsn, char *table)
/* Allocate the structure used to refer to the result set. */ /* Allocate the structure used to refer to the result set. */
/************************************************************************/ /************************************************************************/
qrp = PlgAllocResult(g, ncol, maxres, IDS_PKEY + 1, qrp = PlgAllocResult(g, ncol, maxres, IDS_PKEY + 1,
dbtype, buftyp, length); dbtype, buftyp, NULL, length, true, true);
#ifdef DEBTRACE #ifdef DEBTRACE
htrc("Getting pkey results ncol=%d\n", qrp->Nbcol); htrc("Getting pkey results ncol=%d\n", qrp->Nbcol);
...@@ -693,7 +699,7 @@ PQRYRES ODBCStatistics(PGLOBAL g, ODBConn *op, char *dsn, char *pat, ...@@ -693,7 +699,7 @@ PQRYRES ODBCStatistics(PGLOBAL g, ODBConn *op, char *dsn, char *pat,
/* Allocate the structure used to refer to the result set. */ /* Allocate the structure used to refer to the result set. */
/************************************************************************/ /************************************************************************/
qrp = PlgAllocResult(g, ncol, maxres, IDS_STAT + 1, qrp = PlgAllocResult(g, ncol, maxres, IDS_STAT + 1,
dbtype, buftyp, length); dbtype, buftyp, NULL, length, true, true);
#ifdef DEBTRACE #ifdef DEBTRACE
htrc("Getting stat results ncol=%d\n", qrp->Nbcol); htrc("Getting stat results ncol=%d\n", qrp->Nbcol);
......
...@@ -96,6 +96,7 @@ enum AMT {TYPE_AM_ERROR = 0, /* Type not defined */ ...@@ -96,6 +96,7 @@ enum AMT {TYPE_AM_ERROR = 0, /* Type not defined */
TYPE_AM_DMY = 172, /* DMY Dummy 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_SET = 180, /* SET Set tables am type no */
TYPE_AM_MYSQL = 192, /* MYSQL access method type no */ TYPE_AM_MYSQL = 192, /* MYSQL access method type no */
TYPE_AM_CAT = 193, /* Catalog access method type no */
TYPE_AM_OUT = 200}; /* Output relations (storage) */ TYPE_AM_OUT = 200}; /* Output relations (storage) */
enum RECFM {RECFM_NAF = -2, /* Not a file */ enum RECFM {RECFM_NAF = -2, /* Not a file */
...@@ -440,6 +441,25 @@ typedef struct _tabs { ...@@ -440,6 +441,25 @@ typedef struct _tabs {
PTABADR P3; PTABADR P3;
} TABS; } TABS;
/***********************************************************************/
/* Following definitions are used to define table fields (columns). */
/***********************************************************************/
enum XFLD {FLD_NO = 0, /* Not a field definition item */
FLD_NAME = 1, /* Field name */
FLD_TYPE = 2, /* Field type */
FLD_TYPENAME = 3, /* Field type name */
FLD_PREC = 4, /* Field precision (length?) */
FLD_LENGTH = 5, /* Field length (?) */
FLD_SCALE = 6, /* Field scale (precision) */
FLD_RADIX = 7, /* Field radix */
FLD_NULL = 8, /* Field nullable property */
FLD_REM = 9, /* Field comment (remark) */
FLD_CHARSET = 10, /* Field collation */
FLD_KEY = 11, /* Field key property */
FLD_DEFAULT = 12, /* Field default value */
FLD_PRIV = 13, /* Field priviledges */
FLD_DATEFMT = 14}; /* Field date format */
/***********************************************************************/ /***********************************************************************/
/* Result of last SQL noconv query. */ /* Result of last SQL noconv query. */
/***********************************************************************/ /***********************************************************************/
...@@ -470,6 +490,7 @@ typedef struct _colres { ...@@ -470,6 +490,7 @@ typedef struct _colres {
int Clen; /* Data individual internal size */ int Clen; /* Data individual internal size */
int Length; /* Data individual print length */ int Length; /* Data individual print length */
int Prec; /* Precision */ int Prec; /* Precision */
XFLD Fld; /* Type of field info */
} COLRES; } COLRES;
#if defined(WIN32) && !defined(NOEX) #if defined(WIN32) && !defined(NOEX)
...@@ -491,6 +512,13 @@ void AddPointer(PTABS, void *); ...@@ -491,6 +512,13 @@ void AddPointer(PTABS, void *);
PDTP MakeDateFormat(PGLOBAL, PSZ, bool, bool, int); PDTP MakeDateFormat(PGLOBAL, PSZ, bool, bool, int);
int ExtractDate(char *, PDTP, int, int val[6]); int ExtractDate(char *, PDTP, int, int val[6]);
/**************************************************************************/
/* Allocate the result structure that will contain result data. */
/**************************************************************************/
PQRYRES PlgAllocResult(PGLOBAL g, int ncol, int maxres, int ids,
int *dbtype, int *buftyp, XFLD *fldtyp,
unsigned int *length, bool blank, bool nonull);
/***********************************************************************/ /***********************************************************************/
/* Exported utility routines. */ /* Exported utility routines. */
/***********************************************************************/ /***********************************************************************/
......
/********** PlgDBUtl Fpe C++ Program Source Code File (.CPP) ***********/ /********** PlgDBUtl Fpe C++ Program Source Code File (.CPP) ***********/
/* PROGRAM NAME: PLGDBUTL */ /* PROGRAM NAME: PLGDBUTL */
/* ------------- */ /* ------------- */
/* Version 3.7 */ /* Version 3.8 */
/* */ /* */
/* COPYRIGHT: */ /* COPYRIGHT: */
/* ---------- */ /* ---------- */
/* (C) Copyright to the author Olivier BERTRAND 1998-2012 */ /* (C) Copyright to the author Olivier BERTRAND 1998-2013 */
/* */ /* */
/* WHAT THIS PROGRAM DOES: */ /* WHAT THIS PROGRAM DOES: */
/* ----------------------- */ /* ----------------------- */
...@@ -66,6 +66,7 @@ ...@@ -66,6 +66,7 @@
#include "colblk.h" #include "colblk.h"
#include "xtable.h" // header of TBX, TDB and TDBASE classes #include "xtable.h" // header of TBX, TDB and TDBASE classes
#include "tabcol.h" // header of XTAB and COLUMN classes #include "tabcol.h" // header of XTAB and COLUMN classes
#include "valblk.h"
/***********************************************************************/ /***********************************************************************/
/* Macro or external routine definition */ /* Macro or external routine definition */
...@@ -128,6 +129,7 @@ void CloseXMLFile(PGLOBAL, PFBLOCK, bool); ...@@ -128,6 +129,7 @@ void CloseXMLFile(PGLOBAL, PFBLOCK, bool);
void CloseXML2File(PGLOBAL, PFBLOCK, bool); void CloseXML2File(PGLOBAL, PFBLOCK, bool);
#endif // LIBXML2_SUPPORT #endif // LIBXML2_SUPPORT
extern "C" int GetRcString(int id, char *buf, int bufsize);
/***********************************************************************/ /***********************************************************************/
/* Routines for file IO with error reporting to g->Message */ /* Routines for file IO with error reporting to g->Message */
...@@ -262,6 +264,85 @@ void ptrc(char const *fmt, ...) ...@@ -262,6 +264,85 @@ void ptrc(char const *fmt, ...)
} // end of ptrc } // end of ptrc
#endif // 0 #endif // 0
/**************************************************************************/
/* Allocate the result structure that will contain result data. */
/**************************************************************************/
PQRYRES PlgAllocResult(PGLOBAL g, int ncol, int maxres, int ids,
int *dbtype, int *buftyp, XFLD *fldtyp,
unsigned int *length, bool blank, bool nonull)
{
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
if (fldtyp)
crp->Fld = fldtyp[i];
else
crp->Fld = FLD_NO;
// 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
/***********************************************************************/ /***********************************************************************/
/* Allocate and initialize the new DB User Block. */ /* Allocate and initialize the new DB User Block. */
/***********************************************************************/ /***********************************************************************/
......
...@@ -74,6 +74,7 @@ TABDEF::TABDEF(void) ...@@ -74,6 +74,7 @@ TABDEF::TABDEF(void)
{ {
Owner = NULL; Owner = NULL;
Desc = NULL; Desc = NULL;
Catfunc = 0;
Card = 0; Card = 0;
Elemt = 0; Elemt = 0;
Sort = 0; Sort = 0;
...@@ -95,6 +96,7 @@ bool TABDEF::Define(PGLOBAL g, PCATLG cat, LPCSTR name, LPCSTR am) ...@@ -95,6 +96,7 @@ bool TABDEF::Define(PGLOBAL g, PCATLG cat, LPCSTR name, LPCSTR am)
Name = (PSZ)PlugSubAlloc(g, memp, strlen(name) + 1); Name = (PSZ)PlugSubAlloc(g, memp, strlen(name) + 1);
strcpy(Name, name); strcpy(Name, name);
Cat = cat; Cat = cat;
Catfunc = toupper(*Cat->GetStringCatInfo(g, Name, "Catfunc", ""));
Elemt = cat->GetIntCatInfo(name, "Elements", 0); Elemt = cat->GetIntCatInfo(name, "Elements", 0);
Multiple = cat->GetIntCatInfo(name, "Multiple", 0); Multiple = cat->GetIntCatInfo(name, "Multiple", 0);
Degree = cat->GetIntCatInfo(name, "Degree", 0); Degree = cat->GetIntCatInfo(name, "Degree", 0);
......
...@@ -85,6 +85,7 @@ class DllExport TABDEF : public RELDEF { /* Logical table descriptor */ ...@@ -85,6 +85,7 @@ class DllExport TABDEF : public RELDEF { /* Logical table descriptor */
// Members // Members
PSZ Owner; /* Table owner (for ODBC) */ PSZ Owner; /* Table owner (for ODBC) */
PSZ Desc; /* Table description */ PSZ Desc; /* Table description */
char Catfunc; /* Catalog function */
int Card; /* (max) number of rows in table */ int Card; /* (max) number of rows in table */
int Elemt; /* Number of rows in blocks or rowset */ int Elemt; /* Number of rows in blocks or rowset */
int Sort; /* Table already sorted ??? */ int Sort; /* Table already sorted ??? */
......
...@@ -297,12 +297,16 @@ PTDB DOSDEF::GetTable(PGLOBAL g, MODE mode) ...@@ -297,12 +297,16 @@ PTDB DOSDEF::GetTable(PGLOBAL g, MODE mode)
/* Column blocks will be allocated only when needed. */ /* Column blocks will be allocated only when needed. */
/*********************************************************************/ /*********************************************************************/
if (Recfm == RECFM_DBF) { if (Recfm == RECFM_DBF) {
if (map) if (!Catfunc) {
txfp = new(g) DBMFAM(this); if (map)
else txfp = new(g) DBMFAM(this);
txfp = new(g) DBFFAM(this); else
txfp = new(g) DBFFAM(this);
tdbp = new(g) TDBFIX(this, txfp);
} else // Catfunc should be 'C'
tdbp = new(g) TDBDCL(this);
tdbp = new(g) TDBFIX(this, txfp);
} else if (Recfm != RECFM_VAR && Compressed < 2) { } else if (Recfm != RECFM_VAR && Compressed < 2) {
if (Huge) if (Huge)
txfp = new(g) BGXFAM(this); txfp = new(g) BGXFAM(this);
......
...@@ -34,6 +34,7 @@ class DllExport DOSDEF : public TABDEF { /* Logical table description */ ...@@ -34,6 +34,7 @@ class DllExport DOSDEF : public TABDEF { /* Logical table description */
virtual const char *GetType(void) {return "DOS";} virtual const char *GetType(void) {return "DOS";}
virtual PIXDEF GetIndx(void) {return To_Indx;} virtual PIXDEF GetIndx(void) {return To_Indx;}
virtual void SetIndx(PIXDEF xdp) {To_Indx = xdp;} virtual void SetIndx(PIXDEF xdp) {To_Indx = xdp;}
PSZ GetFn(void) {return Fn;}
PSZ GetOfn(void) {return Ofn;} PSZ GetOfn(void) {return Ofn;}
void SetBlock(int block) {Block = block;} void SetBlock(int block) {Block = block;}
int GetBlock(void) {return Block;} int GetBlock(void) {return Block;}
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#ifndef __TABFIX__ #ifndef __TABFIX__
#define __TABFIX__ #define __TABFIX__
#include "tabdos.h" /* Base class declares */ #include "tabdos.h" /* Base class declares */
#include "filamdbf.h"
typedef class FIXCOL *PFIXCOL; typedef class FIXCOL *PFIXCOL;
typedef class BINCOL *PBINCOL; typedef class BINCOL *PBINCOL;
...@@ -77,4 +78,22 @@ class DllExport BINCOL : public DOSCOL { ...@@ -77,4 +78,22 @@ class DllExport BINCOL : public DOSCOL {
// Members // Members
char Fmt; // The column numeric format char Fmt; // The column numeric format
}; // end of class BINCOL }; // end of class BINCOL
/***********************************************************************/
/* This is the class declaration for the DBF columns catalog table. */
/***********************************************************************/
class TDBDCL : public TDBCAT {
public:
// Constructor
TDBDCL(PDOSDEF tdp) : TDBCAT(tdp) {Fn = tdp->GetFn();}
protected:
// Specific routines
virtual PQRYRES GetResult(PGLOBAL g) {return DBFColumns(g, Fn, false);}
// Members
char *Fn; // The DBF file (path) name
}; // end of class TDBOCL
#endif // __TABFIX__ #endif // __TABFIX__
/************* TabFmt C++ Program Source Code File (.CPP) **************/ /************* TabFmt C++ Program Source Code File (.CPP) **************/
/* PROGRAM NAME: TABFMT */ /* PROGRAM NAME: TABFMT */
/* ------------- */ /* ------------- */
/* Version 3.7 */ /* Version 3.8 */
/* */ /* */
/* COPYRIGHT: */ /* COPYRIGHT: */
/* ---------- */ /* ---------- */
...@@ -67,12 +67,6 @@ ...@@ -67,12 +67,6 @@
extern "C" int trace; extern "C" int trace;
/***********************************************************************/
/* CSV Catalog utility functions. */
/***********************************************************************/
PQRYRES PlgAllocResult(PGLOBAL, int, int, int, int *, int *,
unsigned int *, bool blank = true, bool nonull = false);
/***********************************************************************/ /***********************************************************************/
/* CSVColumns: constructs the result blocks containing the description */ /* CSVColumns: constructs the result blocks containing the description */
/* of all the columns of a CSV file that will be retrieved by #GetData.*/ /* of all the columns of a CSV file that will be retrieved by #GetData.*/
...@@ -80,12 +74,15 @@ PQRYRES PlgAllocResult(PGLOBAL, int, int, int, int *, int *, ...@@ -80,12 +74,15 @@ PQRYRES PlgAllocResult(PGLOBAL, int, int, int, int *, int *,
/* of types (TYPE_STRING < TYPE_FLOAT < TYPE_INT) (1 < 2 < 7). */ /* of types (TYPE_STRING < TYPE_FLOAT < TYPE_INT) (1 < 2 < 7). */
/* If these values are changed, this will have to be revisited. */ /* If these values are changed, this will have to be revisited. */
/***********************************************************************/ /***********************************************************************/
PQRYRES CSVColumns(PGLOBAL g, char *fn, char sep, char q, int hdr, int mxr) PQRYRES CSVColumns(PGLOBAL g, char *fn, char sep, char q,
int hdr, int mxr, bool info)
{ {
static int dbtype[] = {DB_CHAR, DB_SHORT, DB_CHAR, static int dbtype[] = {DB_CHAR, DB_SHORT, DB_CHAR,
DB_INT, DB_INT, DB_SHORT}; DB_INT, DB_INT, DB_SHORT};
static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING, static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING,
TYPE_INT, TYPE_INT, TYPE_SHORT}; TYPE_INT, TYPE_INT, TYPE_SHORT};
static XFLD fldtyp[] = {FLD_NAME, FLD_TYPE, FLD_TYPENAME,
FLD_PREC, FLD_LENGTH, FLD_SCALE};
static unsigned int length[] = {6, 6, 8, 10, 10, 6}; static unsigned int length[] = {6, 6, 8, 10, 10, 6};
char *p, *colname[MAXCOL], dechar, filename[_MAX_PATH], buf[4096]; char *p, *colname[MAXCOL], dechar, filename[_MAX_PATH], buf[4096];
int i, imax, hmax, n, nerr, phase, blank, digit, dec, type; int i, imax, hmax, n, nerr, phase, blank, digit, dec, type;
...@@ -96,9 +93,15 @@ PQRYRES CSVColumns(PGLOBAL g, char *fn, char sep, char q, int hdr, int mxr) ...@@ -96,9 +93,15 @@ PQRYRES CSVColumns(PGLOBAL g, char *fn, char sep, char q, int hdr, int mxr)
PQRYRES qrp; PQRYRES qrp;
PCOLRES crp; PCOLRES crp;
if (info) {
imax = 0;
length[0] = 128;
goto skipit;
} // endif info
// num_max = atoi(p+1); // Max num of record to test // num_max = atoi(p+1); // Max num of record to test
#if defined(WIN32) #if defined(WIN32)
if (strnicmp(setlocale(LC_NUMERIC, NULL), "French", 6)) if (sep == ',' || strnicmp(setlocale(LC_NUMERIC, NULL), "French", 6))
dechar = '.'; dechar = '.';
else else
dechar = ','; dechar = ',';
...@@ -328,6 +331,7 @@ PQRYRES CSVColumns(PGLOBAL g, char *fn, char sep, char q, int hdr, int mxr) ...@@ -328,6 +331,7 @@ PQRYRES CSVColumns(PGLOBAL g, char *fn, char sep, char q, int hdr, int mxr)
fclose(infile); fclose(infile);
skipit:
if (trace) if (trace)
htrc("CSVColumns: imax=%d hmax=%d len=%d\n", htrc("CSVColumns: imax=%d hmax=%d len=%d\n",
imax, hmax, length[0]); imax, hmax, length[0]);
...@@ -336,9 +340,12 @@ PQRYRES CSVColumns(PGLOBAL g, char *fn, char sep, char q, int hdr, int mxr) ...@@ -336,9 +340,12 @@ PQRYRES CSVColumns(PGLOBAL g, char *fn, char sep, char q, int hdr, int mxr)
/* Allocate the structures used to refer to the result set. */ /* Allocate the structures used to refer to the result set. */
/*********************************************************************/ /*********************************************************************/
qrp = PlgAllocResult(g, ncol, imax, IDS_COLUMNS + 3, qrp = PlgAllocResult(g, ncol, imax, IDS_COLUMNS + 3,
dbtype, buftyp, length); dbtype, buftyp, fldtyp, length, true, false);
qrp->Nblin = imax; qrp->Nblin = imax;
if (info)
return qrp;
/*********************************************************************/ /*********************************************************************/
/* Now get the results into blocks. */ /* Now get the results into blocks. */
/*********************************************************************/ /*********************************************************************/
...@@ -398,11 +405,12 @@ bool CSVDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) ...@@ -398,11 +405,12 @@ bool CSVDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
char buf[8]; char buf[8];
// Double check correctness of offset values // Double check correctness of offset values
for (PCOLDEF cdp = To_Cols; cdp; cdp = cdp->GetNext()) if (!Catfunc)
if (cdp->GetOffset() < 1) { for (PCOLDEF cdp = To_Cols; cdp; cdp = cdp->GetNext())
strcpy(g->Message, MSG(BAD_OFFSET_VAL)); if (cdp->GetOffset() < 1) {
return true; strcpy(g->Message, MSG(BAD_OFFSET_VAL));
} // endif Offset return true;
} // endif Offset
// Call DOSDEF DefineAM with am=CSV so FMT is not confused with FIX // Call DOSDEF DefineAM with am=CSV so FMT is not confused with FIX
if (DOSDEF::DefineAM(g, "CSV", poff)) if (DOSDEF::DefineAM(g, "CSV", poff))
...@@ -431,47 +439,52 @@ bool CSVDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) ...@@ -431,47 +439,52 @@ bool CSVDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
/***********************************************************************/ /***********************************************************************/
PTDB CSVDEF::GetTable(PGLOBAL g, MODE mode) PTDB CSVDEF::GetTable(PGLOBAL g, MODE mode)
{ {
USETEMP tmp = PlgGetUser(g)->UseTemp;
bool map = Mapped && mode != MODE_INSERT &&
!(tmp != TMP_NO && mode == MODE_UPDATE) &&
!(tmp == TMP_FORCE &&
(mode == MODE_UPDATE || mode == MODE_DELETE));
PTXF txfp;
PTDBASE tdbp; PTDBASE tdbp;
/*********************************************************************/ if (Catfunc != 'C') {
/* Allocate a file processing class of the proper type. */ USETEMP tmp = PlgGetUser(g)->UseTemp;
/*********************************************************************/ bool map = Mapped && mode != MODE_INSERT &&
if (map) { !(tmp != TMP_NO && mode == MODE_UPDATE) &&
// Should be now compatible with UNIX !(tmp == TMP_FORCE &&
txfp = new(g) MAPFAM(this); (mode == MODE_UPDATE || mode == MODE_DELETE));
} else if (Compressed) { PTXF txfp;
/*******************************************************************/
/* Allocate a file processing class of the proper type. */
/*******************************************************************/
if (map) {
// Should be now compatible with UNIX
txfp = new(g) MAPFAM(this);
} else if (Compressed) {
#if defined(ZIP_SUPPORT) #if defined(ZIP_SUPPORT)
if (Compressed == 1) if (Compressed == 1)
txfp = new(g) ZIPFAM(this); txfp = new(g) ZIPFAM(this);
else { else {
strcpy(g->Message, "Compress 2 not supported yet"); strcpy(g->Message, "Compress 2 not supported yet");
// txfp = new(g) ZLBFAM(defp); // txfp = new(g) ZLBFAM(defp);
return NULL; return NULL;
} // endelse } // endelse
#else // !ZIP_SUPPORT #else // !ZIP_SUPPORT
strcpy(g->Message, "Compress not supported"); strcpy(g->Message, "Compress not supported");
return NULL; return NULL;
#endif // !ZIP_SUPPORT #endif // !ZIP_SUPPORT
} else } else
txfp = new(g) DOSFAM(this); txfp = new(g) DOSFAM(this);
/*********************************************************************/ /*******************************************************************/
/* Allocate a TDB of the proper type. */ /* Allocate a TDB of the proper type. */
/* Column blocks will be allocated only when needed. */ /* Column blocks will be allocated only when needed. */
/*********************************************************************/ /*******************************************************************/
if (!Fmtd) if (!Fmtd)
tdbp = new(g) TDBCSV(this, txfp); tdbp = new(g) TDBCSV(this, txfp);
else else
tdbp = new(g) TDBFMT(this, txfp); tdbp = new(g) TDBFMT(this, txfp);
if (Multiple) if (Multiple)
tdbp = new(g) TDBMUL(tdbp); tdbp = new(g) TDBMUL(tdbp);
} else
tdbp = new(g)TDBCCL(this);
return tdbp; return tdbp;
} // end of GetTable } // end of GetTable
...@@ -1389,4 +1402,26 @@ void CSVCOL::WriteColumn(PGLOBAL g) ...@@ -1389,4 +1402,26 @@ void CSVCOL::WriteColumn(PGLOBAL g)
} // end of WriteColumn } // end of WriteColumn
/* ---------------------------TDBCCL class --------------------------- */
/***********************************************************************/
/* TDBCCL class constructor. */
/***********************************************************************/
TDBCCL::TDBCCL(PCSVDEF tdp) : TDBCAT(tdp)
{
Fn = tdp->GetFn();
Hdr = tdp->Header;
Mxr = tdp->Maxerr;
Qtd = tdp->Quoted;
Sep = tdp->Sep;
} // end of TDBCCL constructor
/***********************************************************************/
/* GetResult: Get the list the CSV file columns. */
/***********************************************************************/
PQRYRES TDBCCL::GetResult(PGLOBAL g)
{
return CSVColumns(g, Fn, Sep, Qtd, Hdr, Mxr, false);
} // end of GetResult
/* ------------------------ End of TabFmt ---------------------------- */ /* ------------------------ End of TabFmt ---------------------------- */
/*************** TabFmt H Declares Source Code File (.H) ***************/ /*************** TabFmt H Declares Source Code File (.H) ***************/
/* Name: TABFMT.H Version 2.2 */ /* Name: TABFMT.H Version 2.3 */
/* */ /* */
/* (C) Copyright to the author Olivier BERTRAND 2001-2012 */ /* (C) Copyright to the author Olivier BERTRAND 2001-2013 */
/* */ /* */
/* This file contains the CSV and FMT classes declares. */ /* This file contains the CSV and FMT classes declares. */
/***********************************************************************/ /***********************************************************************/
...@@ -14,14 +14,15 @@ typedef class TDBFMT *PTDBFMT; ...@@ -14,14 +14,15 @@ typedef class TDBFMT *PTDBFMT;
/***********************************************************************/ /***********************************************************************/
/* Functions used externally. */ /* Functions used externally. */
/***********************************************************************/ /***********************************************************************/
PQRYRES CSVColumns(PGLOBAL g, char *fn, char sep, char q, int hdr, int mxr); PQRYRES CSVColumns(PGLOBAL g, char *fn, char sep, char q,
int hdr, int mxr, bool info);
/***********************************************************************/ /***********************************************************************/
/* CSV table. */ /* CSV table. */
/***********************************************************************/ /***********************************************************************/
class DllExport CSVDEF : public DOSDEF { /* Logical table description */ class DllExport CSVDEF : public DOSDEF { /* Logical table description */
friend class TDBCSV; friend class TDBCSV;
//friend class TDBMCV; friend class TDBCCL;
public: public:
// Constructor // Constructor
CSVDEF(void); CSVDEF(void);
...@@ -160,10 +161,30 @@ class TDBFMT : public TDBCSV { ...@@ -160,10 +161,30 @@ class TDBFMT : public TDBCSV {
protected: protected:
// Members // Members
PSZ *FldFormat; // Field read format PSZ *FldFormat; // Field read format
void *To_Fld; // To field test buffer void *To_Fld; // To field test buffer
int *FmtTest; // Test on ending by %n or %m int *FmtTest; // Test on ending by %n or %m
int Linenum; // Last read line int Linenum; // Last read line
}; // end of class TDBFMT }; // end of class TDBFMT
/***********************************************************************/
/* This is the class declaration for the CSV catalog table. */
/***********************************************************************/
class TDBCCL : public TDBCAT {
public:
// Constructor
TDBCCL(PCSVDEF tdp);
protected:
// Specific routines
virtual PQRYRES GetResult(PGLOBAL g);
// Members
char *Fn; // The CSV file (path) name
bool Hdr; // true if first line contains headers
int Mxr; // Maximum number of bad records
int Qtd; // Quoting level for quoted fields
char Sep; // Separator for standard CSV files
}; // end of class TDBCCL
/* ------------------------- End of TabFmt.H ------------------------- */ /* ------------------------- End of TabFmt.H ------------------------- */
/************** Table C++ Functions Source Code File (.CPP) ************/ /************** Table C++ Functions Source Code File (.CPP) ************/
/* Name: TABLE.CPP Version 2.5 */ /* Name: TABLE.CPP Version 2.6 */
/* */ /* */
/* (C) Copyright to the author Olivier BERTRAND 1999-2012 */ /* (C) Copyright to the author Olivier BERTRAND 1999-2013 */
/* */ /* */
/* This file contains the TBX, TDB and OPJOIN classes functions. */ /* This file contains the TBX, TDB and OPJOIN classes functions. */
/***********************************************************************/ /***********************************************************************/
...@@ -425,3 +425,180 @@ void TDBASE::MarkDB(PGLOBAL g, PTDB tdb2) ...@@ -425,3 +425,180 @@ void TDBASE::MarkDB(PGLOBAL g, PTDB tdb2)
htrc("DOS MarkDB: tdbp=%p tdb2=%p\n", this, tdb2); htrc("DOS MarkDB: tdbp=%p tdb2=%p\n", this, tdb2);
} // end of MarkDB } // end of MarkDB
/* ---------------------------TDBCAT class --------------------------- */
/***********************************************************************/
/* Implementation of the TDBCAT class. */
/***********************************************************************/
TDBCAT::TDBCAT(PTABDEF tdp) : TDBASE(tdp)
{
Qrp = NULL;
Init = false;
N = -1;
} // end of TDBCAT constructor
/***********************************************************************/
/* Allocate CAT column description block. */
/***********************************************************************/
PCOL TDBCAT::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
{
PCATCOL colp;
colp = (PCATCOL)new(g) CATCOL(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: Get the result query block. */
/***********************************************************************/
bool TDBCAT::Initialize(PGLOBAL g)
{
if (Init)
return false;
if (!(Qrp = GetResult(g)))
return true;
Init = true;
return false;
} // end of Initialize
/***********************************************************************/
/* CAT: Get the number of properties. */
/***********************************************************************/
int TDBCAT::GetMaxSize(PGLOBAL g)
{
if (MaxSize < 0) {
if (Initialize(g))
return -1;
MaxSize = Qrp->Nblin;
} // endif MaxSize
return MaxSize;
} // end of GetMaxSize
/***********************************************************************/
/* CAT Access Method opening routine. */
/***********************************************************************/
bool TDBCAT::OpenDB(PGLOBAL g)
{
if (Use == USE_OPEN) {
/*******************************************************************/
/* Table already open. */
/*******************************************************************/
N = -1;
return false;
} // endif use
if (Mode != MODE_READ) {
/*******************************************************************/
/* ODBC Info tables cannot be modified. */
/*******************************************************************/
strcpy(g->Message, "CAT tables are read only");
return true;
} // endif Mode
/*********************************************************************/
/* Initialize the ODBC processing. */
/*********************************************************************/
if (Initialize(g))
return true;
return InitCol(g);
} // end of OpenDB
/***********************************************************************/
/* Initialize columns. */
/***********************************************************************/
bool TDBCAT::InitCol(PGLOBAL g)
{
PCATCOL colp;
PCOLRES crp;
for (colp = (PCATCOL)Columns; colp; colp = (PCATCOL)colp->GetNext()) {
for (crp = Qrp->Colresp; crp; crp = crp->Next)
if ((colp->Flag == crp->Ncol) ||
(!colp->Flag && !stricmp(colp->Name, crp->Name))) {
colp->Crp = crp;
break;
} // endif Flag
if (!colp->Crp /*&& !colp->GetValue()->IsConstant()*/) {
sprintf(g->Message, "Invalid flag %d for column %s",
colp->Flag, colp->Name);
return true;
} // endif Crp
} // endfor colp
return false;
} // end of InitCol
/***********************************************************************/
/* Data Base read routine for CAT access method. */
/***********************************************************************/
int TDBCAT::ReadDB(PGLOBAL g)
{
return (++N < Qrp->Nblin) ? RC_OK : RC_EF;
} // end of ReadDB
/***********************************************************************/
/* WriteDB: Data Base write routine for CAT access methods. */
/***********************************************************************/
int TDBCAT::WriteDB(PGLOBAL g)
{
strcpy(g->Message, "CAT tables are read only");
return RC_FX;
} // end of WriteDB
/***********************************************************************/
/* Data Base delete line routine for CAT access methods. */
/***********************************************************************/
int TDBCAT::DeleteDB(PGLOBAL g, int irc)
{
strcpy(g->Message, "Delete not enabled for CAT tables");
return RC_FX;
} // end of DeleteDB
/***********************************************************************/
/* Data Base close routine for WMI access method. */
/***********************************************************************/
void TDBCAT::CloseDB(PGLOBAL g)
{
// Nothing to do
} // end of CloseDB
// ------------------------ CATCOL functions ----------------------------
/***********************************************************************/
/* CATCOL public constructor. */
/***********************************************************************/
CATCOL::CATCOL(PCOLDEF cdp, PTDB tdbp, int n)
: COLBLK(cdp, tdbp, n)
{
Tdbp = (PTDBCAT)tdbp;
Crp = NULL;
Flag = cdp->GetOffset();
} // end of WMICOL constructor
/***********************************************************************/
/* Read the next Data Source elements. */
/***********************************************************************/
void CATCOL::ReadColumn(PGLOBAL g)
{
// Get the value of the Name or Description property
Value->SetValue_pvblk(Crp->Kdata, Tdbp->N);
} // end of ReadColumn
/************* TabMySQL C++ Program Source Code File (.CPP) *************/ /************* TabMySQL C++ Program Source Code File (.CPP) *************/
/* PROGRAM NAME: TABMYSQL */ /* PROGRAM NAME: TABMYSQL */
/* ------------- */ /* ------------- */
/* Version 1.5 */ /* Version 1.6 */
/* */ /* */
/* AUTHOR: */ /* AUTHOR: */
/* ------- */ /* ------- */
...@@ -105,7 +105,11 @@ bool MYSQLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) ...@@ -105,7 +105,11 @@ bool MYSQLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
/***********************************************************************/ /***********************************************************************/
PTDB MYSQLDEF::GetTable(PGLOBAL g, MODE m) PTDB MYSQLDEF::GetTable(PGLOBAL g, MODE m)
{ {
return new(g) TDBMYSQL(this); if (Catfunc == 'C')
return new(g) TDBMCL(this);
else
return new(g) TDBMYSQL(this);
} // end of GetTable } // end of GetTable
/* ------------------------------------------------------------------- */ /* ------------------------------------------------------------------- */
...@@ -859,3 +863,26 @@ void MYSQLCOL::WriteColumn(PGLOBAL g) ...@@ -859,3 +863,26 @@ void MYSQLCOL::WriteColumn(PGLOBAL g)
} // endif Prep } // endif Prep
} // end of WriteColumn } // end of WriteColumn
/* ---------------------------TDBMCL class --------------------------- */
/***********************************************************************/
/* TDBMCL class constructor. */
/***********************************************************************/
TDBMCL::TDBMCL(PMYDEF tdp) : TDBCAT(tdp)
{
Host = tdp->Hostname;
Db = tdp->Database;
Tab = tdp->Tabname;
User = tdp->Username;
Pwd = tdp->Password;
Port = tdp->Portnumber;
} // end of TDBMCL constructor
/***********************************************************************/
/* GetResult: Get the list the MYSQL table columns. */
/***********************************************************************/
PQRYRES TDBMCL::GetResult(PGLOBAL g)
{
return MyColumns(g, Host, Db, User, Pwd, Tab, NULL, Port, false, false);
} // end of GetResult
// TDBMYSQL.H Olivier Bertrand 2007-2012 // TDBMYSQL.H Olivier Bertrand 2007-2013
#include "myconn.h" // MySQL connection declares #include "myconn.h" // MySQL connection declares
typedef class MYSQLDEF *PMYDEF; typedef class MYSQLDEF *PMYDEF;
...@@ -18,6 +18,7 @@ typedef class MYSQLCOL *PMYCOL; ...@@ -18,6 +18,7 @@ typedef class MYSQLCOL *PMYCOL;
/***********************************************************************/ /***********************************************************************/
class MYSQLDEF : public TABDEF {/* Logical table description */ class MYSQLDEF : public TABDEF {/* Logical table description */
friend class TDBMYSQL; friend class TDBMYSQL;
friend class TDBMCL;
public: public:
// Constructor // Constructor
MYSQLDEF(void); MYSQLDEF(void);
...@@ -104,7 +105,7 @@ class TDBMYSQL : public TDBASE { ...@@ -104,7 +105,7 @@ class TDBMYSQL : public TDBASE {
int AftRows; // The number of affected rows int AftRows; // The number of affected rows
int N; // The current table index int N; // The current table index
int Port; // MySQL port number (0 = default) int Port; // MySQL port number (0 = default)
int Nparm; // The number of statement parameters int Nparm; // The number of statement parameters
}; // end of class TDBMYSQL }; // end of class TDBMYSQL
/***********************************************************************/ /***********************************************************************/
...@@ -132,12 +133,28 @@ class MYSQLCOL : public COLBLK { ...@@ -132,12 +133,28 @@ class MYSQLCOL : public COLBLK {
// Members // Members
MYSQL_BIND *Bind; // This column bind structure pointer MYSQL_BIND *Bind; // This column bind structure pointer
PVAL To_Val; // To value used for Update/Insert PVAL To_Val; // To value used for Update/Insert
unsigned long Slen; // Bind string lengh unsigned long Slen; // Bind string lengh
int Rank; // Rank (position) number in the query int Rank; // Rank (position) number in the query
}; // end of class MYSQLCOL }; // end of class MYSQLCOL
/***********************************************************************/
/* This is the class declaration for the MYSQL column catalog table. */
/***********************************************************************/
class TDBMCL : public TDBCAT {
public:
// Constructor
TDBMCL(PMYDEF tdp);
PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db, protected:
const char *user, const char *pwd, // Specific routines
const char *table, const char *colpat, int port, bool key); virtual PQRYRES GetResult(PGLOBAL g);
// Members
PSZ Host; // Host machine to use
PSZ Db; // Database to be used by server
PSZ Tab; // External table name
PSZ User; // User logon name
PSZ Pwd; // Password logon info
int Port; // MySQL port number (0 = default)
}; // end of class TDBMCL
...@@ -89,7 +89,6 @@ extern int num_read, num_there, num_eq[2]; // Statistics ...@@ -89,7 +89,6 @@ extern int num_read, num_there, num_eq[2]; // Statistics
ODBCDEF::ODBCDEF(void) ODBCDEF::ODBCDEF(void)
{ {
Connect = Tabname = Tabowner = Tabqual = Qchar = NULL; Connect = Tabname = Tabowner = Tabqual = Qchar = NULL;
Catfunc = 0;
Catver = Options = 0; Catver = Options = 0;
} // end of ODBCDEF constructor } // end of ODBCDEF constructor
...@@ -101,7 +100,6 @@ bool ODBCDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) ...@@ -101,7 +100,6 @@ bool ODBCDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
int dop = ODBConn::noOdbcDialog; // Default for options int dop = ODBConn::noOdbcDialog; // Default for options
Desc = Connect = Cat->GetStringCatInfo(g, Name, "Connect", ""); Desc = Connect = Cat->GetStringCatInfo(g, Name, "Connect", "");
Catfunc = toupper(*Cat->GetStringCatInfo(g, Name, "Catfunc", ""));
Tabname = Cat->GetStringCatInfo(g, Name, "Name", Tabname = Cat->GetStringCatInfo(g, Name, "Name",
Catfunc == 'T' ? NULL : Name); Catfunc == 'T' ? NULL : Name);
Tabname = Cat->GetStringCatInfo(g, Name, "Tabname", Tabname); Tabname = Cat->GetStringCatInfo(g, Name, "Tabname", Tabname);
...@@ -905,259 +903,53 @@ void ODBCCOL::WriteColumn(PGLOBAL g) ...@@ -905,259 +903,53 @@ void ODBCCOL::WriteColumn(PGLOBAL g)
} // end of WriteColumn } // end of WriteColumn
/* ---------------------------TDBOIF class --------------------------- */
/***********************************************************************/
/* Implementation of the TDBOIF class. */
/***********************************************************************/
TDBOIF::TDBOIF(PODEF tdp) : TDBASE(tdp)
{
Qrp = NULL;
ID = 0;
NC = 0;
Init = false;
N = -1;
} // end of TDBOIF constructor
/***********************************************************************/
/* Allocate OIF column description block. */
/***********************************************************************/
PCOL TDBOIF::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
{
POIFCOL colp;
colp = (POIFCOL)new(g) OIFCOL(cdp, this, n);
if (cprec) {
colp->SetNext(cprec->GetNext());
cprec->SetNext(colp);
} else {
colp->SetNext(Columns);
Columns = colp;
} // endif cprec
for (int i = 1; !colp->Flag && i <= NC; i++)
if (!stricmp(colp->Name, GetMsgid(ID + i)))
colp->Flag = i;
return colp;
} // end of MakeCol
/***********************************************************************/
/* OIF: Get the number of properties. */
/***********************************************************************/
int TDBOIF::GetMaxSize(PGLOBAL g)
{
if (MaxSize < 0) {
if (Initialize(g))
return -1;
MaxSize = Qrp->Nblin;
} // endif MaxSize
return MaxSize;
} // end of GetMaxSize
/***********************************************************************/
/* OIF Access Method opening routine. */
/***********************************************************************/
bool TDBOIF::OpenDB(PGLOBAL g)
{
if (Use == USE_OPEN) {
/*******************************************************************/
/* Table already open. */
/*******************************************************************/
N = -1;
return false;
} // endif use
if (Mode != MODE_READ) {
/*******************************************************************/
/* ODBC Info tables cannot be modified. */
/*******************************************************************/
strcpy(g->Message, "OIF tables are read only");
return true;
} // endif Mode
/*********************************************************************/
/* Initialize the ODBC processing. */
/*********************************************************************/
if (Initialize(g))
return true;
return InitCol(g);
} // end of OpenDB
/***********************************************************************/
/* Initialize columns. */
/***********************************************************************/
bool TDBOIF::InitCol(PGLOBAL g)
{
POIFCOL colp;
PCOLRES crp;
for (colp = (POIFCOL)Columns; colp; colp = (POIFCOL)colp->GetNext()) {
for (crp = Qrp->Colresp; crp; crp = crp->Next)
if (colp->Flag == crp->Ncol) {
colp->Crp = crp;
break;
} // endif Flag
if (!colp->Crp) {
sprintf(g->Message, "Invalid flag %d for column %s",
colp->Flag, colp->Name);
return true;
} // endif Crp
} // endfor colp
return false;
} // end of InitCol
/***********************************************************************/
/* Data Base read routine for OIF access method. */
/***********************************************************************/
int TDBOIF::ReadDB(PGLOBAL g)
{
return (++N < Qrp->Nblin) ? RC_OK : RC_EF;
} // end of ReadDB
/***********************************************************************/
/* WriteDB: Data Base write routine for OIF access methods. */
/***********************************************************************/
int TDBOIF::WriteDB(PGLOBAL g)
{
strcpy(g->Message, "OIF tables are read only");
return RC_FX;
} // end of WriteDB
/***********************************************************************/
/* Data Base delete line routine for OIF access methods. */
/***********************************************************************/
int TDBOIF::DeleteDB(PGLOBAL g, int irc)
{
strcpy(g->Message, "Delete not enabled for OIF tables");
return RC_FX;
} // end of DeleteDB
/***********************************************************************/
/* Data Base close routine for WMI access method. */
/***********************************************************************/
void TDBOIF::CloseDB(PGLOBAL g)
{
// Nothing to do
} // end of CloseDB
// ------------------------ OIFCOL functions ----------------------------
/***********************************************************************/
/* OIFCOL public constructor. */
/***********************************************************************/
OIFCOL::OIFCOL(PCOLDEF cdp, PTDB tdbp, int n)
: COLBLK(cdp, tdbp, n)
{
Tdbp = (PTDBOIF)tdbp;
Crp = NULL;
Flag = cdp->GetOffset();
} // end of WMICOL constructor
/***********************************************************************/
/* Read the next Data Source elements. */
/***********************************************************************/
void OIFCOL::ReadColumn(PGLOBAL g)
{
// Get the value of the Name or Description property
Value->SetValue_pvblk(Crp->Kdata, Tdbp->N);
} // end of ReadColumn
/* ---------------------------TDBSRC class --------------------------- */ /* ---------------------------TDBSRC class --------------------------- */
/***********************************************************************/ /***********************************************************************/
/* Initialize: Get the list of ODBC data sources. */ /* GetResult: Get the list of ODBC data sources. */
/***********************************************************************/ /***********************************************************************/
bool TDBSRC::Initialize(PGLOBAL g) PQRYRES TDBSRC::GetResult(PGLOBAL g)
{ {
if (Init) return ODBCDataSources(g, false);
return false; } // end of GetResult
if (!(Qrp = ODBCDataSources(g, false)))
return true;
Init = true;
return false;
} // end of Initialize
/* ---------------------------TDBDRV class --------------------------- */ /* ---------------------------TDBDRV class --------------------------- */
/***********************************************************************/ /***********************************************************************/
/* Initialize: Get the list of ODBC drivers. */ /* GetResult: Get the list of ODBC drivers. */
/***********************************************************************/ /***********************************************************************/
bool TDBDRV::Initialize(PGLOBAL g) PQRYRES TDBDRV::GetResult(PGLOBAL g)
{ {
if (Init) return ODBCDrivers(g, false);
return false; } // end of GetResult
if (!(Qrp = ODBCDrivers(g, false)))
return true;
Init = true; /* ---------------------------TDBOTB class --------------------------- */
return false;
} // end of Initialize
/* ---------------------------TDBOCL class --------------------------- */
/***********************************************************************/ /***********************************************************************/
/* TDBOCL class constructor. */ /* TDBOTB class constructor. */
/***********************************************************************/ /***********************************************************************/
TDBOCL::TDBOCL(PODEF tdp) : TDBOIF(tdp) TDBOTB::TDBOTB(PODEF tdp) : TDBCAT(tdp)
{ {
ID = IDS_COLUMNS + 1;
NC = 11;
Dsn = tdp->GetConnect(); Dsn = tdp->GetConnect();
Tabn = tdp->GetTabname(); Tab = tdp->GetTabname();
} // end of TDBOCL constructor } // end of TDBOTB constructor
/***********************************************************************/ /***********************************************************************/
/* Initialize: Get the list of ODBC table columns. */ /* GetResult: Get the list of ODBC tables. */
/***********************************************************************/ /***********************************************************************/
bool TDBOCL::Initialize(PGLOBAL g) PQRYRES TDBOTB::GetResult(PGLOBAL g)
{ {
if (Init) return ODBCTables(g, Dsn, Tab, false);
return false; } // end of GetResult
if (!(Qrp = MyODBCCols(g, Dsn, Tabn, false))) /* ---------------------------TDBOCL class --------------------------- */
return true;
Init = true;
return false;
} // end of Initialize
/* ---------------------------TDBOTB class --------------------------- */
/***********************************************************************/
/* TDBOCL class constructor. */
/***********************************************************************/
TDBOTB::TDBOTB(PODEF tdp) : TDBOIF(tdp)
{
ID = IDS_TABLES + 1;
NC = 4;
Dsn = tdp->GetConnect();
Tabpat = tdp->GetTabname();
} // end of TDBOCL constructor
/***********************************************************************/ /***********************************************************************/
/* Initialize: Get the list of ODBC tables. */ /* GetResult: Get the list of ODBC table columns. */
/***********************************************************************/ /***********************************************************************/
bool TDBOTB::Initialize(PGLOBAL g) PQRYRES TDBOCL::GetResult(PGLOBAL g)
{ {
if (Init) return MyODBCCols(g, Dsn, Tab, false);
return false; } // end of GetResult
if (!(Qrp = ODBCTables(g, Dsn, Tabpat, false)))
return true;
Init = true;
return false;
} // end of Initialize
/* ------------------------ End of Tabodbc --------------------------- */ /* ------------------------ End of Tabodbc --------------------------- */
...@@ -44,7 +44,6 @@ class DllExport ODBCDEF : public TABDEF { /* Logical table description */ ...@@ -44,7 +44,6 @@ class DllExport ODBCDEF : public TABDEF { /* Logical table description */
PSZ Tabowner; /* External table owner */ PSZ Tabowner; /* External table owner */
PSZ Tabqual; /* External table qualifier */ PSZ Tabqual; /* External table qualifier */
PSZ Qchar; /* Identifier quoting character */ PSZ Qchar; /* Identifier quoting character */
char Catfunc; /* Catalog function */
int Catver; /* ODBC version for catalog functions */ int Catver; /* ODBC version for catalog functions */
int Options; /* Open connection options */ int Options; /* Open connection options */
}; // end of ODBCDEF }; // end of ODBCDEF
...@@ -163,128 +162,64 @@ class ODBCCOL : public COLBLK { ...@@ -163,128 +162,64 @@ class ODBCCOL : public COLBLK {
int Rank; // Rank (position) number in the query int Rank; // Rank (position) number in the query
}; // end of class ODBCCOL }; // end of class ODBCCOL
/***********************************************************************/
/* This is the base class declaration for the ODBC info tables. */
/***********************************************************************/
class TDBOIF : public TDBASE {
friend class OIFCOL;
public:
// Constructor
TDBOIF(PODEF tdp);
// Implementation
virtual AMT GetAmType(void) {return TYPE_AM_ODBC;}
// 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
virtual bool Initialize(PGLOBAL g) = 0;
bool InitCol(PGLOBAL g);
// Members
PQRYRES Qrp;
int ID; // Base of Column names
int NC; // Number of valid flags
int N; // Row number
bool Init;
}; // end of class TDBOIF
/***********************************************************************/
/* Class OIFCOL: ODBC info column. */
/***********************************************************************/
class OIFCOL : public COLBLK {
friend class TDBOIF;
public:
// Constructors
OIFCOL(PCOLDEF cdp, PTDB tdbp, int n);
// Implementation
virtual int GetAmType(void) {return TYPE_AM_ODBC;}
// Methods
virtual void ReadColumn(PGLOBAL g);
protected:
OIFCOL(void) {} // Default constructor not to be used
// Members
PTDBOIF Tdbp; // Points to ODBC table block
PCOLRES Crp; // The column data array
int Flag;
}; // end of class OIFCOL
/***********************************************************************/ /***********************************************************************/
/* This is the class declaration for the Data Sources catalog table. */ /* This is the class declaration for the Data Sources catalog table. */
/***********************************************************************/ /***********************************************************************/
class TDBSRC : public TDBOIF { class TDBSRC : public TDBCAT {
public: public:
// Constructor // Constructor
TDBSRC(PODEF tdp) : TDBOIF(tdp) {ID = IDS_DSRC; NC = 2;} TDBSRC(PODEF tdp) : TDBCAT(tdp) {}
protected: protected:
// Specific routines // Specific routines
virtual bool Initialize(PGLOBAL g); virtual PQRYRES GetResult(PGLOBAL g);
}; // end of class TDBSRC }; // end of class TDBSRC
/***********************************************************************/ /***********************************************************************/
/* This is the class declaration for the Drivers catalog table. */ /* This is the class declaration for the Drivers catalog table. */
/***********************************************************************/ /***********************************************************************/
class TDBDRV : public TDBOIF { class TDBDRV : public TDBCAT {
public: public:
// Constructor // Constructor
TDBDRV(PODEF tdp) : TDBOIF(tdp) {ID = IDS_DRIVER; NC = 2;} TDBDRV(PODEF tdp) : TDBCAT(tdp) {}
protected: protected:
// Specific routines // Specific routines
virtual bool Initialize(PGLOBAL g); virtual PQRYRES GetResult(PGLOBAL g);
}; // end of class TDBDRV }; // end of class TDBDRV
/***********************************************************************/ /***********************************************************************/
/* This is the class declaration for the columns catalog table. */ /* This is the class declaration for the tables catalog table. */
/***********************************************************************/ /***********************************************************************/
class TDBOCL : public TDBOIF { class TDBOTB : public TDBCAT {
public: public:
// Constructor // Constructor
TDBOCL(PODEF tdp); TDBOTB(PODEF tdp);
protected: protected:
// Specific routines // Specific routines
virtual bool Initialize(PGLOBAL g); virtual PQRYRES GetResult(PGLOBAL g);
// Members // Members
char *Dsn; // Points to connection string char *Dsn; // Points to connection string
char *Tabn; // Points to ODBC table name char *Tab; // Points to ODBC table name or pattern
}; // end of class TDBOCL }; // end of class TDBOTB
/***********************************************************************/ /***********************************************************************/
/* This is the class declaration for the tables catalog table. */ /* This is the class declaration for the columns catalog table. */
/***********************************************************************/ /***********************************************************************/
class TDBOTB : public TDBOIF { class TDBOCL : public TDBOTB {
public: public:
// Constructor // Constructor
TDBOTB(PODEF tdp); TDBOCL(PODEF tdp) : TDBOTB(tdp) {}
protected: protected:
// Specific routines // Specific routines
virtual bool Initialize(PGLOBAL g); virtual PQRYRES GetResult(PGLOBAL g);
// Members // Members
char *Dsn; // Points to connection string }; // end of class TDBOCL
char *Tabpat; // Points to ODBC table pattern
}; // end of class TDBOTB
#endif // !NODBC #endif // !NODBC
...@@ -23,13 +23,6 @@ ...@@ -23,13 +23,6 @@
extern "C" int trace; extern "C" int trace;
/**************************************************************************/
/* 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 = true, bool nonull = true);
/* ------------------- Functions WMI Column info --------------------- */ /* ------------------- Functions WMI Column info --------------------- */
/***********************************************************************/ /***********************************************************************/
...@@ -140,82 +133,90 @@ PWMIUT InitWMI(PGLOBAL g, char *nsp, char *classname) ...@@ -140,82 +133,90 @@ PWMIUT InitWMI(PGLOBAL g, char *nsp, char *classname)
/* WMIColumns: constructs the result blocks containing the description */ /* WMIColumns: constructs the result blocks containing the description */
/* of all the columns of a WMI table of a specified class. */ /* of all the columns of a WMI table of a specified class. */
/***********************************************************************/ /***********************************************************************/
PQRYRES WMIColumns(PGLOBAL g, char *nsp, char *classname, PWMIUT wp) PQRYRES WMIColumns(PGLOBAL g, char *nsp, char *cls, bool info)
{ {
static int dbtype[] = {DB_CHAR, DB_SHORT, DB_CHAR, static int dbtype[] = {DB_CHAR, DB_SHORT, DB_CHAR,
DB_INT, DB_INT, DB_SHORT}; DB_INT, DB_INT, DB_SHORT};
static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING, static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING,
TYPE_INT, TYPE_INT, TYPE_SHORT}; TYPE_INT, TYPE_INT, TYPE_SHORT};
static XFLD fldtyp[] = {FLD_NAME, FLD_TYPE, FLD_TYPENAME,
FLD_PREC, FLD_LENGTH, FLD_SCALE};
static unsigned int len, length[] = {0, 6, 8, 10, 10, 6}; static unsigned int len, length[] = {0, 6, 8, 10, 10, 6};
int i = 0, n = 0, ncol = sizeof(dbtype) / sizeof(int); int i = 0, n = 0, ncol = sizeof(dbtype) / sizeof(int);
int lng, typ, prec; int lng, typ, prec;
LONG low, upp; LONG low, upp;
BOOL b1, b2 = TRUE;
BSTR propname; BSTR propname;
VARIANT val; VARIANT val;
CIMTYPE type; CIMTYPE type;
HRESULT res; HRESULT res;
PWMIUT wp;
SAFEARRAY *prnlist = NULL; SAFEARRAY *prnlist = NULL;
PQRYRES qrp = NULL; PQRYRES qrp = NULL;
PCOLRES crp; PCOLRES crp;
/*********************************************************************/ if (!info) {
/* Initialize WMI if not done yet. */ /*******************************************************************/
/*********************************************************************/ /* Initialize WMI if not done yet. */
if ((b1 = !wp) && !(wp = InitWMI(g, nsp, classname))) /*******************************************************************/
return NULL; if (!(wp = InitWMI(g, nsp, cls)))
return NULL;
/*********************************************************************/
/* Get the number of properties to return. */
/*********************************************************************/
res = wp->Cobj->Get(bstr_t("__Property_Count"), 0, &val, NULL, NULL);
if (FAILED(res)) {
sprintf(g->Message, "failed Get(__Property_Count) res=%d\n", res);
goto err;
} // endif res
if (!(n = val.lVal)) {
sprintf(g->Message, "Class %s in %s has no properties\n",
classname, nsp);
goto err;
} // endif res
/*********************************************************************/ /*******************************************************************/
/* Get max property name length. */ /* Get the number of properties to return. */
/*********************************************************************/ /*******************************************************************/
res = wp->Cobj->GetNames(NULL, res = wp->Cobj->Get(bstr_t("__Property_Count"), 0, &val, NULL, NULL);
WBEM_FLAG_ALWAYS | WBEM_FLAG_NONSYSTEM_ONLY,
NULL, &prnlist);
if (FAILED(res)) { if (FAILED(res)) {
sprintf(g->Message, "failed GetNames res=%d\n", res); sprintf(g->Message, "failed Get(__Property_Count) res=%d\n", res);
goto err; goto err;
} // endif res } // endif res
res = SafeArrayGetLBound(prnlist, 1, &low); if (!(n = val.lVal)) {
res = SafeArrayGetUBound(prnlist, 1, &upp); sprintf(g->Message, "Class %s in %s has no properties\n",
cls, nsp);
goto err;
} // endif res
for (long i = low; i <= upp; i++) { /*******************************************************************/
// Get this property name. /* Get max property name length. */
res = SafeArrayGetElement(prnlist, &i, &propname); /*******************************************************************/
res = wp->Cobj->GetNames(NULL,
WBEM_FLAG_ALWAYS | WBEM_FLAG_NONSYSTEM_ONLY,
NULL, &prnlist);
if (FAILED(res)) { if (FAILED(res)) {
sprintf(g->Message, "failed GetArrayElement res=%d\n", res); sprintf(g->Message, "failed GetNames res=%d\n", res);
goto err; goto err;
} // endif res } // endif res
len = (unsigned)SysStringLen(propname); res = SafeArrayGetLBound(prnlist, 1, &low);
length[0] = max(length[0], len); res = SafeArrayGetUBound(prnlist, 1, &upp);
} // enfor i
for (long i = low; i <= upp; i++) {
// Get this property name.
res = SafeArrayGetElement(prnlist, &i, &propname);
if (FAILED(res)) {
sprintf(g->Message, "failed GetArrayElement res=%d\n", res);
goto err;
} // endif res
len = (unsigned)SysStringLen(propname);
length[0] = max(length[0], len);
} // enfor i
res = SafeArrayDestroy(prnlist); res = SafeArrayDestroy(prnlist);
} else
length[0] = 128;
/*********************************************************************/ /*********************************************************************/
/* Allocate the structures used to refer to the result set. */ /* Allocate the structures used to refer to the result set. */
/*********************************************************************/ /*********************************************************************/
qrp = PlgAllocResult(g, ncol, n, IDS_COLUMNS + 3, qrp = PlgAllocResult(g, ncol, n, IDS_COLUMNS + 3,
dbtype, buftyp, length); dbtype, buftyp, fldtyp, length, true, true);
if (info)
return qrp;
/*********************************************************************/ /*********************************************************************/
/* Now get the results into blocks. */ /* Now get the results into blocks. */
...@@ -309,16 +310,13 @@ PQRYRES WMIColumns(PGLOBAL g, char *nsp, char *classname, PWMIUT wp) ...@@ -309,16 +310,13 @@ PQRYRES WMIColumns(PGLOBAL g, char *nsp, char *classname, PWMIUT wp)
} // endfor i } // endfor i
qrp->Nblin = i; qrp->Nblin = i;
b2 = b1;
err: err:
if (b2) { // Cleanup
// Cleanup wp->Cobj->Release();
wp->Cobj->Release(); wp->Svc->Release();
wp->Svc->Release(); wp->Svc = NULL; // MUST be set to NULL (why?)
wp->Svc = NULL; // MUST be set to NULL (why?) CoUninitialize();
CoUninitialize();
} // endif b
/*********************************************************************/ /*********************************************************************/
/* Return the result pointer for use by GetData routines. */ /* Return the result pointer for use by GetData routines. */
...@@ -346,7 +344,7 @@ bool WMIDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) ...@@ -346,7 +344,7 @@ bool WMIDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
Wclass = strcat(strcpy(p, "Win32_"), Wclass); Wclass = strcat(strcpy(p, "Win32_"), Wclass);
} // endif Wclass } // endif Wclass
if (!(Info = Cat->GetBoolCatInfo(Name, "Info", false))) if (!Catfunc)
Ems = Cat->GetIntCatInfo(Name, "Estimate", 100); Ems = Cat->GetIntCatInfo(Name, "Estimate", 100);
return false; return false;
...@@ -357,17 +355,19 @@ bool WMIDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) ...@@ -357,17 +355,19 @@ bool WMIDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
/***********************************************************************/ /***********************************************************************/
PTDB WMIDEF::GetTable(PGLOBAL g, MODE m) PTDB WMIDEF::GetTable(PGLOBAL g, MODE m)
{ {
if (Info) if (!Catfunc)
return new(g) TDBWCL(this);
else
return new(g) TDBWMI(this); return new(g) TDBWMI(this);
else if (Catfunc == 'C')
return new(g) TDBWCL(this);
sprintf(g->Message, "Bad catfunc %c for WMI", Catfunc);
return NULL;
} // end of GetTable } // end of GetTable
/* ------------------------------------------------------------------- */ /* ------------------------------------------------------------------- */
/***********************************************************************/ /***********************************************************************/
/* Implementation of the TDBWMI class. */ /* Implementation of the TDBWMI class. */
/***********************************************************************/ /***********************************************************************/
TDBWMI::TDBWMI(PWMIDEF tdp) : TDBASE(tdp) TDBWMI::TDBWMI(PWMIDEF tdp) : TDBASE(tdp)
{ {
...@@ -826,320 +826,20 @@ void WMICOL::ReadColumn(PGLOBAL g) ...@@ -826,320 +826,20 @@ void WMICOL::ReadColumn(PGLOBAL g)
/* ---------------------------TDBWCL class --------------------------- */ /* ---------------------------TDBWCL class --------------------------- */
/***********************************************************************/ /***********************************************************************/
/* Implementation of the TDBWCL class. */ /* TDBWCL class constructor. */
/***********************************************************************/ /***********************************************************************/
TDBWCL::TDBWCL(PWMIDEF tdp) : TDBASE(tdp) TDBWCL::TDBWCL(PWMIDEF tdp) : TDBCAT(tdp)
{ {
Svc = NULL; Nsp = tdp->Nspace;
ClsObj = NULL; Cls = tdp->Wclass;
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 } // end of TDBWCL constructor
/***********************************************************************/ /***********************************************************************/
/* Allocate WCL column description block. */ /* GetResult: Get the list of the WMI class properties. */
/***********************************************************************/
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) PQRYRES TDBWCL::GetResult(PGLOBAL g)
{ {
if (Init) return WMIColumns(g, Nsp, Cls, false);
return false; } // end of GetResult
// 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
...@@ -27,7 +27,7 @@ typedef struct _WMIutil { ...@@ -27,7 +27,7 @@ typedef struct _WMIutil {
/***********************************************************************/ /***********************************************************************/
/* Functions used externally. */ /* Functions used externally. */
/***********************************************************************/ /***********************************************************************/
PQRYRES WMIColumns(PGLOBAL g, char *nsp, char *classname, PWMIUT wp); PQRYRES WMIColumns(PGLOBAL g, char *nsp, char *cls, bool info);
/* -------------------------- WMI classes ---------------------------- */ /* -------------------------- WMI classes ---------------------------- */
...@@ -37,10 +37,10 @@ PQRYRES WMIColumns(PGLOBAL g, char *nsp, char *classname, PWMIUT wp); ...@@ -37,10 +37,10 @@ PQRYRES WMIColumns(PGLOBAL g, char *nsp, char *classname, PWMIUT wp);
class WMIDEF : public TABDEF { /* Logical table description */ class WMIDEF : public TABDEF { /* Logical table description */
friend class TDBWMI; friend class TDBWMI;
friend class TDBWCL; friend class TDBWCL;
friend class TDBWCX;
public: public:
// Constructor // Constructor
WMIDEF(void) WMIDEF(void) {Pseudo = 3; Nspace = NULL; Wclass = NULL; Ems = 0;}
{Pseudo = 3; Nspace = NULL; Wclass = NULL; Ems = 0; Info = false;}
// Implementation // Implementation
virtual const char *GetType(void) {return "WMI";} virtual const char *GetType(void) {return "WMI";}
...@@ -55,7 +55,6 @@ class WMIDEF : public TABDEF { /* Logical table description */ ...@@ -55,7 +55,6 @@ class WMIDEF : public TABDEF { /* Logical table description */
char *Nspace; char *Nspace;
char *Wclass; char *Wclass;
int Ems; int Ems;
bool Info;
}; // end of WMIDEF }; // end of WMIDEF
/***********************************************************************/ /***********************************************************************/
...@@ -99,13 +98,13 @@ class TDBWMI : public TDBASE { ...@@ -99,13 +98,13 @@ class TDBWMI : public TDBASE {
char *Wclass; // Class name char *Wclass; // Class name
char *ObjPath; // Used for direct access char *ObjPath; // Used for direct access
char *Kvp; // Itou char *Kvp; // Itou
int Ems; // Estimated max size int Ems; // Estimated max size
PCOL Kcol; // Key column PCOL Kcol; // Key column
HRESULT Res; HRESULT Res;
PVBLK Vbp; PVBLK Vbp;
bool Init; bool Init;
bool Done; bool Done;
ULONG Rc; ULONG Rc;
int N; // Row number int N; // Row number
}; // end of class TDBWMI }; // end of class TDBWMI
...@@ -129,76 +128,24 @@ class WMICOL : public COLBLK { ...@@ -129,76 +128,24 @@ class WMICOL : public COLBLK {
// Members // Members
PTDBWMI Tdbp; // Points to WMI table block PTDBWMI Tdbp; // Points to WMI table block
VARIANT Prop; // Property value VARIANT Prop; // Property value
CIMTYPE Ctype; // CIM Type CIMTYPE Ctype; // CIM Type
HRESULT Res; HRESULT Res;
}; // end of class WMICOL }; // end of class WMICOL
/***********************************************************************/ /***********************************************************************/
/* This is the class declaration for the WCL table. */ /* This is the class declaration for the WMI catalog table. */
/***********************************************************************/ /***********************************************************************/
class TDBWCL : public TDBASE { class TDBWCL : public TDBCAT {
friend class WCLCOL;
public: public:
// Constructor // Constructor
TDBWCL(PWMIDEF tdp); 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: protected:
// Specific routines // Specific routines
bool Initialize(PGLOBAL g); virtual PQRYRES GetResult(PGLOBAL g);
// Members // Members
IWbemServices *Svc; // IWbemServices pointer char *Nsp; // Name space
IWbemClassObject *ClsObj; char *Cls; // Class
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 }; // 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
...@@ -15,9 +15,12 @@ ...@@ -15,9 +15,12 @@
/***********************************************************************/ /***********************************************************************/
#include "assert.h" #include "assert.h"
#include "block.h" #include "block.h"
#include "colblk.h"
//pedef class INDEXDEF *PIXDEF; //pedef class INDEXDEF *PIXDEF;
typedef char *PFIL; // Specific to CONNECT typedef char *PFIL; // Specific to CONNECT
typedef class TDBCAT *PTDBCAT;
typedef class CATCOL *PCATCOL;
/***********************************************************************/ /***********************************************************************/
/* Definition of class TBX (pure virtual class for TDB and OPJOIN) */ /* Definition of class TBX (pure virtual class for TDB and OPJOIN) */
...@@ -170,8 +173,8 @@ class DllExport TDBASE : public TDB { ...@@ -170,8 +173,8 @@ class DllExport TDBASE : public TDB {
virtual bool IsReadOnly(void) {return Read_Only;} virtual bool IsReadOnly(void) {return Read_Only;}
virtual int GetProgMax(PGLOBAL g) {return GetMaxSize(g);} virtual int GetProgMax(PGLOBAL g) {return GetMaxSize(g);}
virtual int GetProgCur(void) {return GetRecpos();} virtual int GetProgCur(void) {return GetRecpos();}
virtual PSZ GetFile(PGLOBAL g) {return "Not a file";} virtual PSZ GetFile(PGLOBAL g) {return "Not a file";}
virtual int GetRemote(void) {return 0;} virtual int GetRemote(void) {return 0;}
virtual void SetFile(PGLOBAL g, PSZ fn) {} virtual void SetFile(PGLOBAL g, PSZ fn) {}
virtual void ResetDB(void) {} virtual void ResetDB(void) {}
virtual void ResetSize(void) {MaxSize = -1;} virtual void ResetSize(void) {MaxSize = -1;}
...@@ -198,4 +201,66 @@ class DllExport TDBASE : public TDB { ...@@ -198,4 +201,66 @@ class DllExport TDBASE : public TDB {
bool Read_Only; // True for read only tables bool Read_Only; // True for read only tables
}; // end of class TDBASE }; // end of class TDBASE
/***********************************************************************/
/* The abstract base class declaration for the catalog tables. */
/***********************************************************************/
class TDBCAT : public TDBASE {
friend class CATCOL;
public:
// Constructor
TDBCAT(PTABDEF tdp);
// Implementation
virtual AMT GetAmType(void) {return TYPE_AM_CAT;}
// 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
virtual PQRYRES GetResult(PGLOBAL g) = 0;
bool Initialize(PGLOBAL g);
bool InitCol(PGLOBAL g);
// Members
PQRYRES Qrp;
int N; // Row number
bool Init;
}; // end of class TDBCAT
/***********************************************************************/
/* Class CATCOL: ODBC info column. */
/***********************************************************************/
class CATCOL : public COLBLK {
friend class TDBCAT;
public:
// Constructors
CATCOL(PCOLDEF cdp, PTDB tdbp, int n);
// Implementation
virtual int GetAmType(void) {return TYPE_AM_ODBC;}
// Methods
virtual void ReadColumn(PGLOBAL g);
protected:
CATCOL(void) {} // Default constructor not to be used
// Members
PTDBCAT Tdbp; // Points to ODBC table block
PCOLRES Crp; // The column data array
int Flag;
}; // end of class CATCOL
#endif // TABLE_DEFINED #endif // TABLE_DEFINED
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment