diff options
Diffstat (limited to 'storage/connect/odbconn.cpp')
-rw-r--r-- | storage/connect/odbconn.cpp | 189 |
1 files changed, 110 insertions, 79 deletions
diff --git a/storage/connect/odbconn.cpp b/storage/connect/odbconn.cpp index 3e616ec8f04..6aaa048de81 100644 --- a/storage/connect/odbconn.cpp +++ b/storage/connect/odbconn.cpp @@ -1,5 +1,5 @@ /************ Odbconn C++ Functions Source Code File (.CPP) ************/ -/* Name: ODBCONN.CPP Version 2.1 */ +/* Name: ODBCONN.CPP Version 2.2 */ /* */ /* (C) Copyright to the author Olivier BERTRAND 1998-2015 */ /* */ @@ -11,7 +11,7 @@ /***********************************************************************/ #include <my_global.h> #include <m_string.h> -#if defined(WIN32) +#if defined(__WIN__) //nclude <io.h> //nclude <fcntl.h> #include <direct.h> // for getcwd @@ -37,21 +37,23 @@ #include "xobject.h" //#include "kindex.h" #include "xtable.h" -#include "tabodbc.h" #include "odbccat.h" +#include "tabodbc.h" #include "plgcnx.h" // For DB types #include "resource.h" #include "valblk.h" #include "osutil.h" -#if defined(WIN32) +#if defined(__WIN__) /***********************************************************************/ /* For dynamic load of ODBC32.DLL */ /***********************************************************************/ #pragma comment(lib, "odbc32.lib") extern "C" HINSTANCE s_hModule; // Saved module handle -#endif // WIN32 +#endif // __WIN__ + +int GetConvSize(); /***********************************************************************/ /* Some macro's (should be defined elsewhere to be more accessible) */ @@ -100,7 +102,12 @@ static int GetSQLCType(int type) case TYPE_BIGINT: tp = SQL_C_SBIGINT; break; case TYPE_DOUBLE: tp = SQL_C_DOUBLE; break; case TYPE_TINY : tp = SQL_C_TINYINT; break; +//#if (ODBCVER >= 0x0300) +// case TYPE_DECIM: tp = SQL_C_NUMERIC; break; (CRASH!!!) +//#else case TYPE_DECIM: tp = SQL_C_CHAR; break; +//#endif + } // endswitch type return tp; @@ -109,20 +116,28 @@ static int GetSQLCType(int type) /***********************************************************************/ /* TranslateSQLType: translate a SQL Type to a PLG type. */ /***********************************************************************/ -int TranslateSQLType(int stp, int prec, int& len, char& v) +int TranslateSQLType(int stp, int prec, int& len, char& v, bool& w) { int type; switch (stp) { + case SQL_WVARCHAR: // (-9) + w = true; case SQL_VARCHAR: // 12 v = 'V'; + type = TYPE_STRING; + break; + case SQL_WCHAR: // (-8) + w = true; case SQL_CHAR: // 1 type = TYPE_STRING; break; + case SQL_WLONGVARCHAR: // (-10) + w = true; case SQL_LONGVARCHAR: // (-1) v = 'V'; type = TYPE_STRING; - len = MY_MIN(abs(len), 256); + len = MY_MIN(abs(len), GetConvSize()); break; case SQL_NUMERIC: // 2 case SQL_DECIMAL: // 3 @@ -173,7 +188,6 @@ int TranslateSQLType(int stp, int prec, int& len, char& v) case SQL_BINARY: // (-2) case SQL_VARBINARY: // (-3) case SQL_LONGVARBINARY: // (-4) -// case SQL_BIT: // (-7) case SQL_GUID: // (-11) default: type = TYPE_ERROR; @@ -291,7 +305,7 @@ static void ResetNullValues(CATPARM *cap) /* of an ODBC table that will be retrieved by GetData commands. */ /***********************************************************************/ PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *db, char *table, - char *colpat, int maxres, int cto, int qto, bool info) + char *colpat, int maxres, bool info, POPARM sop) { int buftyp[] = {TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_INT, TYPE_INT, @@ -310,10 +324,8 @@ PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *db, char *table, /************************************************************************/ if (!info) { ocp = new(g) ODBConn(g, NULL); - ocp->SetLoginTimeout((DWORD)cto); - ocp->SetQueryTimeout((DWORD)qto); - if (ocp->Open(dsn, 10) < 1) // openReadOnly + noODBCdialog + if (ocp->Open(dsn, sop, 10) < 1) // openReadOnly + noODBCdialog return NULL; if (table && !strchr(table, '%')) { @@ -342,7 +354,7 @@ PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *db, char *table, } // endif ocp if (trace) - htrc("ODBCColumns: max=%d len=%d,%d,%d\n", + htrc("ODBCColumns: max=%d len=%d,%d,%d,%d\n", maxres, length[0], length[1], length[2], length[3]); /************************************************************************/ @@ -388,12 +400,13 @@ PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *db, char *table, /* ODBCSrcCols: constructs the result blocks containing the */ /* description of all the columns of a Srcdef option. */ /**************************************************************************/ -PQRYRES ODBCSrcCols(PGLOBAL g, char *dsn, char *src, int cto, int qto) +PQRYRES ODBCSrcCols(PGLOBAL g, char *dsn, char *src, POPARM sop) { ODBConn *ocp = new(g) ODBConn(g, NULL); - ocp->SetLoginTimeout((DWORD)cto); - ocp->SetQueryTimeout((DWORD)qto); + if (ocp->Open(dsn, sop, 10) < 1) // openReadOnly + noOdbcDialog + return NULL; + return ocp->GetMetaData(g, dsn, src); } // end of ODBCSrcCols @@ -404,6 +417,7 @@ PQRYRES ODBCSrcCols(PGLOBAL g, char *dsn, char *src, int cto, int qto) PQRYRES MyODBCCols(PGLOBAL g, char *dsn, char *tab, bool info) { // int i, type, len, prec; + bool w = false; // PCOLRES crp, crpt, crpl, crpp; PQRYRES qrp; ODBConn *ocp; @@ -449,7 +463,7 @@ PQRYRES MyODBCCols(PGLOBAL g, char *dsn, char *tab, bool info) type = crpt->Kdata->GetIntValue(i); len = crpl->Kdata->GetIntValue(i); prec = crpp->Kdata->GetIntValue(i); - type = TranslateSQLType(type, prec, len); + type = TranslateSQLType(type, prec, len, w); crpt->Kdata->SetValue(type, i); // Some data sources do not count prec in length @@ -574,7 +588,7 @@ PQRYRES ODBCDataSources(PGLOBAL g, int maxres, bool info) /* an ODBC database that will be retrieved by GetData commands. */ /**************************************************************************/ PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *db, char *tabpat, - int maxres, int cto, int qto, bool info) + int maxres, bool info, POPARM sop) { int buftyp[] = {TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_STRING}; @@ -594,10 +608,8 @@ PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *db, char *tabpat, /* Open the connection with the ODBC data source. */ /**********************************************************************/ ocp = new(g) ODBConn(g, NULL); - ocp->SetLoginTimeout((DWORD)cto); - ocp->SetQueryTimeout((DWORD)qto); - if (ocp->Open(dsn, 2) < 1) // 2 is openReadOnly + if (ocp->Open(dsn, sop, 2) < 1) // 2 is openReadOnly return NULL; if (!maxres) @@ -863,8 +875,7 @@ bool DBX::BuildErrorMessage(ODBConn* pdb, HSTMT hstmt) for (int i = 0; i < MAX_NUM_OF_MSG && (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) && strcmp((char*)state, "00000"); i++) { - m_ErrMsg[i] = (PSZ)PlugSubAlloc(g, NULL, strlen((char*)msg) + 1); - strcpy(m_ErrMsg[i], (char*)msg); + m_ErrMsg[i] = (PSZ)PlugDup(g, (char*)msg); if (trace) htrc("%s: %s, Native=%d\n", state, msg, native); @@ -878,8 +889,7 @@ bool DBX::BuildErrorMessage(ODBConn* pdb, HSTMT hstmt) } else { snprintf((char*)msg, SQL_MAX_MESSAGE_LENGTH + 1, "%s: %s", m_Msg, MSG(BAD_HANDLE_VAL)); - m_ErrMsg[0] = (PSZ)PlugSubAlloc(g, NULL, strlen((char*)msg) + 1); - strcpy(m_ErrMsg[0], (char*)msg); + m_ErrMsg[0] = (PSZ)PlugDup(g, (char*)msg); if (trace) htrc("%s: rc=%hd\n", SVP(m_ErrMsg[0]), m_RC); @@ -924,12 +934,15 @@ ODBConn::ODBConn(PGLOBAL g, TDBODBC *tdbp) m_RowsetSize = (DWORD)((tdbp) ? tdbp->Rows : 10); m_Catver = (tdbp) ? tdbp->Catver : 0; m_Rows = 0; + m_Fetch = 0; m_Connect = NULL; + m_User = NULL; + m_Pwd = NULL; m_Updatable = true; m_Transact = false; m_Scrollable = (tdbp) ? tdbp->Scrollable : false; - m_First = true; m_Full = false; + m_UseCnc = false; m_IDQuoteChar[0] = '"'; m_IDQuoteChar[1] = 0; //*m_ErrMsg = '\0'; @@ -982,7 +995,7 @@ void ODBConn::ThrowDBX(RETCODE rc, PSZ msg, HSTMT hstmt) void ODBConn::ThrowDBX(PSZ msg) { - DBX* xp = new(m_G) DBX(0, msg); + DBX* xp = new(m_G) DBX(0, "Error"); xp->m_ErrMsg[0] = msg; throw xp; @@ -1005,8 +1018,7 @@ PSZ ODBConn::GetStringInfo(ushort infotype) // *buffer = '\0'; } // endif rc - p = (char *)PlugSubAlloc(m_G, NULL, strlen(buffer) + 1); - strcpy(p, buffer); + p = PlugDup(m_G, buffer); return p; } // end of GetStringInfo @@ -1061,7 +1073,7 @@ void ODBConn::OnSetOptions(HSTMT hstmt) /***********************************************************************/ /* Open: connect to a data source. */ /***********************************************************************/ -int ODBConn::Open(PSZ ConnectString, DWORD options) +int ODBConn::Open(PSZ ConnectString, POPARM sop, DWORD options) { PGLOBAL& g = m_G; //ASSERT_VALID(this); @@ -1070,6 +1082,11 @@ int ODBConn::Open(PSZ ConnectString, DWORD options) m_Updatable = !(options & openReadOnly); m_Connect = ConnectString; + m_User = sop->User; + m_Pwd = sop->Pwd; + m_LoginTimeout = sop->Cto; + m_QueryTimeout = sop->Qto; + m_UseCnc = sop->UseCnc; // Allocate the HDBC and make connection try { @@ -1078,18 +1095,21 @@ int ODBConn::Open(PSZ ConnectString, DWORD options) AllocConnect(options); /*ver = GetStringInfo(SQL_ODBC_VER);*/ - if (Connect(options)) { - strcpy(g->Message, MSG(CONNECT_CANCEL)); - return 0; - } // endif + if (!m_UseCnc) { + if (DriverConnect(options)) { + strcpy(g->Message, MSG(CONNECT_CANCEL)); + return 0; + } // endif + + } else // Connect using SQLConnect + Connect(); /*ver = GetStringInfo(SQL_DRIVER_ODBC_VER);*/ // Verify support for required functionality and cache info // VerifyConnect(); Deprecated GetConnectInfo(); } catch(DBX *xp) { -// strcpy(g->Message, xp->m_ErrMsg[0]); - strcpy(g->Message, xp->GetErrorMessage(0)); + sprintf(g->Message, "%s: %s", xp->m_Msg, xp->GetErrorMessage(0)); Close(); // Free(); return -1; @@ -1164,23 +1184,40 @@ void ODBConn::AllocConnect(DWORD Options) } // end of AllocConnect /***********************************************************************/ +/* Connect to data source using SQLConnect. */ +/***********************************************************************/ +void ODBConn::Connect(void) + { + SQLRETURN rc; + SQLSMALLINT ul = (m_User ? SQL_NTS : 0); + SQLSMALLINT pl = (m_Pwd ? SQL_NTS : 0); + + rc = SQLConnect(m_hdbc, (SQLCHAR*)m_Connect, SQL_NTS, + (SQLCHAR*)m_User, ul, (SQLCHAR*)m_Pwd, pl); + + if (!Check(rc)) + ThrowDBX(rc, "SQLConnect"); + + } // end of Connect + +/***********************************************************************/ /* Connect to data source using SQLDriverConnect. */ /***********************************************************************/ -bool ODBConn::Connect(DWORD Options) +bool ODBConn::DriverConnect(DWORD Options) { RETCODE rc; SWORD nResult; PUCHAR ConnOut = (PUCHAR)PlugSubAlloc(m_G, NULL, MAX_CONNECT_LEN); UWORD wConnectOption = SQL_DRIVER_COMPLETE; -#if defined(WIN32) +#if defined(__WIN__) HWND hWndTop = GetForegroundWindow(); HWND hWnd = GetParent(hWndTop); if (hWnd == NULL) hWnd = GetDesktopWindow(); -#else // !WIN32 +#else // !__WIN__ HWND hWnd = (HWND)1; -#endif // !WIN32 +#endif // !__WIN__ PGLOBAL& g = m_G; PDBUSER dup = PlgGetUser(g); @@ -1193,10 +1230,10 @@ bool ODBConn::Connect(DWORD Options) SQL_NTS, ConnOut, MAX_CONNECT_LEN, &nResult, wConnectOption); -#if defined(WIN32) +#if defined(__WIN__) if (hWndTop) EnableWindow(hWndTop, true); -#endif // WIN32 +#endif // __WIN__ // If user hit 'Cancel' if (rc == SQL_NO_DATA_FOUND) { @@ -1213,7 +1250,7 @@ bool ODBConn::Connect(DWORD Options) // All done return false; - } // end of Connect + } // end of DriverConnect void ODBConn::VerifyConnect() { @@ -1328,7 +1365,7 @@ int ODBConn::ExecDirectSQL(char *sql, ODBCCOL *tocols) rc = SQLFreeStmt(m_hstmt, SQL_CLOSE); if (!Check(rc)) - ThrowDBX(rc, "SQLFreeStmt"); + ThrowDBX(rc, "SQLFreeStmt", m_hstmt); m_hstmt = NULL; } // endif m_hstmt @@ -1343,7 +1380,7 @@ int ODBConn::ExecDirectSQL(char *sql, ODBCCOL *tocols) (void*)SQL_SCROLLABLE, 0); if (!Check(rc)) - ThrowDBX(rc, "SQLSetStmtAttr"); + ThrowDBX(rc, "Scrollable", hstmt); } // endif m_Scrollable @@ -1394,7 +1431,7 @@ int ODBConn::ExecDirectSQL(char *sql, ODBCCOL *tocols) for (n = 0, colp = tocols; colp; colp = (PODBCCOL)colp->GetNext()) if (!colp->IsSpecial()) - n++; + n++; // n can be 0 for query such as Select count(*) from table if (n && n != (UWORD)ncol) @@ -1430,7 +1467,7 @@ int ODBConn::ExecDirectSQL(char *sql, ODBCCOL *tocols) for (int i = 0; i < MAX_NUM_OF_MSG && x->m_ErrMsg[i]; i++) htrc(x->m_ErrMsg[i]); - strcpy(m_G->Message, x->GetErrorMessage(0)); + sprintf(m_G->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0)); if (b) SQLCancel(hstmt); @@ -1493,7 +1530,7 @@ int ODBConn::GetResultSize(char *sql, ODBCCOL *colp) /***********************************************************************/ /* Fetch next row. */ /***********************************************************************/ -int ODBConn::Fetch() +int ODBConn::Fetch(int pos) { ASSERT(m_hstmt); int irc; @@ -1503,7 +1540,9 @@ int ODBConn::Fetch() try { // do { - if (m_RowsetSize) { + if (pos) { + rc = SQLExtendedFetch(m_hstmt, SQL_FETCH_ABSOLUTE, pos, &crow, NULL); + } else if (m_RowsetSize) { rc = SQLExtendedFetch(m_hstmt, SQL_FETCH_NEXT, 1, &crow, NULL); } else { rc = SQLFetch(m_hstmt); @@ -1516,29 +1555,22 @@ int ODBConn::Fetch() m_hstmt, m_RowsetSize, rc); if (!Check(rc)) - ThrowDBX(rc, "Fetch", m_hstmt); - - irc = (rc == SQL_NO_DATA_FOUND) ? 0 : (int)crow; - - if (m_First) { - // First fetch. Check whether the full table was read - if ((m_Full = irc < (signed)m_RowsetSize)) { - m_Tdb->Memory = 0; // Not needed anymore - m_Rows = irc; // Table size - } // endif m_Full - - m_First = false; - } // endif m_First + ThrowDBX(rc, "Fetching", m_hstmt); - if (m_Tdb->Memory == 1) - m_Rows += irc; + if (rc == SQL_NO_DATA_FOUND) { + m_Full = (m_Fetch == 1); + irc = 0; + } else + irc = (int)crow; + m_Fetch++; + m_Rows += irc; } catch(DBX *x) { if (trace) for (int i = 0; i < MAX_NUM_OF_MSG && x->m_ErrMsg[i]; i++) htrc(x->m_ErrMsg[i]); - strcpy(g->Message, x->GetErrorMessage(0)); + sprintf(g->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0)); irc = -1; } // end try/catch @@ -1574,7 +1606,7 @@ int ODBConn::PrepareSQL(char *sql) for (int i = 0; i < MAX_NUM_OF_MSG && x->m_ErrMsg[i]; i++) htrc(x->m_ErrMsg[i]); - strcpy(g->Message, x->GetErrorMessage(0)); + sprintf(g->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0)); } // end try/catch } // endif Mode @@ -1620,7 +1652,7 @@ int ODBConn::PrepareSQL(char *sql) for (int i = 0; i < MAX_NUM_OF_MSG && x->m_ErrMsg[i]; i++) htrc(x->m_ErrMsg[i]); - strcpy(g->Message, x->GetErrorMessage(0)); + sprintf(g->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0)); if (b) SQLCancel(hstmt); @@ -1672,7 +1704,7 @@ int ODBConn::ExecuteSQL(void) } // endif ncol } catch(DBX *x) { - strcpy(m_G->Message, x->GetErrorMessage(0)); + sprintf(m_G->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0)); SQLCancel(m_hstmt); rc = SQLFreeStmt(m_hstmt, SQL_DROP); m_hstmt = NULL; @@ -1709,9 +1741,11 @@ bool ODBConn::BindParam(ODBCCOL *colp) ThrowDBX(rc, "SQLDescribeParam", m_hstmt); } catch(DBX *x) { - strcpy(m_G->Message, x->GetErrorMessage(0)); + sprintf(m_G->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0)); colsize = colp->GetPrecision(); sqlt = GetSQLType(buftype); + dec = IsTypeChar(buftype) ? 0 : colp->GetScale(); + nul = SQL_NULLABLE_UNKNOWN; } // end try/catch buf = colp->GetBuffer(0); @@ -1815,7 +1849,7 @@ bool ODBConn::ExecSQLcommand(char *sql) for (int i = 0; i < MAX_NUM_OF_MSG && x->m_ErrMsg[i]; i++) htrc(x->m_ErrMsg[i]); - sprintf(g->Message, "Remote: %s", x->GetErrorMessage(0)); + sprintf(g->Message, "Remote %s: %s", x->m_Msg, x->GetErrorMessage(0)); if (b) SQLCancel(hstmt); @@ -1865,9 +1899,6 @@ PQRYRES ODBConn::GetMetaData(PGLOBAL g, char *dsn, char *src) RETCODE rc; HSTMT hstmt; - if (Open(dsn, 10) < 1) // openReadOnly + noOdbcDialog - return NULL; - try { rc = SQLAllocStmt(m_hdbc, &hstmt); @@ -1903,7 +1934,7 @@ PQRYRES ODBConn::GetMetaData(PGLOBAL g, char *dsn, char *src) } // endfor i } catch(DBX *x) { - strcpy(g->Message, x->GetErrorMessage(0)); + sprintf(g->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0)); goto err; } // end try/catch @@ -1954,7 +1985,7 @@ PQRYRES ODBConn::GetMetaData(PGLOBAL g, char *dsn, char *src) } // endfor i } catch(DBX *x) { - strcpy(g->Message, x->GetErrorMessage(0)); + sprintf(g->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0)); qrp = NULL; } // end try/catch @@ -2006,7 +2037,7 @@ bool ODBConn::GetDataSources(PQRYRES qrp) } // endfor i } catch(DBX *x) { - strcpy(m_G->Message, x->GetErrorMessage(0)); + sprintf(m_G->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0)); rv = true; } // end try/catch @@ -2057,7 +2088,7 @@ bool ODBConn::GetDrivers(PQRYRES qrp) } // endfor n } catch(DBX *x) { - strcpy(m_G->Message, x->GetErrorMessage(0)); + sprintf(m_G->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0)); rv = true; } // end try/catch @@ -2375,7 +2406,7 @@ int ODBConn::GetCatInfo(CATPARM *cap) for (int i = 0; i < MAX_NUM_OF_MSG && x->m_ErrMsg[i]; i++) htrc(x->m_ErrMsg[i]); - strcpy(g->Message, x->GetErrorMessage(0)); + sprintf(g->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0)); irc = -1; } // end try/catch @@ -2479,7 +2510,7 @@ int ODBConn::Rewind(char *sql, ODBCCOL *tocols) rbuf = (int)crow; } catch(DBX *x) { - strcpy(m_G->Message, x->GetErrorMessage(0)); + sprintf(m_G->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0)); rbuf = -1; } // end try/catch |