diff options
author | Olivier Bertrand <bertrandop@gmail.com> | 2013-02-11 00:31:03 +0100 |
---|---|---|
committer | Olivier Bertrand <bertrandop@gmail.com> | 2013-02-11 00:31:03 +0100 |
commit | f6ca3b05f230498ede5f4d2467719d529abbb14a (patch) | |
tree | 837b0f2bc017208312a51b1b546bc693c09d5e7c | |
parent | b93db097a3bca6273e2906de4cafe2a1a60ededf (diff) | |
download | mariadb-git-f6ca3b05f230498ede5f4d2467719d529abbb14a.tar.gz |
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
-rw-r--r-- | storage/connect/filamdbf.cpp | 74 | ||||
-rw-r--r-- | storage/connect/ha_connect.cc | 165 | ||||
-rw-r--r-- | storage/connect/mycat.cc | 79 | ||||
-rw-r--r-- | storage/connect/myconn.cpp | 225 | ||||
-rw-r--r-- | storage/connect/myconn.h | 2 | ||||
-rw-r--r-- | storage/connect/odbconn.cpp | 54 | ||||
-rw-r--r-- | storage/connect/plgdbsem.h | 28 | ||||
-rw-r--r-- | storage/connect/plgdbutl.cpp | 85 | ||||
-rw-r--r-- | storage/connect/reldef.cpp | 2 | ||||
-rw-r--r-- | storage/connect/reldef.h | 1 | ||||
-rw-r--r-- | storage/connect/tabdos.cpp | 14 | ||||
-rw-r--r-- | storage/connect/tabdos.h | 1 | ||||
-rw-r--r-- | storage/connect/tabfix.h | 19 | ||||
-rw-r--r-- | storage/connect/tabfmt.cpp | 141 | ||||
-rw-r--r-- | storage/connect/tabfmt.h | 37 | ||||
-rw-r--r-- | storage/connect/table.cpp | 181 | ||||
-rw-r--r-- | storage/connect/tabmysql.cpp | 31 | ||||
-rw-r--r-- | storage/connect/tabmysql.h | 29 | ||||
-rw-r--r-- | storage/connect/tabodbc.cpp | 252 | ||||
-rw-r--r-- | storage/connect/tabodbc.h | 101 | ||||
-rw-r--r-- | storage/connect/tabwmi.cpp | 452 | ||||
-rw-r--r-- | storage/connect/tabwmi.h | 79 | ||||
-rw-r--r-- | storage/connect/xtable.h | 71 |
23 files changed, 937 insertions, 1186 deletions
diff --git a/storage/connect/filamdbf.cpp b/storage/connect/filamdbf.cpp index e8aace3fc06..29cfb70c116 100644 --- a/storage/connect/filamdbf.cpp +++ b/storage/connect/filamdbf.cpp @@ -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. */ diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index f8dff85dd71..4d1ee88c8a1 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -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; diff --git a/storage/connect/mycat.cc b/storage/connect/mycat.cc index 4865711e3a4..bbf38fa0374 100644 --- a/storage/connect/mycat.cc +++ b/storage/connect/mycat.cc @@ -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; diff --git a/storage/connect/myconn.cpp b/storage/connect/myconn.cpp index d8e7a4425de..b4347f11094 100644 --- a/storage/connect/myconn.cpp +++ b/storage/connect/myconn.cpp @@ -1,11 +1,11 @@ /************** 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 --------------------------- */ /***********************************************************************/ diff --git a/storage/connect/myconn.h b/storage/connect/myconn.h index fc462aaa22a..1aab55f1e01 100644 --- a/storage/connect/myconn.h +++ b/storage/connect/myconn.h @@ -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 --------------------------- */ diff --git a/storage/connect/odbconn.cpp b/storage/connect/odbconn.cpp index d9e3e3f4d58..0519a8141e6 100644 --- a/storage/connect/odbconn.cpp +++ b/storage/connect/odbconn.cpp @@ -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); diff --git a/storage/connect/plgdbsem.h b/storage/connect/plgdbsem.h index 0a412972ce1..7a8e13fa4c5 100644 --- a/storage/connect/plgdbsem.h +++ b/storage/connect/plgdbsem.h @@ -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 */ @@ -441,6 +442,25 @@ typedef struct _tabs { } TABS; /***********************************************************************/ +/* Following definitions are used to define table fields (columns). */ +/***********************************************************************/ +enum XFLD {FLD_NO = 0, /* Not a field definition item */ + FLD_NAME = 1, /* Field name */ + FLD_TYPE = 2, /* Field type */ + FLD_TYPENAME = 3, /* Field type name */ + FLD_PREC = 4, /* Field precision (length?) */ + FLD_LENGTH = 5, /* Field length (?) */ + FLD_SCALE = 6, /* Field scale (precision) */ + FLD_RADIX = 7, /* Field radix */ + FLD_NULL = 8, /* Field nullable property */ + FLD_REM = 9, /* Field comment (remark) */ + FLD_CHARSET = 10, /* Field collation */ + FLD_KEY = 11, /* Field key property */ + FLD_DEFAULT = 12, /* Field default value */ + FLD_PRIV = 13, /* Field priviledges */ + FLD_DATEFMT = 14}; /* Field date format */ + +/***********************************************************************/ /* Result of last SQL noconv query. */ /***********************************************************************/ typedef struct _qryres { @@ -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. */ /***********************************************************************/ diff --git a/storage/connect/plgdbutl.cpp b/storage/connect/plgdbutl.cpp index e980926c820..2e0564e8735 100644 --- a/storage/connect/plgdbutl.cpp +++ b/storage/connect/plgdbutl.cpp @@ -1,11 +1,11 @@ /********** 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. */ /***********************************************************************/ diff --git a/storage/connect/reldef.cpp b/storage/connect/reldef.cpp index bf129a2f54a..4f99b2da6d6 100644 --- a/storage/connect/reldef.cpp +++ b/storage/connect/reldef.cpp @@ -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); diff --git a/storage/connect/reldef.h b/storage/connect/reldef.h index ac006f5c7e9..8f14d28599f 100644 --- a/storage/connect/reldef.h +++ b/storage/connect/reldef.h @@ -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 ??? */ diff --git a/storage/connect/tabdos.cpp b/storage/connect/tabdos.cpp index 5218a322ea6..930048346b9 100644 --- a/storage/connect/tabdos.cpp +++ b/storage/connect/tabdos.cpp @@ -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); diff --git a/storage/connect/tabdos.h b/storage/connect/tabdos.h index a1c5b0660cd..2f1f0a5ecf9 100644 --- a/storage/connect/tabdos.h +++ b/storage/connect/tabdos.h @@ -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;} diff --git a/storage/connect/tabfix.h b/storage/connect/tabfix.h index 0a4f9fc4872..bcd171b37bb 100644 --- a/storage/connect/tabfix.h +++ b/storage/connect/tabfix.h @@ -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__ diff --git a/storage/connect/tabfmt.cpp b/storage/connect/tabfmt.cpp index 9b4589a71a7..6834ca5ea28 100644 --- a/storage/connect/tabfmt.cpp +++ b/storage/connect/tabfmt.cpp @@ -1,7 +1,7 @@ /************* TabFmt C++ Program Source Code File (.CPP) **************/ /* PROGRAM NAME: TABFMT */ /* ------------- */ -/* Version 3.7 */ +/* Version 3.8 */ /* */ /* COPYRIGHT: */ /* ---------- */ @@ -68,24 +68,21 @@ 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.*/ /* Note: the algorithm to set the type is based on the internal values */ /* 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 ---------------------------- */ diff --git a/storage/connect/tabfmt.h b/storage/connect/tabfmt.h index 95486a09881..05b9d6445c6 100644 --- a/storage/connect/tabfmt.h +++ b/storage/connect/tabfmt.h @@ -1,7 +1,7 @@ /*************** 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 ------------------------- */ diff --git a/storage/connect/table.cpp b/storage/connect/table.cpp index 77c2fd4df3b..0c8e86c0457 100644 --- a/storage/connect/table.cpp +++ b/storage/connect/table.cpp @@ -1,7 +1,7 @@ /************** 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 + diff --git a/storage/connect/tabmysql.cpp b/storage/connect/tabmysql.cpp index a63526f1e8d..27489f4635e 100644 --- a/storage/connect/tabmysql.cpp +++ b/storage/connect/tabmysql.cpp @@ -1,7 +1,7 @@ /************* 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 diff --git a/storage/connect/tabmysql.h b/storage/connect/tabmysql.h index 68fb9d89f24..abfdeeb13a3 100644 --- a/storage/connect/tabmysql.h +++ b/storage/connect/tabmysql.h @@ -1,4 +1,4 @@ -// 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 diff --git a/storage/connect/tabodbc.cpp b/storage/connect/tabodbc.cpp index 7b8c62e3e53..55475852a62 100644 --- a/storage/connect/tabodbc.cpp +++ b/storage/connect/tabodbc.cpp @@ -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 --------------------------- */ diff --git a/storage/connect/tabodbc.h b/storage/connect/tabodbc.h index f31c005e3d8..645426eef78 100644 --- a/storage/connect/tabodbc.h +++ b/storage/connect/tabodbc.h @@ -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 @@ -164,127 +163,63 @@ class ODBCCOL : public COLBLK { }; // 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 diff --git a/storage/connect/tabwmi.cpp b/storage/connect/tabwmi.cpp index e98dfd0cde0..e6a02e1871f 100644 --- a/storage/connect/tabwmi.cpp +++ b/storage/connect/tabwmi.cpp @@ -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 diff --git a/storage/connect/tabwmi.h b/storage/connect/tabwmi.h index 853f2174434..9df57e7c579 100644 --- a/storage/connect/tabwmi.h +++ b/storage/connect/tabwmi.h @@ -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 diff --git a/storage/connect/xtable.h b/storage/connect/xtable.h index 73af45c7e0a..6932fe7337a 100644 --- a/storage/connect/xtable.h +++ b/storage/connect/xtable.h @@ -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 |