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 @@
/***********************************************************************/
#include "global.h"
#include "plgdbsem.h"
//#include "catalog.h"
//#include "kindex.h"
#include "filamdbf.h"
#include "tabdos.h"
#include "valblk.h"
......@@ -65,12 +63,6 @@
#define DBFTYPE 3 /* value of bits 0 and 1 if .dbf */
#define EOH 0x0D /* end-of-header marker in .dbf file */
/****************************************************************************/
/* Catalog utility function. */
/****************************************************************************/
PQRYRES PlgAllocResult(PGLOBAL, int, int, int, int *, int *,
unsigned int *, bool blank = true, bool nonull = false);
extern "C" int trace; // The general trace value
/****************************************************************************/
......@@ -186,10 +178,12 @@ static int dbfhead(PGLOBAL g, FILE *file, PSZ fn, DBFHEADER *buf)
/****************************************************************************/
PQRYRES DBFColumns(PGLOBAL g, char *fn, BOOL info)
{
static int dbtype[] = {DB_CHAR, DB_SHORT, DB_CHAR,
DB_INT, DB_INT, DB_SHORT};
static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING,
TYPE_INT, TYPE_INT, TYPE_SHORT};
static int dbtype[] = {DB_CHAR, DB_SHORT, DB_CHAR,
DB_INT, DB_INT, DB_SHORT};
static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING,
TYPE_INT, TYPE_INT, TYPE_SHORT};
static XFLD fldtyp[] = {FLD_NAME, FLD_TYPE, FLD_TYPENAME,
FLD_PREC, FLD_LENGTH, FLD_SCALE};
static unsigned int length[] = {11, 6, 8, 10, 10, 6};
char buf[2], filename[_MAX_PATH];
int ncol = sizeof(dbtype) / sizeof(int);
......@@ -204,35 +198,41 @@ PQRYRES DBFColumns(PGLOBAL g, char *fn, BOOL info)
if (trace)
htrc("DBFColumns: File %s\n", SVP(fn));
if (!fn) {
strcpy(g->Message, MSG(MISSING_FNAME));
return NULL;
} // endif fn
if (!info) {
if (!fn) {
strcpy(g->Message, MSG(MISSING_FNAME));
return NULL;
} // endif fn
/**************************************************************************/
/* Open the input file. */
/**************************************************************************/
PlugSetPath(filename, fn, PlgGetDataPath(g));
/************************************************************************/
/* Open the input file. */
/************************************************************************/
PlugSetPath(filename, fn, PlgGetDataPath(g));
if (!(infile= global_fopen(g, MSGID_CANNOT_OPEN, filename, "rb")))
return NULL;
if (!(infile= global_fopen(g, MSGID_CANNOT_OPEN, filename, "rb")))
return NULL;
/**************************************************************************/
/* Get the first 32 bytes of the header. */
/**************************************************************************/
if ((rc = dbfhead(g, infile, filename, &mainhead)) == RC_FX) {
fclose(infile);
return NULL;
} // endif dbfhead
/************************************************************************/
/* Get the first 32 bytes of the header. */
/************************************************************************/
if ((rc = dbfhead(g, infile, filename, &mainhead)) == RC_FX) {
fclose(infile);
return NULL;
} // endif dbfhead
/************************************************************************/
/* Allocate the structures used to refer to the result set. */
/************************************************************************/
fields = mainhead.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,
dbtype, buftyp, length);
qrp->Info = info || (rc == RC_INFO);
dbtype, buftyp, fldtyp, length, true, false);
//qrp->Info = info || (rc == RC_INFO);
if (info)
return qrp;
if (trace) {
htrc("Structure of %s\n", filename);
......@@ -316,6 +316,7 @@ PQRYRES DBFColumns(PGLOBAL g, char *fn, BOOL info)
qrp->Nblin = field;
fclose(infile);
#if 0
if (info) {
/************************************************************************/
/* Prepare return message for dbfinfo command. */
......@@ -330,6 +331,7 @@ PQRYRES DBFColumns(PGLOBAL g, char *fn, BOOL info)
strcat(g->Message, buf);
} // endif info
#endif // 0
/**************************************************************************/
/* Return the result pointer for use by GetData routines. */
......
......@@ -138,10 +138,6 @@
#define my_strlwr(p) my_casedn_str(default_charset_info, (p));
#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
void XmlInitParserLib(void);
void XmlCleanupParserLib(void);
......@@ -1379,9 +1375,6 @@ int ha_connect::MakeRecord(char *buf)
// This is for variable_length rows
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
map= (const MY_BITMAP *)&table->def_read_set;
......@@ -1389,6 +1382,9 @@ int ha_connect::MakeRecord(char *buf)
for (field= table->field; *field && !rc; field++) {
fp= *field;
// Default charset
charset= table->s->table_charset;
#if defined(MARIADB)
if (fp->vcol_info && !fp->stored_in_db)
continue; // This is a virtual column
......@@ -1409,28 +1405,35 @@ int ha_connect::MakeRecord(char *buf)
value= colp->GetValue();
// All this could be better optimized
if (value->GetType() == TYPE_DATE) {
if (!sdval)
sdval= AllocateValue(xp->g, TYPE_STRING, 20);
switch (fp->type()) {
case MYSQL_TYPE_DATE:
fmt= "%Y-%m-%d";
break;
case MYSQL_TYPE_TIME:
fmt= "%H:%M:%S";
break;
default:
fmt= "%Y-%m-%d %H:%M:%S";
} // endswitch type
// Get date in the format required by MySQL fields
value->FormatValue(sdval, fmt);
p= sdval->GetCharValue();
} else if (value->GetType() == TYPE_FLOAT)
p= NULL;
else
p= value->GetCharString(val);
switch (value->GetType()) {
case TYPE_DATE:
if (!sdval)
sdval= AllocateValue(xp->g, TYPE_STRING, 20);
switch (fp->type()) {
case MYSQL_TYPE_DATE:
fmt= "%Y-%m-%d";
break;
case MYSQL_TYPE_TIME:
fmt= "%H:%M:%S";
break;
default:
fmt= "%Y-%m-%d %H:%M:%S";
} // endswitch type
// Get date in the format required by MySQL fields
value->FormatValue(sdval, fmt);
p= sdval->GetCharValue();
break;
case TYPE_FLOAT:
p= NULL;
break;
case TYPE_STRING:
charset= fp->charset();
// Passthru
default:
p= value->GetCharString(val);
} // endswitch Type
if (p) {
if (fp->store(p, strlen(p), charset, CHECK_FIELD_WARN)) {
......@@ -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)
{
char ttp= '?', spc= ',', qch= 0, fnc= 0;
const char *typn= "DOS";
char ttp= '?', spc= ',', qch= 0, fnc= '*';
const char *typn= "?";
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)
char *nsp= NULL, *cls= NULL;
#endif // WIN32
char *supfnc = "*C";
int port= MYSQL_PORT, hdr= 0, mxr= 0;
uint tm;
bool b= false, ok= false, dbf= false;
LEX_STRING *comment, *name;
HA_CREATE_INFO *create_info= (HA_CREATE_INFO *)crt_info;
CHARSET_INFO *cs;
engine_option_value *pov;
PQRYRES qrp;
PCOLRES crp;
......@@ -3325,6 +3331,7 @@ bool ha_connect::pre_create(THD *thd, void *crt_info, void *alt_info)
else
ok= true;
supfnc = "*CTSD";
break;
#endif // ODBC_SUPPORT
case 'A': // DBF
......@@ -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);
} // 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) {
char *length, *decimals, *cnm, *rem;
int i, len, dec;
......@@ -3368,7 +3382,7 @@ bool ha_connect::pre_create(THD *thd, void *crt_info, void *alt_info)
switch (ttp) {
case 'A':
qrp= DBFColumns(g, fn, false);
qrp= DBFColumns(g, fn, fnc == 'C');
break;
#if defined(ODBC_SUPPORT)
case 'O':
......@@ -3394,15 +3408,16 @@ bool ha_connect::pre_create(THD *thd, void *crt_info, void *alt_info)
#endif // ODBC_SUPPORT
#if defined(MYSQL_SUPPORT)
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;
#endif // MYSQL_SUPPORT
case 'C':
qrp= CSVColumns(g, fn, spc, qch, hdr, mxr);
qrp= CSVColumns(g, fn, spc, qch, hdr, mxr, fnc == 'C');
break;
#if defined(WIN32)
case 'W':
qrp= WMIColumns(g, nsp, cls, NULL);
qrp= WMIColumns(g, nsp, cls, fnc == 'C');
break;
#endif // WIN32
} // endswitch ttp
......@@ -3412,7 +3427,8 @@ bool ha_connect::pre_create(THD *thd, void *crt_info, void *alt_info)
return true;
} // endif qrp
if (fnc) {
if (fnc && fnc != '*') {
// Catalog table
for (crp=qrp->Colresp; !b && crp; crp= crp->Next) {
cnm= encode(g, crp->Name);
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)
// Now add the field
b= add_fields(thd, alt_info, name, type, length, decimals,
0, comment, NULL, NULL, NULL);
NOT_NULL_FLAG, comment, NULL, NULL, NULL);
} // endfor crp
} else
} else // Not a catalog table
for (i= 0; !b && i < qrp->Nblin; i++) {
crp= qrp->Colresp; // Column Name
cnm= encode(g, crp->Kdata->GetCharValue(i));
name= thd->make_lex_string(NULL, cnm, strlen(cnm), true);
crp= crp->Next; // Data Type
type= PLGtoMYSQL(crp->Kdata->GetIntValue(i), true);
crp= crp->Next; // Type Name
crp= crp->Next; // Precision (length)
len= crp->Kdata->GetIntValue(i);
length= (char*)PlugSubAlloc(g, NULL, 8);
sprintf(length, "%d", len);
crp= crp->Next; // Length
crp= crp->Next; // Scale (precision)
if ((dec= crp->Kdata->GetIntValue(i))) {
decimals= (char*)PlugSubAlloc(g, NULL, 8);
sprintf(decimals, "%d", dec);
} else
decimals= NULL;
if ((crp= crp->Next) && // Remark (comment)
(rem= crp->Kdata->GetCharValue(i)))
comment= thd->make_lex_string(NULL, rem, strlen(rem), true);
else
comment= thd->make_lex_string(NULL, "", 0, true);
rem= "";
length= "";
decimals= NULL;
tm= NOT_NULL_FLAG;
cs= NULL;
for (crp= qrp->Colresp; crp; crp= crp->Next)
switch (crp->Fld) {
case FLD_NAME:
cnm= encode(g, crp->Kdata->GetCharValue(i));
name= thd->make_lex_string(NULL, cnm, strlen(cnm), true);
break;
case FLD_TYPE:
type= PLGtoMYSQL(crp->Kdata->GetIntValue(i), true);
break;
case FLD_PREC:
len= crp->Kdata->GetIntValue(i);
length= (char*)PlugSubAlloc(g, NULL, 8);
sprintf(length, "%d", len);
break;
case FLD_SCALE:
if ((dec= crp->Kdata->GetIntValue(i))) {
decimals= (char*)PlugSubAlloc(g, NULL, 8);
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
b= add_fields(thd, alt_info, name, type, length, decimals,
0, comment, NULL, NULL, NULL);
tm, comment, cs, NULL, NULL);
} // endfor i
return b;
......
......@@ -100,84 +100,9 @@ extern int xtrace;
/**************************************************************************/
//bool PlugCheckPattern(PGLOBAL, LPCSTR, LPCSTR);
//#if !defined(WIN32)
extern "C" int GetRcString(int id, char *buf, int bufsize);
//#endif // !WIN32
//void ptrc(char const *fmt, ...);
/**************************************************************************/
/* Allocate the result structure that will contain result data. */
/**************************************************************************/
PQRYRES PlgAllocResult(PGLOBAL g, int ncol, int maxres, int ids,
int *dbtype, int *buftyp, unsigned int *length,
bool blank = false, bool nonull = false)
{
char cname[NAM_LEN+1];
int i;
PCOLRES *pcrp, crp;
PQRYRES qrp;
/************************************************************************/
/* Allocate the structure used to contain the result set. */
/************************************************************************/
qrp = (PQRYRES)PlugSubAlloc(g, NULL, sizeof(QRYRES));
pcrp = &qrp->Colresp;
qrp->Continued = false;
qrp->Truncated = false;
qrp->Info = false;
qrp->Suball = true;
qrp->Maxres = maxres;
qrp->Maxsize = 0;
qrp->Nblin = 0;
qrp->Nbcol = 0; // will be ncol
qrp->Cursor = 0;
qrp->BadLines = 0;
for (i = 0; i < ncol; i++) {
*pcrp = (PCOLRES)PlugSubAlloc(g, NULL, sizeof(COLRES));
crp = *pcrp;
pcrp = &crp->Next;
crp->Colp = NULL;
crp->Ncol = ++qrp->Nbcol;
crp->Type = buftyp[i];
crp->Length = length[i];
crp->Clen = GetTypeSize(crp->Type, length[i]);
crp->Prec = 0;
crp->DBtype = dbtype[i];
if (ids > 0) {
#if defined(XMSG)
// Get header from message file
strncpy(cname, PlugReadMessage(g, ids + crp->Ncol, NULL), NAM_LEN);
cname[NAM_LEN] = 0; // for truncated long names
//#elif defined(WIN32)
// Get header from ressource file
// LoadString(s_hModule, ids + crp->Ncol, cname, sizeof(cname));
#else // !WIN32
GetRcString(ids + crp->Ncol, cname, sizeof(cname));
#endif // !WIN32
crp->Name = (PSZ)PlugSubAlloc(g, NULL, strlen(cname) + 1);
strcpy(crp->Name, cname);
} else
crp->Name = NULL; // Will be set by caller
// Allocate the Value Block that will contain data
if (crp->Length || nonull)
crp->Kdata = AllocValBlock(g, NULL, crp->Type, maxres,
crp->Length, 0, true, blank);
else
crp->Kdata = NULL;
if (g->Trace)
htrc("Column(%d) %s type=%d len=%d value=%p\n",
crp->Ncol, crp->Name, crp->Type, crp->Length, crp->Kdata);
} // endfor i
*pcrp = NULL;
return qrp;
} // end of PlgAllocResult
/***********************************************************************/
/* Get a unique char identifier for types. The letter used are: */
/* ABCDEF..I.KLM.O..R.T.VWXY.. */
......@@ -345,14 +270,14 @@ char *MYCAT::GetStringCatInfo(PGLOBAL g, PSZ name, PSZ what, PSZ sdef)
/***********************************************************************/
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;
void *field= NULL;
PCOLDEF cdp, lcdp= NULL, tocols= NULL;
PCOLINFO pcf= (PCOLINFO)PlugSubAlloc(g, NULL, sizeof(COLINFO));
// Get a unique char identifier for type
char tc= GetTypeID(type);
tc= (!defp->Catfunc) ? GetTypeID(type) : 0;
// Take care of the column definitions
i= poff= nof= nlg= 0;
......
/************** MyConn C++ Program Source Code File (.CPP) **************/
/* PROGRAM NAME: MYCONN */
/* ------------- */
/* Version 1.5 */
/* Version 1.6 */
/* */
/* COPYRIGHT: */
/* ---------- */
/* (C) Copyright to the author Olivier BERTRAND 2007-2012 */
/* (C) Copyright to the author Olivier BERTRAND 2007-2013 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
......@@ -63,13 +63,6 @@ static char *server_groups[] = {
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 */
/* 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,
PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
const char *user, const char *pwd,
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,
DB_INT, DB_SHORT, DB_CHAR, DB_CHAR};
static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_INT,
TYPE_INT, TYPE_SHORT, TYPE_STRING, TYPE_STRING};
static unsigned int length[] = {0, 4, 16, 4, 4, 4, 0, 0};
static int dbtype[] = {DB_CHAR, DB_SHORT, DB_CHAR, DB_INT,
DB_CHAR, DB_SHORT, DB_SHORT, DB_SHORT,
DB_CHAR, DB_CHAR, DB_CHAR};
static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_INT,
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];
int i, n, nf, ncol = sizeof(dbtype) / sizeof(int);
int len, type, prec, rc, k = 0;
......@@ -92,44 +90,59 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
PCOLRES crp;
MYSQLC myc;
/**********************************************************************/
/* Open the connection with the MySQL server. */
/**********************************************************************/
if (myc.Open(g, host, db, user, pwd, port))
return NULL;
if (!info) {
/********************************************************************/
/* Open the connection with the MySQL server. */
/********************************************************************/
if (myc.Open(g, host, db, user, pwd, port))
return NULL;
/**********************************************************************/
/* Do an evaluation of the result size. */
/**********************************************************************/
sprintf(cmd, "SHOW FULL COLUMNS FROM %s", table);
strcat(strcat(cmd, " FROM "), (db) ? db : PlgGetUser(g)->DBName);
/********************************************************************/
/* Do an evaluation of the result size. */
/********************************************************************/
sprintf(cmd, "SHOW FULL COLUMNS FROM %s", table);
strcat(strcat(cmd, " FROM "), (db) ? db : PlgGetUser(g)->DBName);
if (colpat)
strcat(strcat(cmd, " LIKE "), colpat);
if (colpat)
strcat(strcat(cmd, " LIKE "), colpat);
if (trace)
htrc("MyColumns: cmd='%s'\n", cmd);
if (trace)
htrc("MyColumns: cmd='%s'\n", cmd);
if ((n = myc.GetResultSize(g, cmd)) < 0) {
myc.Close();
return NULL;
} // endif n
if ((n = myc.GetResultSize(g, cmd)) < 0) {
myc.Close();
return NULL;
} // endif n
/**********************************************************************/
/* 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);
/********************************************************************/
/* Get the size of the name columns. */
/********************************************************************/
length[0] = myc.GetFieldLength(0);
} else {
n = 0;
length[0] = 128;
} // endif info
if (!key) // We are not called from Create table
ncol--; // No date format column
//if (!key) // We are not called from Create table
// ncol--; // No date format column yet
/**********************************************************************/
/* Allocate the structures used to refer to the result set. */
/**********************************************************************/
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. */
......@@ -142,7 +155,7 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
// Get column name
fld = myc.GetCharField(0);
crp = qrp->Colresp;
crp = qrp->Colresp; // Column_Name
crp->Kdata->SetValue(fld, i);
// Get type, type name, and precision
......@@ -161,56 +174,45 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
return NULL;
} // endif type
crp = crp->Next;
crp = crp->Next; // Data_Type
crp->Kdata->SetValue(type, i);
crp = crp->Next;
crp = crp->Next; // Type_Name
crp->Kdata->SetValue(cmd, i);
if (key && type == TYPE_DATE) {
if (type == TYPE_DATE) {
// When creating tables we do need info about date columns
fmt = MyDateFmt(cmd);
len = strlen(fmt);
} else
fmt = NULL;
crp = crp->Next;
crp->Name = "Length";
crp = crp->Next; // Precision
crp->Kdata->SetValue(len, i);
crp = crp->Next;
crp->Name = "Key";
if (key) {
// Creating a table, we need key info
fld = myc.GetCharField(4);
crp->Kdata->SetValue((stricmp(fld, "PRI")) ? 0 : ++k, i);
} else
crp->Kdata->SetValue(len, i);
crp = crp->Next; // was Length
fld = myc.GetCharField(4);
crp->Kdata->SetValue(fld, i);
crp = crp->Next;
crp->Name = "Prec";
crp = crp->Next; // Scale
crp->Kdata->SetValue(prec, i);
// Get comment field
crp = crp->Next;
crp->Name = "Comment";
fld = myc.GetCharField(8);
crp = crp->Next; // Radix
crp->Kdata->SetValue(0, i);
if (fld && strlen(fld))
crp->Kdata->SetValue(fld, i);
else
crp->Kdata->Reset(i);
crp = crp->Next; // Nullable
fld = myc.GetCharField(3);
crp->Kdata->SetValue((toupper(*fld) == 'Y') ? 1 : 0, i);
if (key) {
crp = crp->Next;
crp->Name = "Date_Fmt";
if (fmt)
crp->Kdata->SetValue(fmt, i);
else
crp->Kdata->Reset(i);
crp = crp->Next; // Remark
fld = myc.GetCharField(8);
crp->Kdata->SetValue(fld, 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
if (k > 1) {
......@@ -234,79 +236,6 @@ PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
return qrp;
} // 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 --------------------------- */
/***********************************************************************/
......
......@@ -38,7 +38,7 @@ typedef class MYSQLC *PMYC;
PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
const char *user, const char *pwd,
const char *table, const char *colpat,
int port, bool key);
int port, bool key, bool info);
/* -------------------------- MYCONN class --------------------------- */
......
......@@ -171,13 +171,6 @@ int TranslateSQLType(int stp, int prec, int& len)
HENV ODBConn::m_henv = SQL_NULL_HENV;
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. */
/***********************************************************************/
......@@ -235,14 +228,18 @@ void ResetNullValues(CATPARM *cap)
PQRYRES ODBCColumns(PGLOBAL g, ODBConn *ocp, char *dsn, char *table,
char *colpat)
{
static int dbtype[] = {DB_CHAR, DB_CHAR,
DB_CHAR, DB_SHORT, DB_CHAR,
DB_INT, DB_INT, DB_SHORT,
DB_SHORT, DB_SHORT, DB_CHAR};
static int buftyp[] = {TYPE_STRING, TYPE_STRING,
TYPE_STRING, TYPE_SHORT, TYPE_STRING,
TYPE_INT, TYPE_INT, TYPE_SHORT,
TYPE_SHORT, TYPE_SHORT, TYPE_STRING};
static int dbtype[] = {DB_CHAR, DB_CHAR,
DB_CHAR, DB_SHORT, DB_CHAR,
DB_INT, DB_INT, DB_SHORT,
DB_SHORT, DB_SHORT, DB_CHAR};
static int buftyp[] = {TYPE_STRING, TYPE_STRING,
TYPE_STRING, TYPE_SHORT, TYPE_STRING,
TYPE_INT, TYPE_INT, TYPE_SHORT,
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};
int n, ncol = 11;
int maxres;
......@@ -277,7 +274,7 @@ PQRYRES ODBCColumns(PGLOBAL g, ODBConn *ocp, char *dsn, char *table,
/* Allocate the structures used to refer to the result set. */
/************************************************************************/
qrp = PlgAllocResult(g, ncol, maxres, IDS_COLUMNS + 1,
dbtype, buftyp, length);
dbtype, buftyp, NULL, length, true, true);
if (!ocp) // Info table
return qrp;
......@@ -313,8 +310,8 @@ PQRYRES ODBCColumns(PGLOBAL g, ODBConn *ocp, char *dsn, char *table,
/**************************************************************************/
PQRYRES MyODBCCols(PGLOBAL g, char *dsn, char *tab, bool info)
{
int type, len, prec;
PCOLRES crpt, crpl, crpp;
// int i, type, len, prec;
// PCOLRES crp, crpt, crpl, crpp;
PQRYRES qrp;
ODBConn *ocp;
......@@ -342,6 +339,7 @@ PQRYRES MyODBCCols(PGLOBAL g, char *dsn, char *tab, bool info)
if (ocp)
ocp->Close();
#if 0
if (!qrp)
return NULL; // Error in ODBCColumns
......@@ -371,7 +369,13 @@ PQRYRES MyODBCCols(PGLOBAL g, char *dsn, char *tab, bool info)
} // endfor i
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;
} // end of MyODBCCols
......@@ -410,7 +414,8 @@ PQRYRES ODBCDataSources(PGLOBAL g, bool info)
/************************************************************************/
/* 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. */
......@@ -455,7 +460,8 @@ PQRYRES ODBCDrivers(PGLOBAL g, bool info)
/************************************************************************/
/* 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. */
......@@ -521,7 +527,7 @@ PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *tabpat, bool info)
/* Allocate the structures used to refer to the result set. */
/************************************************************************/
qrp = PlgAllocResult(g, ncol, maxres, IDS_TABLES + 1,
dbtype, buftyp, length);
dbtype, buftyp, NULL, length, true, true);
if (info)
return qrp;
......@@ -606,7 +612,7 @@ PQRYRES ODBCPrimaryKeys(PGLOBAL g, ODBConn *op, char *dsn, char *table)
/* Allocate the structure used to refer to the result set. */
/************************************************************************/
qrp = PlgAllocResult(g, ncol, maxres, IDS_PKEY + 1,
dbtype, buftyp, length);
dbtype, buftyp, NULL, length, true, true);
#ifdef DEBTRACE
htrc("Getting pkey results ncol=%d\n", qrp->Nbcol);
......@@ -693,7 +699,7 @@ PQRYRES ODBCStatistics(PGLOBAL g, ODBConn *op, char *dsn, char *pat,
/* Allocate the structure used to refer to the result set. */
/************************************************************************/
qrp = PlgAllocResult(g, ncol, maxres, IDS_STAT + 1,
dbtype, buftyp, length);
dbtype, buftyp, NULL, length, true, true);
#ifdef DEBTRACE
htrc("Getting stat results ncol=%d\n", qrp->Nbcol);
......
......@@ -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_SET = 180, /* SET Set tables am 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) */
enum RECFM {RECFM_NAF = -2, /* Not a file */
......@@ -440,6 +441,25 @@ typedef struct _tabs {
PTABADR P3;
} 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. */
/***********************************************************************/
......@@ -470,6 +490,7 @@ typedef struct _colres {
int Clen; /* Data individual internal size */
int Length; /* Data individual print length */
int Prec; /* Precision */
XFLD Fld; /* Type of field info */
} COLRES;
#if defined(WIN32) && !defined(NOEX)
......@@ -491,6 +512,13 @@ void AddPointer(PTABS, void *);
PDTP MakeDateFormat(PGLOBAL, PSZ, bool, bool, int);
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. */
/***********************************************************************/
......
/********** PlgDBUtl Fpe C++ Program Source Code File (.CPP) ***********/
/* PROGRAM NAME: PLGDBUTL */
/* ------------- */
/* Version 3.7 */
/* Version 3.8 */
/* */
/* COPYRIGHT: */
/* ---------- */
/* (C) Copyright to the author Olivier BERTRAND 1998-2012 */
/* (C) Copyright to the author Olivier BERTRAND 1998-2013 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
......@@ -66,6 +66,7 @@
#include "colblk.h"
#include "xtable.h" // header of TBX, TDB and TDBASE classes
#include "tabcol.h" // header of XTAB and COLUMN classes
#include "valblk.h"
/***********************************************************************/
/* Macro or external routine definition */
......@@ -128,6 +129,7 @@ void CloseXMLFile(PGLOBAL, PFBLOCK, bool);
void CloseXML2File(PGLOBAL, PFBLOCK, bool);
#endif // LIBXML2_SUPPORT
extern "C" int GetRcString(int id, char *buf, int bufsize);
/***********************************************************************/
/* Routines for file IO with error reporting to g->Message */
......@@ -262,6 +264,85 @@ void ptrc(char const *fmt, ...)
} // end of ptrc
#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. */
/***********************************************************************/
......
......@@ -74,6 +74,7 @@ TABDEF::TABDEF(void)
{
Owner = NULL;
Desc = NULL;
Catfunc = 0;
Card = 0;
Elemt = 0;
Sort = 0;
......@@ -95,6 +96,7 @@ bool TABDEF::Define(PGLOBAL g, PCATLG cat, LPCSTR name, LPCSTR am)
Name = (PSZ)PlugSubAlloc(g, memp, strlen(name) + 1);
strcpy(Name, name);
Cat = cat;
Catfunc = toupper(*Cat->GetStringCatInfo(g, Name, "Catfunc", ""));
Elemt = cat->GetIntCatInfo(name, "Elements", 0);
Multiple = cat->GetIntCatInfo(name, "Multiple", 0);
Degree = cat->GetIntCatInfo(name, "Degree", 0);
......
......@@ -85,6 +85,7 @@ class DllExport TABDEF : public RELDEF { /* Logical table descriptor */
// Members
PSZ Owner; /* Table owner (for ODBC) */
PSZ Desc; /* Table description */
char Catfunc; /* Catalog function */
int Card; /* (max) number of rows in table */
int Elemt; /* Number of rows in blocks or rowset */
int Sort; /* Table already sorted ??? */
......
......@@ -297,12 +297,16 @@ PTDB DOSDEF::GetTable(PGLOBAL g, MODE mode)
/* Column blocks will be allocated only when needed. */
/*********************************************************************/
if (Recfm == RECFM_DBF) {
if (map)
txfp = new(g) DBMFAM(this);
else
txfp = new(g) DBFFAM(this);
if (!Catfunc) {
if (map)
txfp = new(g) DBMFAM(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) {
if (Huge)
txfp = new(g) BGXFAM(this);
......
......@@ -34,6 +34,7 @@ class DllExport DOSDEF : public TABDEF { /* Logical table description */
virtual const char *GetType(void) {return "DOS";}
virtual PIXDEF GetIndx(void) {return To_Indx;}
virtual void SetIndx(PIXDEF xdp) {To_Indx = xdp;}
PSZ GetFn(void) {return Fn;}
PSZ GetOfn(void) {return Ofn;}
void SetBlock(int block) {Block = block;}
int GetBlock(void) {return Block;}
......
......@@ -8,6 +8,7 @@
#ifndef __TABFIX__
#define __TABFIX__
#include "tabdos.h" /* Base class declares */
#include "filamdbf.h"
typedef class FIXCOL *PFIXCOL;
typedef class BINCOL *PBINCOL;
......@@ -77,4 +78,22 @@ class DllExport BINCOL : public DOSCOL {
// Members
char Fmt; // The column numeric format
}; // 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__
/************* TabFmt C++ Program Source Code File (.CPP) **************/
/* PROGRAM NAME: TABFMT */
/* ------------- */
/* Version 3.7 */
/* Version 3.8 */
/* */
/* COPYRIGHT: */
/* ---------- */
......@@ -67,12 +67,6 @@
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 */
/* 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 *,
/* of types (TYPE_STRING < TYPE_FLOAT < TYPE_INT) (1 < 2 < 7). */
/* 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,
DB_INT, DB_INT, DB_SHORT};
static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING,
TYPE_INT, TYPE_INT, TYPE_SHORT};
static int dbtype[] = {DB_CHAR, DB_SHORT, DB_CHAR,
DB_INT, DB_INT, DB_SHORT};
static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING,
TYPE_INT, TYPE_INT, TYPE_SHORT};
static XFLD fldtyp[] = {FLD_NAME, FLD_TYPE, FLD_TYPENAME,
FLD_PREC, FLD_LENGTH, FLD_SCALE};
static unsigned int length[] = {6, 6, 8, 10, 10, 6};
char *p, *colname[MAXCOL], dechar, filename[_MAX_PATH], buf[4096];
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)
PQRYRES qrp;
PCOLRES crp;
if (info) {
imax = 0;
length[0] = 128;
goto skipit;
} // endif info
// num_max = atoi(p+1); // Max num of record to test
#if defined(WIN32)
if (strnicmp(setlocale(LC_NUMERIC, NULL), "French", 6))
if (sep == ',' || strnicmp(setlocale(LC_NUMERIC, NULL), "French", 6))
dechar = '.';
else
dechar = ',';
......@@ -328,6 +331,7 @@ PQRYRES CSVColumns(PGLOBAL g, char *fn, char sep, char q, int hdr, int mxr)
fclose(infile);
skipit:
if (trace)
htrc("CSVColumns: imax=%d hmax=%d len=%d\n",
imax, hmax, length[0]);
......@@ -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. */
/*********************************************************************/
qrp = PlgAllocResult(g, ncol, imax, IDS_COLUMNS + 3,
dbtype, buftyp, length);
dbtype, buftyp, fldtyp, length, true, false);
qrp->Nblin = imax;
if (info)
return qrp;
/*********************************************************************/
/* Now get the results into blocks. */
/*********************************************************************/
......@@ -398,11 +405,12 @@ bool CSVDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
char buf[8];
// Double check correctness of offset values
for (PCOLDEF cdp = To_Cols; cdp; cdp = cdp->GetNext())
if (cdp->GetOffset() < 1) {
strcpy(g->Message, MSG(BAD_OFFSET_VAL));
return true;
} // endif Offset
if (!Catfunc)
for (PCOLDEF cdp = To_Cols; cdp; cdp = cdp->GetNext())
if (cdp->GetOffset() < 1) {
strcpy(g->Message, MSG(BAD_OFFSET_VAL));
return true;
} // endif Offset
// Call DOSDEF DefineAM with am=CSV so FMT is not confused with FIX
if (DOSDEF::DefineAM(g, "CSV", poff))
......@@ -431,47 +439,52 @@ bool CSVDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
/***********************************************************************/
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;
/*********************************************************************/
/* 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 (Catfunc != 'C') {
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;
/*******************************************************************/
/* 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 (Compressed == 1)
txfp = new(g) ZIPFAM(this);
else {
strcpy(g->Message, "Compress 2 not supported yet");
// txfp = new(g) ZLBFAM(defp);
return NULL;
} // endelse
if (Compressed == 1)
txfp = new(g) ZIPFAM(this);
else {
strcpy(g->Message, "Compress 2 not supported yet");
// txfp = new(g) ZLBFAM(defp);
return NULL;
} // endelse
#else // !ZIP_SUPPORT
strcpy(g->Message, "Compress not supported");
return NULL;
strcpy(g->Message, "Compress not supported");
return NULL;
#endif // !ZIP_SUPPORT
} else
txfp = new(g) DOSFAM(this);
} else
txfp = new(g) DOSFAM(this);
/*********************************************************************/
/* Allocate a TDB of the proper type. */
/* Column blocks will be allocated only when needed. */
/*********************************************************************/
if (!Fmtd)
tdbp = new(g) TDBCSV(this, txfp);
else
tdbp = new(g) TDBFMT(this, txfp);
/*******************************************************************/
/* Allocate a TDB of the proper type. */
/* Column blocks will be allocated only when needed. */
/*******************************************************************/
if (!Fmtd)
tdbp = new(g) TDBCSV(this, txfp);
else
tdbp = new(g) TDBFMT(this, txfp);
if (Multiple)
tdbp = new(g) TDBMUL(tdbp);
if (Multiple)
tdbp = new(g) TDBMUL(tdbp);
} else
tdbp = new(g)TDBCCL(this);
return tdbp;
} // end of GetTable
......@@ -1389,4 +1402,26 @@ void CSVCOL::WriteColumn(PGLOBAL g)
} // 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 ---------------------------- */
/*************** 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. */
/***********************************************************************/
......@@ -14,14 +14,15 @@ typedef class TDBFMT *PTDBFMT;
/***********************************************************************/
/* 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. */
/***********************************************************************/
class DllExport CSVDEF : public DOSDEF { /* Logical table description */
friend class TDBCSV;
//friend class TDBMCV;
friend class TDBCCL;
public:
// Constructor
CSVDEF(void);
......@@ -160,10 +161,30 @@ class TDBFMT : public TDBCSV {
protected:
// Members
PSZ *FldFormat; // Field read format
void *To_Fld; // To field test buffer
int *FmtTest; // Test on ending by %n or %m
int Linenum; // Last read line
PSZ *FldFormat; // Field read format
void *To_Fld; // To field test buffer
int *FmtTest; // Test on ending by %n or %m
int Linenum; // Last read line
}; // end of class TDBFMT
/***********************************************************************/
/* 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 ------------------------- */
/************** 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. */
/***********************************************************************/
......@@ -425,3 +425,180 @@ void TDBASE::MarkDB(PGLOBAL g, PTDB tdb2)
htrc("DOS MarkDB: tdbp=%p tdb2=%p\n", this, tdb2);
} // 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) *************/
/* PROGRAM NAME: TABMYSQL */
/* ------------- */
/* Version 1.5 */
/* Version 1.6 */
/* */
/* AUTHOR: */
/* ------- */
......@@ -105,7 +105,11 @@ bool MYSQLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
/***********************************************************************/
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
/* ------------------------------------------------------------------- */
......@@ -859,3 +863,26 @@ void MYSQLCOL::WriteColumn(PGLOBAL g)
} // endif Prep
} // 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
typedef class MYSQLDEF *PMYDEF;
......@@ -18,6 +18,7 @@ typedef class MYSQLCOL *PMYCOL;
/***********************************************************************/
class MYSQLDEF : public TABDEF {/* Logical table description */
friend class TDBMYSQL;
friend class TDBMCL;
public:
// Constructor
MYSQLDEF(void);
......@@ -104,7 +105,7 @@ class TDBMYSQL : public TDBASE {
int AftRows; // The number of affected rows
int N; // The current table index
int Port; // MySQL port number (0 = default)
int Nparm; // The number of statement parameters
int Nparm; // The number of statement parameters
}; // end of class TDBMYSQL
/***********************************************************************/
......@@ -132,12 +133,28 @@ class MYSQLCOL : public COLBLK {
// Members
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
int Rank; // Rank (position) number in the query
}; // 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,
const char *user, const char *pwd,
const char *table, const char *colpat, int port, bool key);
protected:
// Specific routines
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
ODBCDEF::ODBCDEF(void)
{
Connect = Tabname = Tabowner = Tabqual = Qchar = NULL;
Catfunc = 0;
Catver = Options = 0;
} // end of ODBCDEF constructor
......@@ -101,7 +100,6 @@ bool ODBCDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
int dop = ODBConn::noOdbcDialog; // Default for options
Desc = Connect = Cat->GetStringCatInfo(g, Name, "Connect", "");
Catfunc = toupper(*Cat->GetStringCatInfo(g, Name, "Catfunc", ""));
Tabname = Cat->GetStringCatInfo(g, Name, "Name",
Catfunc == 'T' ? NULL : Name);
Tabname = Cat->GetStringCatInfo(g, Name, "Tabname", Tabname);
......@@ -905,259 +903,53 @@ void ODBCCOL::WriteColumn(PGLOBAL g)
} // 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 --------------------------- */
/***********************************************************************/
/* 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 false;
if (!(Qrp = ODBCDataSources(g, false)))
return true;
Init = true;
return false;
} // end of Initialize
return ODBCDataSources(g, false);
} // end of GetResult
/* ---------------------------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 false;
if (!(Qrp = ODBCDrivers(g, false)))
return true;
return ODBCDrivers(g, false);
} // end of GetResult
Init = true;
return false;
} // end of Initialize
/* ---------------------------TDBOCL class --------------------------- */
/* ---------------------------TDBOTB 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();
Tabn = tdp->GetTabname();
} // end of TDBOCL constructor
Tab = tdp->GetTabname();
} // 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 false;
return ODBCTables(g, Dsn, Tab, false);
} // end of GetResult
if (!(Qrp = MyODBCCols(g, Dsn, Tabn, false)))
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
/* ---------------------------TDBOCL class --------------------------- */
/***********************************************************************/
/* 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 false;
if (!(Qrp = ODBCTables(g, Dsn, Tabpat, false)))
return true;
Init = true;
return false;
} // end of Initialize
return MyODBCCols(g, Dsn, Tab, false);
} // end of GetResult
/* ------------------------ End of Tabodbc --------------------------- */
......@@ -44,7 +44,6 @@ class DllExport ODBCDEF : public TABDEF { /* Logical table description */
PSZ Tabowner; /* External table owner */
PSZ Tabqual; /* External table qualifier */
PSZ Qchar; /* Identifier quoting character */
char Catfunc; /* Catalog function */
int Catver; /* ODBC version for catalog functions */
int Options; /* Open connection options */
}; // end of ODBCDEF
......@@ -163,128 +162,64 @@ class ODBCCOL : public COLBLK {
int Rank; // Rank (position) number in the query
}; // 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. */
/***********************************************************************/
class TDBSRC : public TDBOIF {
class TDBSRC : public TDBCAT {
public:
// Constructor
TDBSRC(PODEF tdp) : TDBOIF(tdp) {ID = IDS_DSRC; NC = 2;}
TDBSRC(PODEF tdp) : TDBCAT(tdp) {}
protected:
// Specific routines
virtual bool Initialize(PGLOBAL g);
virtual PQRYRES GetResult(PGLOBAL g);
}; // end of class TDBSRC
/***********************************************************************/
/* This is the class declaration for the Drivers catalog table. */
/***********************************************************************/
class TDBDRV : public TDBOIF {
class TDBDRV : public TDBCAT {
public:
// Constructor
TDBDRV(PODEF tdp) : TDBOIF(tdp) {ID = IDS_DRIVER; NC = 2;}
TDBDRV(PODEF tdp) : TDBCAT(tdp) {}
protected:
// Specific routines
virtual bool Initialize(PGLOBAL g);
virtual PQRYRES GetResult(PGLOBAL g);
}; // 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:
// Constructor
TDBOCL(PODEF tdp);
TDBOTB(PODEF tdp);
protected:
// Specific routines
virtual bool Initialize(PGLOBAL g);
virtual PQRYRES GetResult(PGLOBAL g);
// Members
char *Dsn; // Points to connection string
char *Tabn; // Points to ODBC table name
}; // end of class TDBOCL
char *Tab; // Points to ODBC table name or pattern
}; // 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:
// Constructor
TDBOTB(PODEF tdp);
TDBOCL(PODEF tdp) : TDBOTB(tdp) {}
protected:
// Specific routines
virtual bool Initialize(PGLOBAL g);
virtual PQRYRES GetResult(PGLOBAL g);
// Members
char *Dsn; // Points to connection string
char *Tabpat; // Points to ODBC table pattern
}; // end of class TDBOTB
}; // end of class TDBOCL
#endif // !NODBC
......@@ -23,13 +23,6 @@
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 --------------------- */
/***********************************************************************/
......@@ -140,82 +133,90 @@ PWMIUT InitWMI(PGLOBAL g, char *nsp, char *classname)
/* WMIColumns: constructs the result blocks containing the description */
/* 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,
DB_INT, DB_INT, DB_SHORT};
static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING,
TYPE_INT, TYPE_INT, TYPE_SHORT};
static int dbtype[] = {DB_CHAR, DB_SHORT, DB_CHAR,
DB_INT, DB_INT, DB_SHORT};
static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING,
TYPE_INT, TYPE_INT, TYPE_SHORT};
static 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};
int i = 0, n = 0, ncol = sizeof(dbtype) / sizeof(int);
int lng, typ, prec;
LONG low, upp;
BOOL b1, b2 = TRUE;
BSTR propname;
VARIANT val;
CIMTYPE type;
HRESULT res;
PWMIUT wp;
SAFEARRAY *prnlist = NULL;
PQRYRES qrp = NULL;
PCOLRES crp;
/*********************************************************************/
/* Initialize WMI if not done yet. */
/*********************************************************************/
if ((b1 = !wp) && !(wp = InitWMI(g, nsp, classname)))
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
if (!info) {
/*******************************************************************/
/* Initialize WMI if not done yet. */
/*******************************************************************/
if (!(wp = InitWMI(g, nsp, cls)))
return NULL;
/*********************************************************************/
/* Get max property name length. */
/*********************************************************************/
res = wp->Cobj->GetNames(NULL,
WBEM_FLAG_ALWAYS | WBEM_FLAG_NONSYSTEM_ONLY,
NULL, &prnlist);
/*******************************************************************/
/* 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 GetNames res=%d\n", res);
goto err;
} // endif res
if (FAILED(res)) {
sprintf(g->Message, "failed Get(__Property_Count) res=%d\n", res);
goto err;
} // endif res
res = SafeArrayGetLBound(prnlist, 1, &low);
res = SafeArrayGetUBound(prnlist, 1, &upp);
if (!(n = val.lVal)) {
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.
res = SafeArrayGetElement(prnlist, &i, &propname);
/*******************************************************************/
/* Get max property name length. */
/*******************************************************************/
res = wp->Cobj->GetNames(NULL,
WBEM_FLAG_ALWAYS | WBEM_FLAG_NONSYSTEM_ONLY,
NULL, &prnlist);
if (FAILED(res)) {
sprintf(g->Message, "failed GetArrayElement res=%d\n", res);
sprintf(g->Message, "failed GetNames res=%d\n", res);
goto err;
} // endif res
len = (unsigned)SysStringLen(propname);
length[0] = max(length[0], len);
} // enfor i
res = SafeArrayGetLBound(prnlist, 1, &low);
res = SafeArrayGetUBound(prnlist, 1, &upp);
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. */
/*********************************************************************/
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. */
......@@ -309,16 +310,13 @@ PQRYRES WMIColumns(PGLOBAL g, char *nsp, char *classname, PWMIUT wp)
} // endfor i
qrp->Nblin = i;
b2 = b1;
err:
if (b2) {
// Cleanup
wp->Cobj->Release();
wp->Svc->Release();
wp->Svc = NULL; // MUST be set to NULL (why?)
CoUninitialize();
} // endif b
// Cleanup
wp->Cobj->Release();
wp->Svc->Release();
wp->Svc = NULL; // MUST be set to NULL (why?)
CoUninitialize();
/*********************************************************************/
/* Return the result pointer for use by GetData routines. */
......@@ -346,7 +344,7 @@ bool WMIDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
Wclass = strcat(strcpy(p, "Win32_"), Wclass);
} // endif Wclass
if (!(Info = Cat->GetBoolCatInfo(Name, "Info", false)))
if (!Catfunc)
Ems = Cat->GetIntCatInfo(Name, "Estimate", 100);
return false;
......@@ -357,17 +355,19 @@ bool WMIDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
/***********************************************************************/
PTDB WMIDEF::GetTable(PGLOBAL g, MODE m)
{
if (Info)
return new(g) TDBWCL(this);
else
if (!Catfunc)
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
/* ------------------------------------------------------------------- */
/***********************************************************************/
/* Implementation of the TDBWMI class. */
/* Implementation of the TDBWMI class. */
/***********************************************************************/
TDBWMI::TDBWMI(PWMIDEF tdp) : TDBASE(tdp)
{
......@@ -826,320 +826,20 @@ void WMICOL::ReadColumn(PGLOBAL g)
/* ---------------------------TDBWCL class --------------------------- */
/***********************************************************************/
/* Implementation of the TDBWCL class. */
/* TDBWCL class constructor. */
/***********************************************************************/
TDBWCL::TDBWCL(PWMIDEF tdp) : TDBASE(tdp)
TDBWCL::TDBWCL(PWMIDEF tdp) : TDBCAT(tdp)
{
Svc = NULL;
ClsObj = NULL;
Propname = NULL;
Nspace = tdp->Nspace;
Wclass = tdp->Wclass;
Init = false;
Done = false;
Res = 0;
N = -1;
Lng = 0;
Typ = 0;
Prec = 0;
Nsp = tdp->Nspace;
Cls = tdp->Wclass;
} // end of TDBWCL constructor
/***********************************************************************/
/* Allocate WCL column description block. */
/***********************************************************************/
PCOL TDBWCL::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
{
PWCLCOL colp;
colp = (PWCLCOL)new(g) WCLCOL(cdp, this, n);
if (cprec) {
colp->SetNext(cprec->GetNext());
cprec->SetNext(colp);
} else {
colp->SetNext(Columns);
Columns = colp;
} // endif cprec
if (!colp->Flag) {
if (!stricmp(colp->Name, "Column_Name"))
colp->Flag = 1;
else if (!stricmp(colp->Name, "Data_Type"))
colp->Flag = 2;
else if (!stricmp(colp->Name, "Type_Name"))
colp->Flag = 3;
else if (!stricmp(colp->Name, "Precision"))
colp->Flag = 4;
else if (!stricmp(colp->Name, "Length"))
colp->Flag = 5;
else if (!stricmp(colp->Name, "Scale"))
colp->Flag = 6;
} // endif Flag
return colp;
} // end of MakeCol
/***********************************************************************/
/* Initialize: Initialize WMI operations. */
/* GetResult: Get the list of the WMI class properties. */
/***********************************************************************/
bool TDBWCL::Initialize(PGLOBAL g)
PQRYRES TDBWCL::GetResult(PGLOBAL g)
{
if (Init)
return false;
// Initialize COM.
Res = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
if (FAILED(Res)) {
sprintf(g->Message, "Failed to initialize COM library. "
"Error code = %p", Res);
return true; // Program has failed.
} // endif Res
// Obtain the initial locator to Windows Management
// on a particular host computer.
IWbemLocator *loc; // Initial Windows Management locator
Res = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER,
IID_IWbemLocator, (LPVOID*) &loc);
if (FAILED(Res)) {
sprintf(g->Message, "Failed to create Locator. "
"Error code = %p", Res);
CoUninitialize();
return true; // Program has failed.
} // endif Res
// Connect to the specified namespace with the
// current user and obtain pointer to Svc
// to make IWbemServices calls.
Res = loc->ConnectServer(_bstr_t(Nspace),
NULL, NULL,0, NULL, 0, 0, &Svc);
if (FAILED(Res)) {
sprintf(g->Message, "Could not connect. Error code = %p", Res);
loc->Release();
CoUninitialize();
return true; // Program has failed.
} // endif hres
loc->Release(); // Not used anymore
return WMIColumns(g, Nsp, Cls, false);
} // end of GetResult
// 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 {
/***********************************************************************/
/* 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 ---------------------------- */
......@@ -37,10 +37,10 @@ PQRYRES WMIColumns(PGLOBAL g, char *nsp, char *classname, PWMIUT wp);
class WMIDEF : public TABDEF { /* Logical table description */
friend class TDBWMI;
friend class TDBWCL;
friend class TDBWCX;
public:
// Constructor
WMIDEF(void)
{Pseudo = 3; Nspace = NULL; Wclass = NULL; Ems = 0; Info = false;}
WMIDEF(void) {Pseudo = 3; Nspace = NULL; Wclass = NULL; Ems = 0;}
// Implementation
virtual const char *GetType(void) {return "WMI";}
......@@ -55,7 +55,6 @@ class WMIDEF : public TABDEF { /* Logical table description */
char *Nspace;
char *Wclass;
int Ems;
bool Info;
}; // end of WMIDEF
/***********************************************************************/
......@@ -99,13 +98,13 @@ class TDBWMI : public TDBASE {
char *Wclass; // Class name
char *ObjPath; // Used for direct access
char *Kvp; // Itou
int Ems; // Estimated max size
int Ems; // Estimated max size
PCOL Kcol; // Key column
HRESULT Res;
PVBLK Vbp;
bool Init;
bool Done;
ULONG Rc;
ULONG Rc;
int N; // Row number
}; // end of class TDBWMI
......@@ -129,76 +128,24 @@ class WMICOL : public COLBLK {
// Members
PTDBWMI Tdbp; // Points to WMI table block
VARIANT Prop; // Property value
CIMTYPE Ctype; // CIM Type
VARIANT Prop; // Property value
CIMTYPE Ctype; // CIM Type
HRESULT Res;
}; // 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 {
friend class WCLCOL;
class TDBWCL : public TDBCAT {
public:
// Constructor
TDBWCL(PWMIDEF tdp);
// Implementation
virtual AMT GetAmType(void) {return TYPE_AM_WMI;}
// Methods
virtual int GetRecpos(void) {return N;}
virtual int GetProgCur(void) {return N;}
virtual int RowNumber(PGLOBAL g, bool b = false) {return N + 1;}
// Database routines
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
virtual int GetMaxSize(PGLOBAL g);
virtual bool OpenDB(PGLOBAL g);
virtual int ReadDB(PGLOBAL g);
virtual int WriteDB(PGLOBAL g);
virtual int DeleteDB(PGLOBAL g, int irc);
virtual void CloseDB(PGLOBAL g);
protected:
// Specific routines
bool Initialize(PGLOBAL g);
// Specific routines
virtual PQRYRES GetResult(PGLOBAL g);
// Members
IWbemServices *Svc; // IWbemServices pointer
IWbemClassObject *ClsObj;
BSTR Propname;
char *Nspace; // Namespace
char *Wclass; // Class name
HRESULT Res;
bool Init;
bool Done;
int N; // Row number
int Lng;
int Typ;
int Prec;
char *Nsp; // Name space
char *Cls; // Class
}; // 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 @@
/***********************************************************************/
#include "assert.h"
#include "block.h"
#include "colblk.h"
//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) */
......@@ -170,8 +173,8 @@ class DllExport TDBASE : public TDB {
virtual bool IsReadOnly(void) {return Read_Only;}
virtual int GetProgMax(PGLOBAL g) {return GetMaxSize(g);}
virtual int GetProgCur(void) {return GetRecpos();}
virtual PSZ GetFile(PGLOBAL g) {return "Not a file";}
virtual int GetRemote(void) {return 0;}
virtual PSZ GetFile(PGLOBAL g) {return "Not a file";}
virtual int GetRemote(void) {return 0;}
virtual void SetFile(PGLOBAL g, PSZ fn) {}
virtual void ResetDB(void) {}
virtual void ResetSize(void) {MaxSize = -1;}
......@@ -198,4 +201,66 @@ class DllExport TDBASE : public TDB {
bool Read_Only; // True for read only tables
}; // 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
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