Commit 82e746ea authored by Olivier Bertrand's avatar Olivier Bertrand

Put almost all function prototypes in header files that are

included by the program using them.

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

A common way to handle them will permit to develop many
other such tables. Implemented:

The ODBC column catalog table.
The ODBC tables catalog table.
The ODBC drivers catalog table.

The INFO table option is replaced by the CATFUNC string option
whode first letter specifies the information to retrieve:
C: Columns (of a table)
T: Tables  (of a database)
S: Data sources
D: Drivers

Modified:
ha_connect.cc
odbconn.cpp
odbconn.h
tabodbc.h
tabodbc.cpp
rcmsg.c
tabfmt.h
tabmysql.cpp
tabwmi.cpp
tabwmi.h
resource.h
myconn.h
filamdbf.h
connect.cc
connect.h

Added:
myutil.h
parent ec2112f3
...@@ -36,8 +36,6 @@ ...@@ -36,8 +36,6 @@
#include "handler.h" #include "handler.h"
#undef OFFSET #undef OFFSET
typedef class ha_connect *PHC;
#include "global.h" #include "global.h"
#include "plgdbsem.h" #include "plgdbsem.h"
#include "xobject.h" #include "xobject.h"
...@@ -60,7 +58,7 @@ extern int xtrace; ...@@ -60,7 +58,7 @@ extern int xtrace;
/* Routines called internally by semantic routines. */ /* Routines called internally by semantic routines. */
/***********************************************************************/ /***********************************************************************/
void CntEndDB(PGLOBAL); void CntEndDB(PGLOBAL);
RCODE EvalColumns(PGLOBAL g, PTDB tdbp); RCODE EvalColumns(PGLOBAL g, PTDB tdbp);
/***********************************************************************/ /***********************************************************************/
/* MySQL routines called externally by semantic routines. */ /* MySQL routines called externally by semantic routines. */
......
...@@ -24,8 +24,27 @@ ...@@ -24,8 +24,27 @@
//typedef struct _tabdesc *PTABD; // For friend setting //typedef struct _tabdesc *PTABD; // For friend setting
typedef struct _xinfo *PXF; typedef struct _xinfo *PXF;
typedef struct _create_xinfo *PCXF; typedef struct _create_xinfo *PCXF;
typedef class ha_connect *PHC;
typedef class TDBDOX *PTDBDOX; typedef class TDBDOX *PTDBDOX;
/****************************************************************************/
/* CONNECT functions called externally. */
/****************************************************************************/
bool CntCheckDB(PGLOBAL g, PHC handler, const char *pathname);
PTDB CntGetTDB(PGLOBAL g, const char *name, MODE xmod, PHC);
bool CntOpenTable(PGLOBAL g, PTDB tdbp, MODE, char *, char *, bool, PHC);
bool CntRewindTable(PGLOBAL g, PTDB tdbp);
int CntCloseTable(PGLOBAL g, PTDB tdbp);
int CntIndexInit(PGLOBAL g, PTDB tdbp, int id);
RCODE CntReadNext(PGLOBAL g, PTDB tdbp);
RCODE CntIndexRead(PGLOBAL g, PTDB, OPVAL op, const void *k, int n);
RCODE CntWriteRow(PGLOBAL g, PTDB tdbp);
RCODE CntUpdateRow(PGLOBAL g, PTDB tdbp);
RCODE CntDeleteRow(PGLOBAL g, PTDB tdbp, bool all);
bool CntInfo(PGLOBAL g, PTDB tdbp, PXF info);
int CntIndexRange(PGLOBAL g, PTDB ptdb, const uchar* *key, uint *len,
bool *incl, key_part_map *kmap);
/***********************************************************************/ /***********************************************************************/
/* Definition of classes XCOLCRT, XIXDEF, XKPDEF, DOXDEF, TDBDOX */ /* Definition of classes XCOLCRT, XIXDEF, XKPDEF, DOXDEF, TDBDOX */
/* These classes purpose is chiefly to access protected items! */ /* These classes purpose is chiefly to access protected items! */
...@@ -74,4 +93,4 @@ class XKPDEF: public KPARTDEF { ...@@ -74,4 +93,4 @@ class XKPDEF: public KPARTDEF {
bool HasNulls; /* Can have null values */ bool HasNulls; /* Can have null values */
}; // end of class XKPDEF }; // end of class XKPDEF
RCODE CheckRecord(PGLOBAL g, PTDB tdbp, char *oldbuf, char *newbuf); //RCODE CheckRecord(PGLOBAL g, PTDB tdbp, char *oldbuf, char *newbuf);
...@@ -16,6 +16,11 @@ typedef class DBFBASE *PDBF; ...@@ -16,6 +16,11 @@ typedef class DBFBASE *PDBF;
typedef class DBFFAM *PDBFFAM; typedef class DBFFAM *PDBFFAM;
typedef class DBMFAM *PDBMFAM; typedef class DBMFAM *PDBMFAM;
/****************************************************************************/
/* Functions used externally. */
/****************************************************************************/
PQRYRES DBFColumns(PGLOBAL g, char *fn, BOOL info);
/****************************************************************************/ /****************************************************************************/
/* This is the base class for dBASE file access methods. */ /* This is the base class for dBASE file access methods. */
/****************************************************************************/ /****************************************************************************/
......
...@@ -104,6 +104,7 @@ ...@@ -104,6 +104,7 @@
#include "create_options.h" #include "create_options.h"
#include "mysql_com.h" #include "mysql_com.h"
#include "field.h" #include "field.h"
#include "sql_parse.h"
#undef OFFSET #undef OFFSET
#define NOPARSE #define NOPARSE
...@@ -112,70 +113,40 @@ ...@@ -112,70 +113,40 @@
#endif // UNIX #endif // UNIX
#include "global.h" #include "global.h"
#include "plgdbsem.h" #include "plgdbsem.h"
#if defined(ODBC_SUPPORT)
#include "odbconn.h"
#endif // ODBC_SUPPORT
#if defined(MYSQL_SUPPORT)
#include "myconn.h"
#endif // MYSQL_SUPPORT
#include "filamdbf.h"
#include "tabfmt.h"
#include "reldef.h" #include "reldef.h"
#include "tabcol.h" #include "tabcol.h"
#include "xindex.h" #include "xindex.h"
#if defined(WIN32)
#include "tabwmi.h"
#endif // WIN32
#include "connect.h" #include "connect.h"
#include "user_connect.h" #include "user_connect.h"
#include "ha_connect.h" #include "ha_connect.h"
#include "mycat.h" #include "mycat.h"
#include "myutil.h"
#define PLGINI "plugdb.ini" /* Configuration settings file */
#define PLGXINI "plgcnx.ini" /* Configuration settings file */ #define PLGXINI "plgcnx.ini" /* Configuration settings file */
#define my_strupr(p) my_caseup_str(default_charset_info, (p)); #define my_strupr(p) my_caseup_str(default_charset_info, (p));
#define my_strlwr(p) my_casedn_str(default_charset_info, (p)); #define my_strlwr(p) my_casedn_str(default_charset_info, (p));
#define my_stricmp(a, b) my_strcasecmp(default_charset_info, (a), (b)) #define my_stricmp(a,b) my_strcasecmp(default_charset_info, (a), (b))
#if defined (WIN32) #if defined (WIN32)
typedef struct _WMIutil *PWMIUT; /* Used to call WMIColumns */ typedef struct _WMIutil *PWMIUT; /* Used to call WMIColumns */
#endif #endif
/****************************************************************************/
/* CONNECT functions called externally. */
/****************************************************************************/
bool CntCheckDB(PGLOBAL g, PHC handler, const char *pathname);
PTDB CntGetTDB(PGLOBAL g, const char *name, MODE xmod, PHC);
bool CntOpenTable(PGLOBAL g, PTDB tdbp, MODE, char *, char *, bool, PHC);
bool CntRewindTable(PGLOBAL g, PTDB tdbp);
int CntCloseTable(PGLOBAL g, PTDB tdbp);
int CntIndexInit(PGLOBAL g, PTDB tdbp, int id);
RCODE CntReadNext(PGLOBAL g, PTDB tdbp);
RCODE CntIndexRead(PGLOBAL g, PTDB, OPVAL op, const void *k, int n);
RCODE CntWriteRow(PGLOBAL g, PTDB tdbp);
RCODE CntUpdateRow(PGLOBAL g, PTDB tdbp);
RCODE CntDeleteRow(PGLOBAL g, PTDB tdbp, bool all);
bool CntInfo(PGLOBAL g, PTDB tdbp, PXF info);
int CntIndexRange(PGLOBAL g, PTDB ptdb, const uchar* *key, uint *len,
bool *incl, key_part_map *kmap);
#ifdef LIBXML2_SUPPORT #ifdef LIBXML2_SUPPORT
void XmlInitParserLib(void); void XmlInitParserLib(void);
void XmlCleanupParserLib(void); void XmlCleanupParserLib(void);
#endif // LIBXML2_SUPPORT #endif // LIBXML2_SUPPORT
/****************************************************************************/
/* Functions called externally by pre_parser. */
/****************************************************************************/
PQRYRES DBFColumns(PGLOBAL g, char *fn, BOOL info);
PQRYRES CSVColumns(PGLOBAL g, char *fn, char sep, char q, int hdr, int mxr);
#if defined(ODBC_SUPPORT)
PQRYRES ODBCDataSources(PGLOBAL g, bool info = true);
PQRYRES MyODBCCols(PGLOBAL g, char *tab, char *dsn, bool info);
#endif // ODBC_SUPPORT
#if defined(MYSQL_SUPPORT)
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);
#endif // MYSQL_SUPPORT
enum enum_field_types PLGtoMYSQL(int type, bool gdf);
#if defined(WIN32)
PQRYRES WMIColumns(PGLOBAL g, char *nsp, char *classname, PWMIUT wp= NULL);
#endif // WIN32
char GetTypeID(char *type);
bool check_string_char_length(LEX_STRING *str, const char *err_msg,
uint max_char_length, CHARSET_INFO *cs,
bool no_error);
/***********************************************************************/ /***********************************************************************/
/* DB static variables. */ /* DB static variables. */
/***********************************************************************/ /***********************************************************************/
...@@ -185,7 +156,7 @@ extern "C" char nmfile[]; ...@@ -185,7 +156,7 @@ extern "C" char nmfile[];
extern "C" char pdebug[]; extern "C" char pdebug[];
extern "C" { extern "C" {
char version[]= "Version 1.00.0005 October 03, 2012"; char version[]= "Version 1.01.0001 February 08, 2013";
#if defined(XMSG) #if defined(XMSG)
char msglang[]; // Default message language char msglang[]; // Default message language
...@@ -237,7 +208,7 @@ struct ha_table_option_struct { ...@@ -237,7 +208,7 @@ struct ha_table_option_struct {
const char *qchar; const char *qchar;
const char *module; const char *module;
const char *subtype; const char *subtype;
const char *info; const char *catfunc;
const char *oplist; const char *oplist;
int lrecl; int lrecl;
int elements; int elements;
...@@ -268,7 +239,7 @@ ha_create_table_option connect_table_option_list[]= ...@@ -268,7 +239,7 @@ ha_create_table_option connect_table_option_list[]=
HA_TOPTION_STRING("QCHAR", qchar), HA_TOPTION_STRING("QCHAR", qchar),
HA_TOPTION_STRING("MODULE", module), HA_TOPTION_STRING("MODULE", module),
HA_TOPTION_STRING("SUBTYPE", subtype), HA_TOPTION_STRING("SUBTYPE", subtype),
HA_TOPTION_STRING("INFO", info), HA_TOPTION_STRING("CATFUNC", catfunc),
HA_TOPTION_STRING("OPTION_LIST", oplist), HA_TOPTION_STRING("OPTION_LIST", oplist),
HA_TOPTION_NUMBER("LRECL", lrecl, 0, 0, INT_MAX32, 1), HA_TOPTION_NUMBER("LRECL", lrecl, 0, 0, INT_MAX32, 1),
HA_TOPTION_NUMBER("BLOCK_SIZE", elements, 0, 0, INT_MAX32, 1), HA_TOPTION_NUMBER("BLOCK_SIZE", elements, 0, 0, INT_MAX32, 1),
...@@ -816,8 +787,8 @@ char *ha_connect::GetStringOption(char *opname, char *sdef) ...@@ -816,8 +787,8 @@ char *ha_connect::GetStringOption(char *opname, char *sdef)
opval= (char*)options->module; opval= (char*)options->module;
else if (!stricmp(opname, "Subtype")) else if (!stricmp(opname, "Subtype"))
opval= (char*)options->subtype; opval= (char*)options->subtype;
else if (!stricmp(opname, "Info")) else if (!stricmp(opname, "Catfunc"))
opval= (char*)options->info; opval= (char*)options->catfunc;
if (!opval && options->oplist) if (!opval && options->oplist)
opval= GetListOption(opname, options->oplist); opval= GetListOption(opname, options->oplist);
...@@ -3282,15 +3253,15 @@ bool ha_connect::add_fields(THD *thd, void *alt_info, ...@@ -3282,15 +3253,15 @@ bool ha_connect::add_fields(THD *thd, void *alt_info,
*/ */
bool ha_connect::pre_create(THD *thd, void *crt_info, void *alt_info) bool ha_connect::pre_create(THD *thd, void *crt_info, void *alt_info)
{ {
char ttp= '?', spc= ',', qch= 0; char ttp= '?', spc= ',', qch= 0, fnc= 0;
const char *typn= "DOS"; const char *typn= "DOS";
const char *user; const char *user;
char *fn, *dsn, *tab, *db, *host, *pwd, *prt, *sep, *inf; char *fn, *dsn, *tab, *db, *host, *pwd, *prt, *sep;
#if defined(WIN32) #if defined(WIN32)
char *nsp= NULL, *cls= NULL; char *nsp= NULL, *cls= NULL;
#endif // WIN32 #endif // WIN32
int port= MYSQL_PORT, hdr= 0, mxr= 0; int port= MYSQL_PORT, hdr= 0, mxr= 0;
bool b= false, ok= false, info= false; bool b= false, ok= false, dbf= false;
LEX_STRING *comment, *name; LEX_STRING *comment, *name;
HA_CREATE_INFO *create_info= (HA_CREATE_INFO *)crt_info; HA_CREATE_INFO *create_info= (HA_CREATE_INFO *)crt_info;
engine_option_value *pov; engine_option_value *pov;
...@@ -3298,16 +3269,13 @@ bool ha_connect::pre_create(THD *thd, void *crt_info, void *alt_info) ...@@ -3298,16 +3269,13 @@ bool ha_connect::pre_create(THD *thd, void *crt_info, void *alt_info)
PCOLRES crp; PCOLRES crp;
PGLOBAL g= GetPlug(thd); PGLOBAL g= GetPlug(thd);
fn= dsn= tab= db= host= pwd= prt= sep= inf= NULL; if (!g)
user= NULL;
if (g) {
// Set default values
tab= (char*)create_info->alias;
db= thd->db;
} else
return true; return true;
fn= dsn= tab= host= pwd= prt= sep= NULL;
user= NULL;
db= thd->db; // Default value
// Get the useful create options // Get the useful create options
for (pov= create_info->option_list; pov; pov= pov->next) for (pov= create_info->option_list; pov; pov= pov->next)
if (!stricmp(pov->name.str, "table_type")) { if (!stricmp(pov->name.str, "table_type")) {
...@@ -3319,8 +3287,8 @@ bool ha_connect::pre_create(THD *thd, void *crt_info, void *alt_info) ...@@ -3319,8 +3287,8 @@ bool ha_connect::pre_create(THD *thd, void *crt_info, void *alt_info)
tab= pov->value.str; tab= pov->value.str;
} else if (!stricmp(pov->name.str, "db_name")) { } else if (!stricmp(pov->name.str, "db_name")) {
db= pov->value.str; db= pov->value.str;
} else if (!stricmp(pov->name.str, "info")) { } else if (!stricmp(pov->name.str, "catfunc")) {
inf= pov->value.str; fnc= toupper(*pov->value.str);
} else if (!stricmp(pov->name.str, "sep_char")) { } else if (!stricmp(pov->name.str, "sep_char")) {
sep= pov->value.str; sep= pov->value.str;
spc= (!strcmp(sep, "\\t")) ? '\t' : *sep; spc= (!strcmp(sep, "\\t")) ? '\t' : *sep;
...@@ -3343,15 +3311,16 @@ bool ha_connect::pre_create(THD *thd, void *crt_info, void *alt_info) ...@@ -3343,15 +3311,16 @@ bool ha_connect::pre_create(THD *thd, void *crt_info, void *alt_info)
cls= GetListOption("class", pov->value.str); cls= GetListOption("class", pov->value.str);
#endif // WIN32 #endif // WIN32
mxr= atoi(GetListOption("maxerr", pov->value.str, "0")); mxr= atoi(GetListOption("maxerr", pov->value.str, "0"));
inf= GetListOption("info", pov->value.str);
} // endelse option_list } // endelse option_list
if (!tab && fnc != 'T')
tab= (char*)create_info->alias;
switch (ttp) { switch (ttp) {
#if defined(ODBC_SUPPORT) #if defined(ODBC_SUPPORT)
case 'O': // ODBC case 'O': // ODBC
info= inf && !!strchr("1yYoO", *inf); if (!(dsn= create_info->connect_string.str)
&& fnc != 'S'&& fnc != 'D')
if (!(dsn= create_info->connect_string.str) && !info)
sprintf(g->Message, "Missing %s connection string", typn); sprintf(g->Message, "Missing %s connection string", typn);
else else
ok= true; ok= true;
...@@ -3359,6 +3328,8 @@ bool ha_connect::pre_create(THD *thd, void *crt_info, void *alt_info) ...@@ -3359,6 +3328,8 @@ bool ha_connect::pre_create(THD *thd, void *crt_info, void *alt_info)
break; break;
#endif // ODBC_SUPPORT #endif // ODBC_SUPPORT
case 'A': // DBF case 'A': // DBF
dbf= true;
// Passthru
case 'C': // CSV case 'C': // CSV
if (!fn) if (!fn)
sprintf(g->Message, "Missing %s file name", typn); sprintf(g->Message, "Missing %s file name", typn);
...@@ -3401,10 +3372,23 @@ bool ha_connect::pre_create(THD *thd, void *crt_info, void *alt_info) ...@@ -3401,10 +3372,23 @@ bool ha_connect::pre_create(THD *thd, void *crt_info, void *alt_info)
break; break;
#if defined(ODBC_SUPPORT) #if defined(ODBC_SUPPORT)
case 'O': case 'O':
if (dsn) switch (fnc) {
qrp= MyODBCCols(g, tab, dsn, info); case 'C':
else case '\0':
qrp= ODBCDataSources(g); qrp= MyODBCCols(g, dsn, tab, fnc == 'C');
break;
case 'T':
qrp= ODBCTables(g, dsn, tab, true);
break;
case 'S':
qrp= ODBCDataSources(g, true);
break;
case 'D':
qrp= ODBCDrivers(g, true);
break;
default:
sprintf(g->Message, "invalid catfunc %c", fnc);
} // endswitch info
break; break;
#endif // ODBC_SUPPORT #endif // ODBC_SUPPORT
...@@ -3418,7 +3402,7 @@ bool ha_connect::pre_create(THD *thd, void *crt_info, void *alt_info) ...@@ -3418,7 +3402,7 @@ bool ha_connect::pre_create(THD *thd, void *crt_info, void *alt_info)
break; break;
#if defined(WIN32) #if defined(WIN32)
case 'W': case 'W':
qrp= WMIColumns(g, nsp, cls); qrp= WMIColumns(g, nsp, cls, NULL);
break; break;
#endif // WIN32 #endif // WIN32
} // endswitch ttp } // endswitch ttp
...@@ -3428,11 +3412,11 @@ bool ha_connect::pre_create(THD *thd, void *crt_info, void *alt_info) ...@@ -3428,11 +3412,11 @@ bool ha_connect::pre_create(THD *thd, void *crt_info, void *alt_info)
return true; return true;
} // endif qrp } // endif qrp
if (info) { if (fnc) {
for (crp=qrp->Colresp; !b && crp; crp= crp->Next) { for (crp=qrp->Colresp; !b && crp; crp= crp->Next) {
cnm= encode(g, crp->Name); cnm= encode(g, crp->Name);
name= thd->make_lex_string(NULL, cnm, strlen(cnm), true); name= thd->make_lex_string(NULL, cnm, strlen(cnm), true);
type= PLGtoMYSQL(crp->Type, true); type= PLGtoMYSQL(crp->Type, dbf);
len= crp->Length; len= crp->Length;
length= (char*)PlugSubAlloc(g, NULL, 8); length= (char*)PlugSubAlloc(g, NULL, 8);
sprintf(length, "%d", len); sprintf(length, "%d", len);
......
...@@ -39,6 +39,8 @@ ...@@ -39,6 +39,8 @@
#include "global.h" #include "global.h"
#include "plgdbsem.h" #include "plgdbsem.h"
#include "plgcnx.h" // For DB types
#include "resource.h"
#include "value.h" #include "value.h"
#include "valblk.h" #include "valblk.h"
#define DLL_EXPORT // Items are exported from this DLL #define DLL_EXPORT // Items are exported from this DLL
...@@ -59,6 +61,252 @@ static char *server_groups[] = { ...@@ -59,6 +61,252 @@ static char *server_groups[] = {
}; };
#endif // EMBEDDED #endif // EMBEDDED
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. */
/* key = TRUE when called from Create Table to get key informations. */
/************************************************************************/
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)
{
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};
char *fld, *fmt, cmd[128];
int i, n, nf, ncol = sizeof(dbtype) / sizeof(int);
int len, type, prec, rc, k = 0;
PQRYRES qrp;
PCOLRES crp;
MYSQLC myc;
/**********************************************************************/
/* 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);
if (colpat)
strcat(strcat(cmd, " LIKE "), colpat);
if (trace)
htrc("MyColumns: cmd='%s'\n", cmd);
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);
if (!key) // We are not called from Create table
ncol--; // No date format column
/**********************************************************************/
/* Allocate the structures used to refer to the result set. */
/**********************************************************************/
qrp = PlgAllocResult(g, ncol, n, IDS_COLUMNS + 3,
dbtype, buftyp, length);
/**********************************************************************/
/* Now get the results into blocks. */
/**********************************************************************/
for (i = 0; i < n; i++) {
if ((rc = myc.Fetch(g, -1) == RC_FX))
return NULL;
else if (rc == RC_NF)
break;
// Get column name
fld = myc.GetCharField(0);
crp = qrp->Colresp;
crp->Kdata->SetValue(fld, i);
// Get type, type name, and precision
fld = myc.GetCharField(1);
prec = 0;
len = 256; // Default for text or blob
if ((nf = sscanf(fld, "%[^(](%d,%d", cmd, &len, &prec)) < 1) {
sprintf(g->Message, MSG(BAD_FIELD_TYPE), fld);
return NULL;
} else
qrp->Nblin++;
if ((type = MYSQLtoPLG(cmd)) == TYPE_ERROR) {
sprintf(g->Message, "Unsupported column type %s", cmd);
return NULL;
} // endif type
crp = crp->Next;
crp->Kdata->SetValue(type, i);
crp = crp->Next;
crp->Kdata->SetValue(cmd, i);
if (key && 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->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;
crp->Name = "Prec";
crp->Kdata->SetValue(prec, i);
// Get comment field
crp = crp->Next;
crp->Name = "Comment";
fld = myc.GetCharField(8);
if (fld && strlen(fld))
crp->Kdata->SetValue(fld, i);
else
crp->Kdata->Reset(i);
if (key) {
crp = crp->Next;
crp->Name = "Date_Fmt";
if (fmt)
crp->Kdata->SetValue(fmt, i);
else
crp->Kdata->Reset(i);
} // endif key
} // endfor i
if (k > 1) {
// Multicolumn primary key
PVBLK vbp = qrp->Colresp->Next->Next->Next->Next->Kdata;
for (i = 0; i < n; i++)
if (vbp->GetIntValue(i))
vbp->SetValue(k, i);
} // endif k
/**********************************************************************/
/* Close MySQL connection. */
/**********************************************************************/
myc.Close();
/**********************************************************************/
/* Return the result pointer for use by GetData routines. */
/**********************************************************************/
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 --------------------------- */ /* -------------------------- Class MYSQLC --------------------------- */
/***********************************************************************/ /***********************************************************************/
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#endif // !WIN32 #endif // !WIN32
#include <mysql.h> #include <mysql.h>
#include <errmsg.h> #include <errmsg.h>
#include "myutil.h"
#if defined(WIN32) && defined(MYCONN_EXPORTS) #if defined(WIN32) && defined(MYCONN_EXPORTS)
#if defined(DLL_EXPORT) #if defined(DLL_EXPORT)
...@@ -32,13 +33,12 @@ ...@@ -32,13 +33,12 @@
typedef class MYSQLC *PMYC; typedef class MYSQLC *PMYC;
/***********************************************************************/ /***********************************************************************/
/* Exported/Imported functions. */ /* Prototypes of info functions. */
/***********************************************************************/ /***********************************************************************/
DllItem int MYSQLtoPLG(char *); PQRYRES MyColumns(PGLOBAL g, const char *host, const char *db,
DllItem int MYSQLtoPLG(int); const char *user, const char *pwd,
DllItem enum enum_field_types PLGtoMYSQL(int, bool gdf = FALSE); const char *table, const char *colpat,
DllItem char *MyDateFmt(int); int port, bool key);
DllItem char *MyDateFmt(char *);
/* -------------------------- MYCONN class --------------------------- */ /* -------------------------- MYCONN class --------------------------- */
......
...@@ -59,7 +59,7 @@ int MYSQLtoPLG(char *typname) ...@@ -59,7 +59,7 @@ int MYSQLtoPLG(char *typname)
/************************************************************************/ /************************************************************************/
/* Convert from PlugDB type to MySQL type number */ /* Convert from PlugDB type to MySQL type number */
/************************************************************************/ /************************************************************************/
enum enum_field_types PLGtoMYSQL(int type, bool gdf) enum enum_field_types PLGtoMYSQL(int type, bool dbf)
{ {
enum enum_field_types mytype; enum enum_field_types mytype;
...@@ -74,7 +74,7 @@ enum enum_field_types PLGtoMYSQL(int type, bool gdf) ...@@ -74,7 +74,7 @@ enum enum_field_types PLGtoMYSQL(int type, bool gdf)
mytype = MYSQL_TYPE_DOUBLE; mytype = MYSQL_TYPE_DOUBLE;
break; break;
case TYPE_DATE: case TYPE_DATE:
mytype = (gdf) ? MYSQL_TYPE_DATE : MYSQL_TYPE_DATETIME; mytype = (dbf) ? MYSQL_TYPE_DATE : MYSQL_TYPE_DATETIME;
break; break;
case TYPE_STRING: case TYPE_STRING:
mytype = MYSQL_TYPE_VARCHAR; mytype = MYSQL_TYPE_VARCHAR;
......
/***********************************************************************/
/* Prototypes of Functions used externally. */
/***********************************************************************/
enum enum_field_types PLGtoMYSQL(int type, bool dbf);
int MYSQLtoPLG(char *typname);
int MYSQLtoPLG(int mytype);
char *MyDateFmt(int mytype);
char *MyDateFmt(char *typname);
...@@ -311,7 +311,7 @@ PQRYRES ODBCColumns(PGLOBAL g, ODBConn *ocp, char *dsn, char *table, ...@@ -311,7 +311,7 @@ PQRYRES ODBCColumns(PGLOBAL g, ODBConn *ocp, char *dsn, char *table,
/**************************************************************************/ /**************************************************************************/
/* MyODBCCols: returns column info as required by ha_connect::pre_create. */ /* MyODBCCols: returns column info as required by ha_connect::pre_create. */
/**************************************************************************/ /**************************************************************************/
PQRYRES MyODBCCols(PGLOBAL g, char *tab, char *dsn, bool info) PQRYRES MyODBCCols(PGLOBAL g, char *dsn, char *tab, bool info)
{ {
int type, len, prec; int type, len, prec;
PCOLRES crpt, crpl, crpp; PCOLRES crpt, crpl, crpp;
...@@ -388,7 +388,7 @@ PQRYRES ODBCDataSources(PGLOBAL g, bool info) ...@@ -388,7 +388,7 @@ PQRYRES ODBCDataSources(PGLOBAL g, bool info)
int n = 0, ncol = 2; int n = 0, ncol = 2;
int maxres; int maxres;
PQRYRES qrp; PQRYRES qrp;
ODBConn *ocp; ODBConn *ocp = NULL;
/************************************************************************/ /************************************************************************/
/* Do an evaluation of the result size. */ /* Do an evaluation of the result size. */
...@@ -424,14 +424,57 @@ PQRYRES ODBCDataSources(PGLOBAL g, bool info) ...@@ -424,14 +424,57 @@ PQRYRES ODBCDataSources(PGLOBAL g, bool info)
return qrp; return qrp;
} // end of ODBCDataSources } // end of ODBCDataSources
#if 0 // Currently not used by CONNECT /*************************************************************************/
/* ODBCDrivers: constructs the result blocks containing all ODBC */
/* drivers available on the local host. */
/* Called with info=true to have result column names. */
/*************************************************************************/
PQRYRES ODBCDrivers(PGLOBAL g, bool info)
{
static int dbtype[] = {DB_CHAR, DB_CHAR};
static int buftyp[] = {TYPE_STRING, TYPE_STRING};
static unsigned int length[] = {128, 256};
int ncol = 2;
int maxres;
PQRYRES qrp;
ODBConn *ocp = NULL;
/************************************************************************/
/* Do an evaluation of the result size. */
/************************************************************************/
if (!info) {
ocp = new(g) ODBConn(g, NULL);
maxres = 256; // Estimated max number of drivers
} else
maxres = 0;
#ifdef DEBTRACE
htrc("ODBCDrivers: max=%d len=%d\n", maxres, length[0]);
#endif
/************************************************************************/
/* Allocate the structures used to refer to the result set. */
/************************************************************************/
qrp = PlgAllocResult(g, ncol, maxres, IDS_DRIVER, dbtype, buftyp, length);
/************************************************************************/
/* Now get the results into blocks. */
/************************************************************************/
if (!info && ocp->GetDrivers(qrp))
qrp = NULL;
/************************************************************************/
/* Return the result pointer for use by GetData routines. */
/************************************************************************/
return qrp;
} // end of ODBCDrivers
/***********************************************************************/ /***********************************************************************/
/* ODBCTables: constructs the result blocks containing all tables in */ /* ODBCTables: constructs the result blocks containing all tables in */
/* an ODBC database that will be retrieved by GetData commands. */ /* an ODBC database that will be retrieved by GetData commands. */
/* Note: The first two columns (Qualifier, Owner) are ignored. */ /* Note: The first two columns (Qualifier, Owner) are ignored. */
/***********************************************************************/ /***********************************************************************/
PQRYRES ODBCTables(PGLOBAL g, ODBConn *op, char *dsn, char *tabpat, PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *tabpat, bool info)
char *tabtyp)
{ {
static int dbtype[] = {DB_CHAR, DB_CHAR, DB_CHAR, DB_CHAR}; static int dbtype[] = {DB_CHAR, DB_CHAR, DB_CHAR, DB_CHAR};
static int buftyp[] = {TYPE_STRING, TYPE_STRING, static int buftyp[] = {TYPE_STRING, TYPE_STRING,
...@@ -441,9 +484,9 @@ PQRYRES ODBCTables(PGLOBAL g, ODBConn *op, char *dsn, char *tabpat, ...@@ -441,9 +484,9 @@ PQRYRES ODBCTables(PGLOBAL g, ODBConn *op, char *dsn, char *tabpat,
int maxres; int maxres;
PQRYRES qrp; PQRYRES qrp;
CATPARM *cap; CATPARM *cap;
ODBConn *ocp = op; ODBConn *ocp;
if (!op) { if (!info) {
/**********************************************************************/ /**********************************************************************/
/* Open the connection with the ODBC data source. */ /* Open the connection with the ODBC data source. */
/**********************************************************************/ /**********************************************************************/
...@@ -452,16 +495,22 @@ PQRYRES ODBCTables(PGLOBAL g, ODBConn *op, char *dsn, char *tabpat, ...@@ -452,16 +495,22 @@ PQRYRES ODBCTables(PGLOBAL g, ODBConn *op, char *dsn, char *tabpat,
if (ocp->Open(dsn, 2) < 1) // 2 is openReadOnly if (ocp->Open(dsn, 2) < 1) // 2 is openReadOnly
return NULL; return NULL;
} // endif op } // endif info
/************************************************************************/ /************************************************************************/
/* Do an evaluation of the result size. */ /* Do an evaluation of the result size. */
/************************************************************************/ /************************************************************************/
maxres = 512; // This is completely arbitrary if (!info) {
n = ocp->GetMaxValue(SQL_MAX_USER_NAME_LEN); maxres = 512; // This is completely arbitrary
length[0] = (n) ? (n + 1) : 128; n = ocp->GetMaxValue(SQL_MAX_USER_NAME_LEN);
n = ocp->GetMaxValue(SQL_MAX_TABLE_NAME_LEN); length[0] = (n) ? (n + 1) : 128;
length[1] = (n) ? (n + 1) : 128; n = ocp->GetMaxValue(SQL_MAX_TABLE_NAME_LEN);
length[1] = (n) ? (n + 1) : 128;
} else {
maxres = 0;
length[0] = 128;
length[1] = 128;
} // endif info
#ifdef DEBTRACE #ifdef DEBTRACE
htrc("ODBCTables: max=%d len=%d,%d\n", htrc("ODBCTables: max=%d len=%d,%d\n",
...@@ -474,8 +523,11 @@ PQRYRES ODBCTables(PGLOBAL g, ODBConn *op, char *dsn, char *tabpat, ...@@ -474,8 +523,11 @@ PQRYRES ODBCTables(PGLOBAL g, ODBConn *op, char *dsn, char *tabpat,
qrp = PlgAllocResult(g, ncol, maxres, IDS_TABLES + 1, qrp = PlgAllocResult(g, ncol, maxres, IDS_TABLES + 1,
dbtype, buftyp, length); dbtype, buftyp, length);
if (info)
return qrp;
cap = AllocCatInfo(g, CAT_TAB, tabpat, qrp); cap = AllocCatInfo(g, CAT_TAB, tabpat, qrp);
cap->Pat = (PUCHAR)tabtyp; //cap->Pat = (PUCHAR)tabtyp;
#ifdef DEBTRACE #ifdef DEBTRACE
htrc("Getting table results ncol=%d\n", cap->Qrp->Nbcol); htrc("Getting table results ncol=%d\n", cap->Qrp->Nbcol);
...@@ -497,8 +549,7 @@ PQRYRES ODBCTables(PGLOBAL g, ODBConn *op, char *dsn, char *tabpat, ...@@ -497,8 +549,7 @@ PQRYRES ODBCTables(PGLOBAL g, ODBConn *op, char *dsn, char *tabpat,
/************************************************************************/ /************************************************************************/
/* Close any local connection. */ /* Close any local connection. */
/************************************************************************/ /************************************************************************/
if (!op) ocp->Close();
ocp->Close();
/************************************************************************/ /************************************************************************/
/* Return the result pointer for use by GetData routines. */ /* Return the result pointer for use by GetData routines. */
...@@ -506,6 +557,7 @@ PQRYRES ODBCTables(PGLOBAL g, ODBConn *op, char *dsn, char *tabpat, ...@@ -506,6 +557,7 @@ PQRYRES ODBCTables(PGLOBAL g, ODBConn *op, char *dsn, char *tabpat,
return qrp; return qrp;
} // end of ODBCTables } // end of ODBCTables
#if 0 // Currently not used by CONNECT
/**************************************************************************/ /**************************************************************************/
/* PrimaryKeys: constructs the result blocks containing all the */ /* PrimaryKeys: constructs the result blocks containing all the */
/* ODBC catalog information concerning primary keys. */ /* ODBC catalog information concerning primary keys. */
...@@ -1558,6 +1610,7 @@ bool ODBConn::BindParam(ODBCCOL *colp) ...@@ -1558,6 +1610,7 @@ bool ODBConn::BindParam(ODBCCOL *colp)
/***********************************************************************/ /***********************************************************************/
bool ODBConn::GetDataSources(PQRYRES qrp) bool ODBConn::GetDataSources(PQRYRES qrp)
{ {
bool rv = false;
UCHAR *dsn, *des; UCHAR *dsn, *des;
UWORD dir = SQL_FETCH_FIRST; UWORD dir = SQL_FETCH_FIRST;
SWORD n1, n2, p1, p2; SWORD n1, n2, p1, p2;
...@@ -1589,14 +1642,65 @@ bool ODBConn::GetDataSources(PQRYRES qrp) ...@@ -1589,14 +1642,65 @@ bool ODBConn::GetDataSources(PQRYRES qrp)
} catch(DBX *x) { } catch(DBX *x) {
strcpy(m_G->Message, x->GetErrorMessage(0)); strcpy(m_G->Message, x->GetErrorMessage(0));
SQLFreeEnv(m_henv); rv = true;
return true;
} // end try/catch } // end try/catch
SQLFreeEnv(m_henv); SQLFreeEnv(m_henv);
return false; Close();
return rv;
} // end of GetDataSources } // end of GetDataSources
/***********************************************************************/
/* Get the list of Drivers and set it in qrp. */
/***********************************************************************/
bool ODBConn::GetDrivers(PQRYRES qrp)
{
int i, n;
bool rv = false;
UCHAR *des, *att;
UWORD dir = SQL_FETCH_FIRST;
SWORD n1, n2, p1, p2;
PCOLRES crp1 = qrp->Colresp, crp2 = qrp->Colresp->Next;
RETCODE rc;
n1 = crp1->Clen;
n2 = crp2->Clen;
try {
rc = SQLAllocEnv(&m_henv);
if (!Check(rc))
ThrowDBX(rc); // Fatal
for (n = 0; n < qrp->Maxres; n++) {
des = (UCHAR*)crp1->Kdata->GetValPtr(n);
att = (UCHAR*)crp2->Kdata->GetValPtr(n);
rc = SQLDrivers(m_henv, dir, des, n1, &p1, att, n2, &p2);
if (rc == SQL_NO_DATA_FOUND)
break;
else if (!Check(rc))
ThrowDBX(rc); // Fatal
// The attributes being separated by '\0', set them to ';'
for (i = 0; i < p2; i++)
if (!att[i])
att[i] = ';';
qrp->Nblin++;
dir = SQL_FETCH_NEXT;
} // endfor n
} catch(DBX *x) {
strcpy(m_G->Message, x->GetErrorMessage(0));
rv = true;
} // end try/catch
SQLFreeEnv(m_henv);
Close();
return rv;
} // end of GetDrivers
/***********************************************************************/ /***********************************************************************/
/* Allocate recset and call SQLTables, SQLColumns or SQLPrimaryKeys. */ /* Allocate recset and call SQLTables, SQLColumns or SQLPrimaryKeys. */
/***********************************************************************/ /***********************************************************************/
......
...@@ -4,6 +4,14 @@ ...@@ -4,6 +4,14 @@
//nclude <windows.h> /* Windows include file */ //nclude <windows.h> /* Windows include file */
//nclude <windowsx.h> /* Message crackers */ //nclude <windowsx.h> /* Message crackers */
/***********************************************************************/
/* Catalog function prototypes. */
/***********************************************************************/
PQRYRES ODBCDataSources(PGLOBAL g, bool info);
PQRYRES MyODBCCols(PGLOBAL g, char *dsn, char *tab, bool info);
PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *tabpat, bool info);
PQRYRES ODBCDrivers(PGLOBAL g, bool info);
/***********************************************************************/ /***********************************************************************/
/* Included C-definition files required by the interface. */ /* Included C-definition files required by the interface. */
/***********************************************************************/ /***********************************************************************/
...@@ -143,6 +151,7 @@ class ODBConn : public BLOCK { ...@@ -143,6 +151,7 @@ class ODBConn : public BLOCK {
bool BindParam(ODBCCOL *colp); bool BindParam(ODBCCOL *colp);
int GetCatInfo(CATPARM *cap); int GetCatInfo(CATPARM *cap);
bool GetDataSources(PQRYRES qrp); bool GetDataSources(PQRYRES qrp);
bool GetDrivers(PQRYRES qrp);
public: public:
// Set special options // Set special options
......
...@@ -109,6 +109,8 @@ char *GetMsgid(int id) ...@@ -109,6 +109,8 @@ char *GetMsgid(int id)
case IDS_SPC_06: p = "Longueur"; break; case IDS_SPC_06: p = "Longueur"; break;
case IDS_SPC_07: p = "Echelle"; break; case IDS_SPC_07: p = "Echelle"; break;
case IDS_SPC_08: p = "Pseudo_Colonne"; break; case IDS_SPC_08: p = "Pseudo_Colonne"; break;
case IDS_DRV_01: p = "Description"; break;
case IDS_DRV_02: p = "Attributs"; break;
case IDS_DSC_01: p = "Nom"; break; case IDS_DSC_01: p = "Nom"; break;
case IDS_DSC_02: p = "Description"; break; case IDS_DSC_02: p = "Description"; break;
#else // English #else // English
...@@ -199,6 +201,8 @@ char *GetMsgid(int id) ...@@ -199,6 +201,8 @@ char *GetMsgid(int id)
case IDS_SPC_06: p = "Length"; break; case IDS_SPC_06: p = "Length"; break;
case IDS_SPC_07: p = "Scale"; break; case IDS_SPC_07: p = "Scale"; break;
case IDS_SPC_08: p = "Pseudo_Column"; break; case IDS_SPC_08: p = "Pseudo_Column"; break;
case IDS_DRV_01: p = "Description"; break;
case IDS_DRV_02: p = "Attributes"; break;
case IDS_DSC_01: p = "Name"; break; case IDS_DSC_01: p = "Name"; break;
case IDS_DSC_02: p = "Description"; break; case IDS_DSC_02: p = "Description"; break;
#endif // English #endif // English
......
...@@ -118,6 +118,9 @@ ...@@ -118,6 +118,9 @@
#define IDS_PLG_07 1286 #define IDS_PLG_07 1286
#define IDS_PLG_08 1287 #define IDS_PLG_08 1287
#define IDS_PLG_09 1288 #define IDS_PLG_09 1288
#define IDS_DRIVER 1290
#define IDS_DRV_01 1291
#define IDS_DRV_02 1292
#define IDS_DSRC 1295 #define IDS_DSRC 1295
#define IDS_DSC_01 1296 #define IDS_DSC_01 1296
#define IDS_DSC_02 1297 #define IDS_DSC_02 1297
......
...@@ -11,6 +11,11 @@ ...@@ -11,6 +11,11 @@
//pedef struct _tabdesc *PTABD; // For friend setting //pedef struct _tabdesc *PTABD; // For friend setting
typedef class TDBFMT *PTDBFMT; typedef class TDBFMT *PTDBFMT;
/***********************************************************************/
/* Functions used externally. */
/***********************************************************************/
PQRYRES CSVColumns(PGLOBAL g, char *fn, char sep, char q, int hdr, int mxr);
/***********************************************************************/ /***********************************************************************/
/* CSV table. */ /* CSV table. */
/***********************************************************************/ /***********************************************************************/
......
...@@ -57,8 +57,6 @@ ...@@ -57,8 +57,6 @@
#include "reldef.h" #include "reldef.h"
#include "tabmysql.h" #include "tabmysql.h"
#include "valblk.h" #include "valblk.h"
#include "plgcnx.h" // For DB types
#include "resource.h"
#if defined(_CONSOLE) #if defined(_CONSOLE)
void PrintResult(PGLOBAL, PSEM, PQRYRES); void PrintResult(PGLOBAL, PSEM, PQRYRES);
...@@ -66,250 +64,6 @@ void PrintResult(PGLOBAL, PSEM, PQRYRES); ...@@ -66,250 +64,6 @@ void PrintResult(PGLOBAL, PSEM, PQRYRES);
extern "C" int trace; extern "C" int trace;
/**************************************************************************/
/* Allocate the result structure that will contain result data. */
/**************************************************************************/
PQRYRES PlgAllocResult(PGLOBAL g, int ncol, int maxres, int ids,
int *dbtype, int *buftyp, unsigned int *length,
bool blank = true, bool nonull = true);
/************************************************************************/
/* MyColumns: constructs the result blocks containing all columns */
/* of a MySQL table that will be retrieved by GetData commands. */
/* key = TRUE when called from Create Table to get key informations. */
/************************************************************************/
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)
{
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};
char *fld, *fmt, cmd[128];
int i, n, nf, ncol = sizeof(dbtype) / sizeof(int);
int len, type, prec, rc, k = 0;
PQRYRES qrp;
PCOLRES crp;
MYSQLC myc;
/**********************************************************************/
/* 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);
if (colpat)
strcat(strcat(cmd, " LIKE "), colpat);
if (trace)
htrc("MyColumns: cmd='%s'\n", cmd);
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);
if (!key) // We are not called from Create table
ncol--; // No date format column
/**********************************************************************/
/* Allocate the structures used to refer to the result set. */
/**********************************************************************/
qrp = PlgAllocResult(g, ncol, n, IDS_COLUMNS + 3,
dbtype, buftyp, length);
/**********************************************************************/
/* Now get the results into blocks. */
/**********************************************************************/
for (i = 0; i < n; i++) {
if ((rc = myc.Fetch(g, -1) == RC_FX))
return NULL;
else if (rc == RC_NF)
break;
// Get column name
fld = myc.GetCharField(0);
crp = qrp->Colresp;
crp->Kdata->SetValue(fld, i);
// Get type, type name, and precision
fld = myc.GetCharField(1);
prec = 0;
len = 256; // Default for text or blob
if ((nf = sscanf(fld, "%[^(](%d,%d", cmd, &len, &prec)) < 1) {
sprintf(g->Message, MSG(BAD_FIELD_TYPE), fld);
return NULL;
} else
qrp->Nblin++;
if ((type = MYSQLtoPLG(cmd)) == TYPE_ERROR) {
sprintf(g->Message, "Unsupported column type %s", cmd);
return NULL;
} // endif type
crp = crp->Next;
crp->Kdata->SetValue(type, i);
crp = crp->Next;
crp->Kdata->SetValue(cmd, i);
if (key && 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->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;
crp->Name = "Prec";
crp->Kdata->SetValue(prec, i);
// Get comment field
crp = crp->Next;
crp->Name = "Comment";
fld = myc.GetCharField(8);
if (fld && strlen(fld))
crp->Kdata->SetValue(fld, i);
else
crp->Kdata->Reset(i);
if (key) {
crp = crp->Next;
crp->Name = "Date_Fmt";
if (fmt)
crp->Kdata->SetValue(fmt, i);
else
crp->Kdata->Reset(i);
} // endif key
} // endfor i
if (k > 1) {
// Multicolumn primary key
PVBLK vbp = qrp->Colresp->Next->Next->Next->Next->Kdata;
for (i = 0; i < n; i++)
if (vbp->GetIntValue(i))
vbp->SetValue(k, i);
} // endif k
/**********************************************************************/
/* Close MySQL connection. */
/**********************************************************************/
myc.Close();
/**********************************************************************/
/* Return the result pointer for use by GetData routines. */
/**********************************************************************/
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
/* -------------- Implementation of the MYSQLDEF class --------------- */ /* -------------- Implementation of the MYSQLDEF class --------------- */
/***********************************************************************/ /***********************************************************************/
...@@ -1038,12 +792,12 @@ void MYSQLCOL::InitBind(PGLOBAL g) ...@@ -1038,12 +792,12 @@ void MYSQLCOL::InitBind(PGLOBAL g)
// if (!((DTVAL*)Value)->IsFormatted()) // if (!((DTVAL*)Value)->IsFormatted())
((DTVAL*)Value)->SetFormat(g, "YYYY-MM-DD hh:mm:ss", 19); ((DTVAL*)Value)->SetFormat(g, "YYYY-MM-DD hh:mm:ss", 19);
Bind->buffer_type = PLGtoMYSQL(TYPE_STRING); Bind->buffer_type = PLGtoMYSQL(TYPE_STRING, false);
Bind->buffer = (char *)PlugSubAlloc(g,NULL, 20); Bind->buffer = (char *)PlugSubAlloc(g,NULL, 20);
Bind->buffer_length = 20; Bind->buffer_length = 20;
Bind->length = &Slen; Bind->length = &Slen;
} else { } else {
Bind->buffer_type = PLGtoMYSQL(Buf_Type); Bind->buffer_type = PLGtoMYSQL(Buf_Type, false);
Bind->buffer = (char *)Value->GetTo_Val(); Bind->buffer = (char *)Value->GetTo_Val();
Bind->buffer_length = Value->GetClen(); Bind->buffer_length = Value->GetClen();
Bind->length = (IsTypeChar(Buf_Type)) ? &Slen : NULL; Bind->length = (IsTypeChar(Buf_Type)) ? &Slen : NULL;
......
...@@ -74,8 +74,6 @@ ...@@ -74,8 +74,6 @@
#include "sql_string.h" #include "sql_string.h"
extern "C" char *GetMsgid(int id); extern "C" char *GetMsgid(int id);
PQRYRES ODBCDataSources(PGLOBAL g, bool info = false);
PQRYRES MyODBCCols(PGLOBAL g, char *tab, char *dsn, bool info);
/***********************************************************************/ /***********************************************************************/
/* DB static variables. */ /* DB static variables. */
...@@ -90,7 +88,8 @@ extern int num_read, num_there, num_eq[2]; // Statistics ...@@ -90,7 +88,8 @@ extern int num_read, num_there, num_eq[2]; // Statistics
/***********************************************************************/ /***********************************************************************/
ODBCDEF::ODBCDEF(void) ODBCDEF::ODBCDEF(void)
{ {
Connect = Tabname = Tabowner = Tabqual = Qchar = Info = NULL; Connect = Tabname = Tabowner = Tabqual = Qchar = NULL;
Catfunc = 0;
Catver = Options = 0; Catver = Options = 0;
} // end of ODBCDEF constructor } // end of ODBCDEF constructor
...@@ -99,20 +98,18 @@ ODBCDEF::ODBCDEF(void) ...@@ -99,20 +98,18 @@ ODBCDEF::ODBCDEF(void)
/***********************************************************************/ /***********************************************************************/
bool ODBCDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) bool ODBCDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
{ {
//void *memp = Cat->GetDescp();
//PSZ dbfile = Cat->GetDescFile();
int dop = ODBConn::noOdbcDialog; // Default for options int dop = ODBConn::noOdbcDialog; // Default for options
Desc = Connect = Cat->GetStringCatInfo(g, Name, "Connect", ""); Desc = Connect = Cat->GetStringCatInfo(g, Name, "Connect", "");
Tabname = Cat->GetStringCatInfo(g, Name, "Name", Name); // Deprecated Catfunc = toupper(*Cat->GetStringCatInfo(g, Name, "Catfunc", ""));
Tabname = Cat->GetStringCatInfo(g, Name, "Name",
Catfunc == 'T' ? NULL : Name);
Tabname = Cat->GetStringCatInfo(g, Name, "Tabname", Tabname); Tabname = Cat->GetStringCatInfo(g, Name, "Tabname", Tabname);
Tabowner = Cat->GetStringCatInfo(g, Name, "Owner", ""); Tabowner = Cat->GetStringCatInfo(g, Name, "Owner", "");
Tabqual = Cat->GetStringCatInfo(g, Name, "Qualifier", ""); Tabqual = Cat->GetStringCatInfo(g, Name, "Qualifier", "");
Qchar = Cat->GetStringCatInfo(g, Name, "Qchar", ""); Qchar = Cat->GetStringCatInfo(g, Name, "Qchar", "");
Info = Cat->GetStringCatInfo(g, Name, "Info", NULL);
Catver = Cat->GetIntCatInfo(Name, "Catver", 2); Catver = Cat->GetIntCatInfo(Name, "Catver", 2);
Options = Cat->GetIntCatInfo(Name, "Options", dop); Options = Cat->GetIntCatInfo(Name, "Options", dop);
//Options = Cat->GetIntCatInfo(Name, "Options", 0);
Pseudo = 2; // FILID is Ok but not ROWID Pseudo = 2; // FILID is Ok but not ROWID
return false; return false;
} // end of DefineAM } // end of DefineAM
...@@ -128,18 +125,27 @@ PTDB ODBCDEF::GetTable(PGLOBAL g, MODE m) ...@@ -128,18 +125,27 @@ PTDB ODBCDEF::GetTable(PGLOBAL g, MODE m)
/* Allocate a TDB of the proper type. */ /* Allocate a TDB of the proper type. */
/* Column blocks will be allocated only when needed. */ /* Column blocks will be allocated only when needed. */
/*********************************************************************/ /*********************************************************************/
if (!Info || !strchr("1yYoO", *Info)) { switch (Catfunc) {
tdbp = new(g) TDBODBC(this); case 'C':
tdbp = new(g) TDBOCL(this);
if (Multiple == 1) break;
tdbp = new(g) TDBMUL(tdbp); case 'T':
else if (Multiple == 2) tdbp = new(g) TDBOTB(this);
strcpy(g->Message, MSG(NO_ODBC_MUL)); break;
case 'S':
} else if (*Connect) tdbp = new(g) TDBSRC(this);
tdbp = new(g) TDBOCL(this); break;
else case 'D':
tdbp = new(g) TDBSRC(this); tdbp = new(g) TDBDRV(this);
break;
default:
tdbp = new(g) TDBODBC(this);
if (Multiple == 1)
tdbp = new(g) TDBMUL(tdbp);
else if (Multiple == 2)
strcpy(g->Message, MSG(NO_ODBC_MUL));
} // endswitch Catfunc
return tdbp; return tdbp;
} // end of GetTable } // end of GetTable
...@@ -1074,7 +1080,24 @@ bool TDBSRC::Initialize(PGLOBAL g) ...@@ -1074,7 +1080,24 @@ bool TDBSRC::Initialize(PGLOBAL g)
if (Init) if (Init)
return false; return false;
if (!(Qrp = ODBCDataSources(g))) if (!(Qrp = ODBCDataSources(g, false)))
return true;
Init = true;
return false;
} // end of Initialize
/* ---------------------------TDBDRV class --------------------------- */
/***********************************************************************/
/* Initialize: Get the list of ODBC drivers. */
/***********************************************************************/
bool TDBDRV::Initialize(PGLOBAL g)
{
if (Init)
return false;
if (!(Qrp = ODBCDrivers(g, false)))
return true; return true;
Init = true; Init = true;
...@@ -1102,7 +1125,35 @@ bool TDBOCL::Initialize(PGLOBAL g) ...@@ -1102,7 +1125,35 @@ bool TDBOCL::Initialize(PGLOBAL g)
if (Init) if (Init)
return false; return false;
if (!(Qrp = MyODBCCols(g, Tabn, Dsn, false))) 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
/***********************************************************************/
/* Initialize: Get the list of ODBC tables. */
/***********************************************************************/
bool TDBOTB::Initialize(PGLOBAL g)
{
if (Init)
return false;
if (!(Qrp = ODBCTables(g, Dsn, Tabpat, false)))
return true; return true;
Init = true; Init = true;
......
...@@ -44,7 +44,7 @@ class DllExport ODBCDEF : public TABDEF { /* Logical table description */ ...@@ -44,7 +44,7 @@ class DllExport ODBCDEF : public TABDEF { /* Logical table description */
PSZ Tabowner; /* External table owner */ PSZ Tabowner; /* External table owner */
PSZ Tabqual; /* External table qualifier */ PSZ Tabqual; /* External table qualifier */
PSZ Qchar; /* Identifier quoting character */ PSZ Qchar; /* Identifier quoting character */
PSZ Info; /* Information value */ char Catfunc; /* Catalog function */
int Catver; /* ODBC version for catalog functions */ int Catver; /* ODBC version for catalog functions */
int Options; /* Open connection options */ int Options; /* Open connection options */
}; // end of ODBCDEF }; // end of ODBCDEF
...@@ -118,7 +118,7 @@ class TDBODBC : public TDBASE { ...@@ -118,7 +118,7 @@ class TDBODBC : public TDBASE {
int CurNum; // Current buffer line number int CurNum; // Current buffer line number
int Rbuf; // Number of lines read in buffer int Rbuf; // Number of lines read in buffer
int BufSize; // Size of connect string buffer int BufSize; // Size of connect string buffer
int Nparm; // The number of statement parameters int Nparm; // The number of statement parameters
}; // end of class TDBODBC }; // end of class TDBODBC
/***********************************************************************/ /***********************************************************************/
...@@ -227,7 +227,7 @@ class OIFCOL : public COLBLK { ...@@ -227,7 +227,7 @@ class OIFCOL : public COLBLK {
}; // end of class OIFCOL }; // end of class OIFCOL
/***********************************************************************/ /***********************************************************************/
/* This is the class declaration for the Data Sources info table. */ /* This is the class declaration for the Data Sources catalog table. */
/***********************************************************************/ /***********************************************************************/
class TDBSRC : public TDBOIF { class TDBSRC : public TDBOIF {
public: public:
...@@ -241,7 +241,21 @@ class TDBSRC : public TDBOIF { ...@@ -241,7 +241,21 @@ class TDBSRC : public TDBOIF {
}; // end of class TDBSRC }; // end of class TDBSRC
/***********************************************************************/ /***********************************************************************/
/* This is the class declaration for the columns info table. */ /* This is the class declaration for the Drivers catalog table. */
/***********************************************************************/
class TDBDRV : public TDBOIF {
public:
// Constructor
TDBDRV(PODEF tdp) : TDBOIF(tdp) {ID = IDS_DRIVER; NC = 2;}
protected:
// Specific routines
virtual bool Initialize(PGLOBAL g);
}; // end of class TDBDRV
/***********************************************************************/
/* This is the class declaration for the columns catalog table. */
/***********************************************************************/ /***********************************************************************/
class TDBOCL : public TDBOIF { class TDBOCL : public TDBOIF {
public: public:
...@@ -256,4 +270,21 @@ class TDBOCL : public TDBOIF { ...@@ -256,4 +270,21 @@ class TDBOCL : public TDBOIF {
char *Dsn; // Points to connection string char *Dsn; // Points to connection string
char *Tabn; // Points to ODBC table name char *Tabn; // Points to ODBC table name
}; // end of class TDBOCL }; // end of class TDBOCL
/***********************************************************************/
/* This is the class declaration for the tables catalog table. */
/***********************************************************************/
class TDBOTB : public TDBOIF {
public:
// Constructor
TDBOTB(PODEF tdp);
protected:
// Specific routines
virtual bool Initialize(PGLOBAL g);
// Members
char *Dsn; // Points to connection string
char *Tabpat; // Points to ODBC table pattern
}; // end of class TDBOTB
#endif // !NODBC #endif // !NODBC
...@@ -32,14 +32,6 @@ PQRYRES PlgAllocResult(PGLOBAL g, int ncol, int maxres, int ids, ...@@ -32,14 +32,6 @@ PQRYRES PlgAllocResult(PGLOBAL g, int ncol, int maxres, int ids,
/* ------------------- Functions WMI Column info --------------------- */ /* ------------------- Functions WMI Column info --------------------- */
/***********************************************************************/
/* Structure used by WMI column info functions. */
/***********************************************************************/
typedef struct _WMIutil {
IWbemServices *Svc;
IWbemClassObject *Cobj;
} WMIUTIL, *PWMIUT;
/***********************************************************************/ /***********************************************************************/
/* Initialize WMI operations. */ /* Initialize WMI operations. */
/***********************************************************************/ /***********************************************************************/
......
...@@ -16,6 +16,19 @@ typedef class WMICOL *PWMICOL; ...@@ -16,6 +16,19 @@ typedef class WMICOL *PWMICOL;
typedef class TDBWCL *PTDBWCL; typedef class TDBWCL *PTDBWCL;
typedef class WCLCOL *PWCLCOL; typedef class WCLCOL *PWCLCOL;
/***********************************************************************/
/* Structure used by WMI column info functions. */
/***********************************************************************/
typedef struct _WMIutil {
IWbemServices *Svc;
IWbemClassObject *Cobj;
} WMIUTIL, *PWMIUT;
/***********************************************************************/
/* Functions used externally. */
/***********************************************************************/
PQRYRES WMIColumns(PGLOBAL g, char *nsp, char *classname, PWMIUT wp);
/* -------------------------- WMI classes ---------------------------- */ /* -------------------------- WMI classes ---------------------------- */
/***********************************************************************/ /***********************************************************************/
......
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