summaryrefslogtreecommitdiff
path: root/storage
diff options
context:
space:
mode:
authorOlivier Bertrand <bertrandop@gmail.com>2013-02-05 01:56:22 +0100
committerOlivier Bertrand <bertrandop@gmail.com>2013-02-05 01:56:22 +0100
commit1830e732fb6a47bad7c4a6c97d3bcf964e70aae7 (patch)
tree81b778893081f11629c6a27fa20d0abc7da1e0f3 /storage
parent9d8d62eeffd3b03a70f536490b46a38cc4522672 (diff)
downloadmariadb-git-1830e732fb6a47bad7c4a6c97d3bcf964e70aae7.tar.gz
Make possible to get ODBC DataSources name and description by:
create table datasrc ( `anyname` varchar(256) flag=1, `anyother name` varchar(256) flag=2) engine=CONNECT table_type=ODBC option_list='info=yes'; or simply by: create table datasrc engine=CONNECT table_type=ODBC option_list='info=yes'; then: select * from datasrc; Modified: ha_connect.cc odbconn.h odbconn.cpp tabodbc.h tabodbc.cpp
Diffstat (limited to 'storage')
-rw-r--r--storage/connect/ha_connect.cc31
-rw-r--r--storage/connect/odbconn.cpp89
-rw-r--r--storage/connect/odbconn.h1
-rw-r--r--storage/connect/tabodbc.cpp211
-rw-r--r--storage/connect/tabodbc.h71
5 files changed, 380 insertions, 23 deletions
diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc
index f09aa911631..dbfa83a4ce7 100644
--- a/storage/connect/ha_connect.cc
+++ b/storage/connect/ha_connect.cc
@@ -3272,20 +3272,21 @@ 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, *typn= "DOS";
- char *fn, *dsn, *tab, *db, *host, *user, *pwd, *prt, *sep;
+ char *fn, *dsn, *tab, *db, *host, *user, *pwd, *prt, *sep, *inf;
#if defined(WIN32)
char *nsp= NULL, *cls= NULL;
#endif // WIN32
int port= MYSQL_PORT, hdr= 0, mxr= 0;
- bool ok= false;
+ bool b= false, ok= false, info= false;
LEX *lex= thd->lex;
+ LEX_STRING *comment, *name;
HA_CREATE_INFO *create_info= (HA_CREATE_INFO *)crt_info;
engine_option_value *pov;
PQRYRES qrp;
PCOLRES crp;
PGLOBAL g= GetPlug(thd);
- fn= dsn= tab= db= host= user= pwd= prt= sep= NULL;
+ fn= dsn= tab= db= host= user= pwd= prt= sep= inf= NULL;
if (g) {
// Set default values
@@ -3327,15 +3328,18 @@ bool ha_connect::pre_create(THD *thd, void *crt_info, void *alt_info)
cls= GetListOption("class", pov->value.str);
#endif // WIN32
mxr= atoi(GetListOption("maxerr", pov->value.str, "0"));
+ inf= GetListOption("info", pov->value.str);
} // endelse option_list
switch (ttp) {
#if defined(ODBC_SUPPORT)
case 'O': // ODBC
- if (!(dsn= create_info->connect_string.str))
+ info= !!strchr("1yYoO", *inf);
+
+ if (!(dsn= create_info->connect_string.str) && !info)
sprintf(g->Message, "Missing %s connection string", typn);
else
- ok= true;
+ ok= !info;
break;
#endif // ODBC_SUPPORT
@@ -3367,8 +3371,6 @@ bool ha_connect::pre_create(THD *thd, void *crt_info, void *alt_info)
if (ok) {
char *length, *decimals, *cnm, *rem;
int i, len, dec;
- bool b;
- LEX_STRING *comment, *name;
enum_field_types type;
PDBUSER dup= PlgGetUser(g);
PCATLG cat= (dup) ? dup->Catalog : NULL;
@@ -3407,7 +3409,7 @@ bool ha_connect::pre_create(THD *thd, void *crt_info, void *alt_info)
return true;
} // endif qrp
- for (i= 0; i < qrp->Nblin; i++) {
+ 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);
@@ -3440,8 +3442,17 @@ bool ha_connect::pre_create(THD *thd, void *crt_info, void *alt_info)
0, comment, NULL, NULL, NULL);
} // endfor i
- return false;
- } // endif ttp
+ return b;
+ } else if (info) { // ODBC Data Sources
+ comment= thd->make_lex_string(NULL, "", 0, true);
+ name= thd->make_lex_string(NULL, "Name", 4, true);
+ b= add_fields(thd, alt_info, name, MYSQL_TYPE_VARCHAR, "256", 0,
+ 0, comment, NULL, NULL, NULL);
+ name= thd->make_lex_string(NULL, "Description", 11, true);
+ b= add_fields(thd, alt_info, name, MYSQL_TYPE_VARCHAR, "256", 0,
+ 0, comment, NULL, NULL, NULL);
+ return b;
+ } // endif info
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0, g->Message);
return true;
diff --git a/storage/connect/odbconn.cpp b/storage/connect/odbconn.cpp
index 6810321f439..33d181fcfaf 100644
--- a/storage/connect/odbconn.cpp
+++ b/storage/connect/odbconn.cpp
@@ -189,7 +189,6 @@ CATPARM *AllocCatInfo(PGLOBAL g, CATINFO fid, char *tab, PQRYRES qrp)
#if defined(_DEBUG)
assert(qrp);
#endif
-
m = (size_t)qrp->Maxres;
n = (size_t)qrp->Nbcol;
cap = (CATPARM *)PlugSubAlloc(g, NULL, sizeof(CATPARM));
@@ -376,6 +375,50 @@ PQRYRES MyODBCCols(PGLOBAL g, char *tab, char *dsn)
return qrp;
} // end of MyODBCCols
+/*************************************************************************/
+/* ODBCDataSources: constructs the result blocks containing all ODBC */
+/* data sources available on the local host. */
+/*************************************************************************/
+PQRYRES ODBCDataSources(PGLOBAL g)
+ {
+ static int dbtype[] = {DB_CHAR, DB_CHAR};
+ static int buftyp[] = {TYPE_STRING, TYPE_STRING};
+ static unsigned int length[] = {0, 256};
+ int n, ncol = 2;
+ int maxres;
+ PQRYRES qrp;
+ ODBConn *ocp = new(g) ODBConn(g, NULL);
+
+ /************************************************************************/
+ /* Do an evaluation of the result size. */
+ /************************************************************************/
+ maxres = 512; // This is completely arbitrary
+ n = ocp->GetMaxValue(SQL_MAX_DSN_LENGTH);
+ length[0] = (n) ? (n + 1) : 256;
+
+#ifdef DEBTRACE
+ htrc("ODBCDataSources: max=%d len=%d\n", maxres, length[0]);
+#endif
+
+ /************************************************************************/
+ /* Allocate the structures used to refer to the result set. */
+ /************************************************************************/
+ qrp = PlgAllocResult(g, ncol, maxres, 0, dbtype, buftyp, length);
+ qrp->Colresp->Name = "Name";
+ qrp->Colresp->Next->Name = "Description";
+
+ /************************************************************************/
+ /* Now get the results into blocks. */
+ /************************************************************************/
+ if (ocp->GetDataSources(qrp))
+ qrp = NULL;
+
+ /************************************************************************/
+ /* Return the result pointer for use by GetData routines. */
+ /************************************************************************/
+ return qrp;
+ } // end of ODBCDataSources
+
#if 0 // Currently not used by CONNECT
/***********************************************************************/
/* ODBCTables: constructs the result blocks containing all tables in */
@@ -1506,6 +1549,50 @@ bool ODBConn::BindParam(ODBCCOL *colp)
} // end of BindParam
/***********************************************************************/
+/* Get the list of Data Sources and set it in qrp. */
+/***********************************************************************/
+bool ODBConn::GetDataSources(PQRYRES qrp)
+ {
+ UCHAR *dsn, *des;
+ UWORD dir = SQL_FETCH_FIRST;
+ SWORD n1, n2, p1, p2;
+ PCOLRES crp1 = qrp->Colresp, crp2 = qrp->Colresp->Next;
+ RETCODE rc;
+
+ n1 = crp1->Clen;
+ n2 = crp2->Clen;
+
+ try {
+ rc = SQLAllocEnv(&m_henv);
+
+ if (!Check(rc))
+ ThrowDBX(rc); // Fatal
+
+ for (int i = 0; i < qrp->Maxres; i++) {
+ dsn = (UCHAR*)crp1->Kdata->GetValPtr(i);
+ des = (UCHAR*)crp2->Kdata->GetValPtr(i);
+ rc = SQLDataSources(m_henv, dir, dsn, n1, &p1, des, n2, &p2);
+
+ if (rc == SQL_NO_DATA_FOUND)
+ break;
+ else if (!Check(rc))
+ ThrowDBX(rc); // Fatal
+
+ qrp->Nblin++;
+ dir = SQL_FETCH_NEXT;
+ } // endfor i
+
+ } catch(DBX *x) {
+ strcpy(m_G->Message, x->GetErrorMessage(0));
+ SQLFreeEnv(m_henv);
+ return true;
+ } // end try/catch
+
+ SQLFreeEnv(m_henv);
+ return false;
+ } // end of GetDataSources
+
+/***********************************************************************/
/* Allocate recset and call SQLTables, SQLColumns or SQLPrimaryKeys. */
/***********************************************************************/
int ODBConn::GetCatInfo(CATPARM *cap)
diff --git a/storage/connect/odbconn.h b/storage/connect/odbconn.h
index 24f5898743e..7f1567eaa70 100644
--- a/storage/connect/odbconn.h
+++ b/storage/connect/odbconn.h
@@ -143,6 +143,7 @@ class ODBConn : public BLOCK {
bool ExecuteSQL(void);
bool BindParam(ODBCCOL *colp);
int GetCatInfo(CATPARM *cap);
+ bool GetDataSources(PQRYRES qrp);
public:
// Set special options
diff --git a/storage/connect/tabodbc.cpp b/storage/connect/tabodbc.cpp
index d27b0f5a3ba..c58091a32fb 100644
--- a/storage/connect/tabodbc.cpp
+++ b/storage/connect/tabodbc.cpp
@@ -1,11 +1,11 @@
/************* Tabodbc C++ Program Source Code File (.CPP) *************/
/* PROGRAM NAME: TABODBC */
/* ------------- */
-/* Version 2.3 */
+/* Version 2.4 */
/* */
/* COPYRIGHT: */
/* ---------- */
-/* (C) Copyright to the author Olivier BERTRAND 2000-2012 */
+/* (C) Copyright to the author Olivier BERTRAND 2000-2013 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@@ -32,7 +32,7 @@
/***********************************************************************/
/***********************************************************************/
-/* Include relevant MariaDB header file. */
+/* Include relevant MariaDB header file. */
/***********************************************************************/
#include "my_global.h"
#if defined(WIN32)
@@ -74,6 +74,7 @@
#include "sql_string.h"
+PQRYRES ODBCDataSources(PGLOBAL g);
/***********************************************************************/
/* DB static variables. */
@@ -84,6 +85,16 @@ extern int num_read, num_there, num_eq[2]; // Statistics
/* -------------------------- Class ODBCDEF -------------------------- */
/***********************************************************************/
+/* Constructor. */
+/***********************************************************************/
+ODBCDEF::ODBCDEF(void)
+ {
+ Connect = Tabname = Tabowner = Tabqual = Qchar = NULL;
+ Catver = Options = 0;
+ Info = false;
+ } // end of ODBCDEF constructor
+
+/***********************************************************************/
/* DefineAM: define specific AM block values from XDB file. */
/***********************************************************************/
bool ODBCDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
@@ -102,6 +113,7 @@ bool ODBCDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
Options = Cat->GetIntCatInfo(Name, "Options", dop);
//Options = Cat->GetIntCatInfo(Name, "Options", 0);
Pseudo = 2; // FILID is Ok but not ROWID
+ Info = Cat->GetBoolCatInfo(Name, "Info", false);
return false;
} // end of DefineAM
@@ -116,12 +128,16 @@ PTDB ODBCDEF::GetTable(PGLOBAL g, MODE m)
/* Allocate a TDB of the proper type. */
/* Column blocks will be allocated only when needed. */
/*********************************************************************/
- tdbp = new(g) TDBODBC(this);
+ if (!Info) {
+ tdbp = new(g) TDBODBC(this);
- if (Multiple == 1)
- tdbp = new(g) TDBMUL(tdbp);
- else if (Multiple == 2)
- strcpy(g->Message, MSG(NO_ODBC_MUL));
+ if (Multiple == 1)
+ tdbp = new(g) TDBMUL(tdbp);
+ else if (Multiple == 2)
+ strcpy(g->Message, MSG(NO_ODBC_MUL));
+
+ } else
+ tdbp = new(g) TDBOIF(this);
return tdbp;
} // end of GetTable
@@ -881,4 +897,183 @@ void ODBCCOL::WriteColumn(PGLOBAL g)
} // end of WriteColumn
+/* ---------------------------TDBOIF class --------------------------- */
+
+/***********************************************************************/
+/* Implementation of the TDBOIF class. */
+/***********************************************************************/
+TDBOIF::TDBOIF(PODEF tdp) : TDBASE(tdp)
+ {
+ Qrp = NULL;
+ 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
+
+ if (!colp->Flag) {
+ if (!stricmp(colp->Name, "Name"))
+ colp->Flag = 1;
+ else if (!stricmp(colp->Name, "Description"))
+ colp->Flag = 2;
+
+ } // endif Flag
+
+ return colp;
+ } // end of MakeCol
+
+/***********************************************************************/
+/* Initialize: Get the list of ODBC data sources. */
+/***********************************************************************/
+bool TDBOIF::Initialize(PGLOBAL g)
+ {
+ if (Init)
+ return false;
+
+ if (!(Qrp = ODBCDataSources(g)))
+ return true;
+
+ Init = true;
+ return false;
+ } // end of Initialize
+
+/***********************************************************************/
+/* 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;
+
+ for (colp = (POIFCOL)Columns; colp; colp = (POIFCOL)colp->GetNext())
+ switch (colp->Flag) {
+ case 1:
+ colp->Crp = Qrp->Colresp;
+ break;
+ case 2:
+ colp->Crp = Qrp->Colresp->Next;
+ break;
+ default:
+ strcpy(g->Message, "Invalid column name or flag");
+ return true;
+ } // endswitch Flag
+
+ 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_psz(Crp->Kdata->GetCharValue(Tdbp->N));
+ } // end of ReadColumn
+
/* ------------------------ End of Tabodbc --------------------------- */
diff --git a/storage/connect/tabodbc.h b/storage/connect/tabodbc.h
index 2b24ebc8e7c..5509d3df679 100644
--- a/storage/connect/tabodbc.h
+++ b/storage/connect/tabodbc.h
@@ -1,7 +1,7 @@
/*************** Tabodbc H Declares Source Code File (.H) **************/
-/* Name: TABODBC.H Version 1.4 */
+/* Name: TABODBC.H Version 1.5 */
/* */
-/* (C) Copyright to the author Olivier BERTRAND 2000-2012 */
+/* (C) Copyright to the author Olivier BERTRAND 2000-2013 */
/* */
/* This file contains the TDBODBC classes declares. */
/***********************************************************************/
@@ -10,6 +10,8 @@
typedef class ODBCDEF *PODEF;
typedef class TDBODBC *PTDBODBC;
typedef class ODBCCOL *PODBCCOL;
+typedef class TDBOIF *PTDBOIF;
+typedef class OIFCOL *POIFCOL;
/***********************************************************************/
/* ODBC table. */
@@ -17,8 +19,7 @@ typedef class ODBCCOL *PODBCCOL;
class DllExport ODBCDEF : public TABDEF { /* Logical table description */
public:
// Constructor
- ODBCDEF(void)
- {Connect = Tabname = Tabowner = Tabqual = Qchar = NULL; Options = 0;}
+ ODBCDEF(void);
// Implementation
virtual const char *GetType(void) {return "ODBC";}
@@ -43,6 +44,7 @@ class DllExport ODBCDEF : public TABDEF { /* Logical table description */
PSZ Qchar; /* Identifier quoting character */
int Catver; /* ODBC version for catalog functions */
int Options; /* Open connection options */
+ bool Info; /* true if getting data sources */
}; // end of ODBCDEF
#if !defined(NODBC)
@@ -158,5 +160,66 @@ class ODBCCOL : public COLBLK {
SQLLEN Slen; // Used with Fetch
int Rank; // Rank (position) number in the query
}; // end of class ODBCCOL
+
+/***********************************************************************/
+/* This is the class declaration for the ODBC info table. */
+/***********************************************************************/
+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
+ bool Initialize(PGLOBAL g);
+ bool InitCol(PGLOBAL g);
+
+ // Members
+ PQRYRES Qrp;
+ 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
#endif // !NODBC