diff options
author | Sergei Golubchik <serg@mariadb.org> | 2016-06-28 22:12:50 +0200 |
---|---|---|
committer | Sergei Golubchik <serg@mariadb.org> | 2016-06-28 22:12:50 +0200 |
commit | 736f821c420954912464b9ae521acc5b768438cc (patch) | |
tree | 6348f794bb3b1ec24d7064000b7ea6e941f9ec2c | |
parent | 62e0a4552f3b4a932f9aa055579dad716b371b9b (diff) | |
parent | 7e64b079680b5f0f1e1cb735e3c83e45e96ec0e3 (diff) | |
download | mariadb-git-736f821c420954912464b9ae521acc5b768438cc.tar.gz |
Merge branch 'connect/10.1' into 10.1
-rw-r--r-- | .gitattributes | 3 | ||||
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | storage/connect/JdbcInterface.class | bin | 15215 -> 15215 bytes | |||
-rw-r--r-- | storage/connect/JdbcInterface.java | 2 | ||||
-rw-r--r-- | storage/connect/ha_connect.cc | 49 | ||||
-rw-r--r-- | storage/connect/jdbccat.h | 8 | ||||
-rw-r--r-- | storage/connect/jdbconn.cpp | 1094 | ||||
-rw-r--r-- | storage/connect/jdbconn.h | 67 | ||||
-rw-r--r-- | storage/connect/odbccat.h | 2 | ||||
-rw-r--r-- | storage/connect/odbconn.cpp | 4 | ||||
-rw-r--r-- | storage/connect/tabjdbc.cpp | 180 | ||||
-rw-r--r-- | storage/connect/tabjdbc.h | 21 | ||||
-rw-r--r-- | storage/connect/tabodbc.cpp | 27 | ||||
-rw-r--r-- | storage/connect/tabodbc.h | 15 |
14 files changed, 844 insertions, 630 deletions
diff --git a/.gitattributes b/.gitattributes index b2e324795aa..852eec4d638 100644 --- a/.gitattributes +++ b/.gitattributes @@ -9,6 +9,7 @@ *.cpp text *.h text *.test text +*.java text # These files should be checked out as is *.result -text -whitespace @@ -23,9 +24,11 @@ pcre/testdata/greppatN4 -text *.frm binary *.MYD binary *.MYI binary +*.class binary *.c diff=cpp *.h diff=cpp *.cc diff=cpp *.ic diff=cpp *.cpp diff=cpp +*.java diff=cpp diff --git a/.gitignore b/.gitignore index f2064537da4..279d3f59dc5 100644 --- a/.gitignore +++ b/.gitignore @@ -244,6 +244,8 @@ storage/mroonga/mysql-test/mroonga/storage/r/variable_version.result *.exp *.dep *.idb +*.res +*.tlog # Precompiled Headers *.gch diff --git a/storage/connect/JdbcInterface.class b/storage/connect/JdbcInterface.class Binary files differindex 8c5ba6439f3..51a0e69bad5 100644 --- a/storage/connect/JdbcInterface.class +++ b/storage/connect/JdbcInterface.class diff --git a/storage/connect/JdbcInterface.java b/storage/connect/JdbcInterface.java index f9a6e734454..8c4db1db8c3 100644 --- a/storage/connect/JdbcInterface.java +++ b/storage/connect/JdbcInterface.java @@ -307,7 +307,7 @@ public class JdbcInterface { } // end of GetMaxValue public int GetColumns(String[] parms) { - int ncol = 0; + int ncol = -1; try { if (rs != null) rs.close(); diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index eaebd88b0cd..6a8fc4514f1 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -129,7 +129,8 @@ #include "odbccat.h" #endif // ODBC_SUPPORT #if defined(JDBC_SUPPORT) -#include "jdbccat.h" +#include "tabjdbc.h" +#include "jdbconn.h" #endif // JDBC_SUPPORT #include "xtable.h" #include "tabmysql.h" @@ -5163,7 +5164,6 @@ static int connect_assisted_discovery(handlerton *, THD* thd, #endif // ODBC_SUPPORT #if defined(JDBC_SUPPORT) PJPARM sjp= NULL; - char *jpath= NULL; char *driver= NULL; char *url= NULL; char *tabtyp = NULL; @@ -5230,9 +5230,8 @@ static int connect_assisted_discovery(handlerton *, THD* thd, cnc= (!*ucnc || *ucnc == 'y' || *ucnc == 'Y' || atoi(ucnc) != 0); #endif #if defined(JDBC_SUPPORT) - jpath= GetListOption(g, "Jpath", topt->oplist, NULL); driver= GetListOption(g, "Driver", topt->oplist, NULL); - url= GetListOption(g, "URL", topt->oplist, NULL); +// url= GetListOption(g, "URL", topt->oplist, NULL); tabtyp = GetListOption(g, "Tabtype", topt->oplist, NULL); #endif // JDBC_SUPPORT mxe= atoi(GetListOption(g,"maxerr", topt->oplist, "0")); @@ -5333,18 +5332,31 @@ static int connect_assisted_discovery(handlerton *, THD* thd, case TAB_JDBC: if (fnc & FNC_DRIVER) { ok= true; - } else if (!url) { - strcpy(g->Message, "Missing URL"); + } else if (!(url= strz(g, create_info->connect_string))) { + strcpy(g->Message, "Missing URL"); } else { - // Store ODBC additional parameters + // Store JDBC additional parameters + int rc; + PJDBCDEF jdef= new(g) JDBCDEF(); + + jdef->SetName(create_info->alias); sjp= (PJPARM)PlugSubAlloc(g, NULL, sizeof(JDBCPARM)); sjp->Driver= driver; - sjp->Url= url; - sjp->User= (char*)user; - sjp->Pwd= (char*)pwd; sjp->Fsize= 0; sjp->Scrollable= false; - ok= true; + + if ((rc = jdef->ParseURL(g, url, false)) == RC_OK) { + sjp->Url= url; + sjp->User= (char*)user; + sjp->Pwd= (char*)pwd; + ok= true; + } else if (rc == RC_NF) { + if (jdef->GetTabname()) + tab= jdef->GetTabname(); + + ok= jdef->SetParms(sjp); + } // endif rc + } // endif's supfnc |= (FNC_DRIVER | FNC_TABLE); @@ -5496,7 +5508,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd, break; case FNC_TABLE: - qrp= ODBCTables(g, dsn, shm, tab, mxr, true, sop); + qrp= ODBCTables(g, dsn, shm, tab, NULL, mxr, true, sop); break; case FNC_DSN: qrp= ODBCDataSources(g, mxr, true); @@ -5517,15 +5529,14 @@ static int connect_assisted_discovery(handlerton *, THD* thd, case FNC_NO: case FNC_COL: if (src) { - qrp= JDBCSrcCols(g, jpath, (char*)src, sjp); + qrp= JDBCSrcCols(g, (char*)src, sjp); src= NULL; // for next tests } else - qrp= JDBCColumns(g, jpath, shm, tab, NULL, - mxr, fnc == FNC_COL, sjp); + qrp= JDBCColumns(g, shm, tab, NULL, mxr, fnc == FNC_COL, sjp); break; case FNC_TABLE: - qrp= JDBCTables(g, dsn, shm, tab, tabtyp, mxr, true, sjp); + qrp= JDBCTables(g, shm, tab, tabtyp, mxr, true, sjp); break; #if 0 case FNC_DSN: @@ -5533,7 +5544,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd, break; #endif // 0 case FNC_DRIVER: - qrp= JDBCDrivers(g, jpath, mxr, true); + qrp= JDBCDrivers(g, mxr, true); break; default: sprintf(g->Message, "invalid catfunc %s", fncn); @@ -5784,12 +5795,10 @@ static int connect_assisted_discovery(handlerton *, THD* thd, switch (typ) { case TYPE_DOUBLE: + case TYPE_DECIM: // Some data sources do not count dec in length (prec) prec += (dec + 2); // To be safe break; - case TYPE_DECIM: - prec= len; - break; default: dec= 0; } // endswitch typ diff --git a/storage/connect/jdbccat.h b/storage/connect/jdbccat.h index 150197804d5..37f33d7063d 100644 --- a/storage/connect/jdbccat.h +++ b/storage/connect/jdbccat.h @@ -21,9 +21,9 @@ typedef struct jdbc_parms { char *JDBCCheckConnection(PGLOBAL g, char *dsn, int cop); #endif // PROMPT_OK //PQRYRES JDBCDataSources(PGLOBAL g, int maxres, bool info); -PQRYRES JDBCColumns(PGLOBAL g, char *jpath, char *db, char *table, +PQRYRES JDBCColumns(PGLOBAL g, char *db, char *table, char *colpat, int maxres, bool info, PJPARM sop); -PQRYRES JDBCSrcCols(PGLOBAL g, char *jpath, char *src, PJPARM sop); -PQRYRES JDBCTables(PGLOBAL g, char *jpath, char *db, char *tabpat, +PQRYRES JDBCSrcCols(PGLOBAL g, char *src, PJPARM sop); +PQRYRES JDBCTables(PGLOBAL g, char *db, char *tabpat, char *tabtyp, int maxres, bool info, PJPARM sop); -PQRYRES JDBCDrivers(PGLOBAL g, char *jpath, int maxres, bool info); +PQRYRES JDBCDrivers(PGLOBAL g, int maxres, bool info); diff --git a/storage/connect/jdbconn.cpp b/storage/connect/jdbconn.cpp index cf744971c9e..9b479277df2 100644 --- a/storage/connect/jdbconn.cpp +++ b/storage/connect/jdbconn.cpp @@ -17,17 +17,19 @@ #include <direct.h> // for getcwd #if defined(__BORLANDC__) #define __MFC_COMPAT__ // To define min/max as macro -#endif +#endif // __BORLANDC__ //#include <windows.h> -#else +#else // !__WIN__ #if defined(UNIX) #include <errno.h> -#else +#else // !UNIX //nclude <io.h> -#endif +#endif // !UNIX +#include <stdio.h> +#include <stdlib.h> // for getenv //nclude <fcntl.h> #define NODW -#endif +#endif // !__WIN__ /***********************************************************************/ /* Required objects includes. */ @@ -36,7 +38,6 @@ #include "plgdbsem.h" #include "xobject.h" #include "xtable.h" -#include "jdbccat.h" #include "tabjdbc.h" //#include "jdbconn.h" //#include "plgcnx.h" // For DB types @@ -47,9 +48,24 @@ #if defined(__WIN__) extern "C" HINSTANCE s_hModule; // Saved module handle -#endif // __WIN__ +#else // !__WIN__ +#define nullptr 0 +#endif // !__WIN__ int GetConvSize(); +extern char *JvmPath; // The connect_jvm_path global variable value +extern char *ClassPath; // The connect_class_path global variable value +extern char *Wrapper; // The connect_java_wrapper global variable value + +/***********************************************************************/ +/* Static JDBConn objects. */ +/***********************************************************************/ +void *JDBConn::LibJvm = NULL; +CRTJVM JDBConn::CreateJavaVM = NULL; +GETJVM JDBConn::GetCreatedJavaVMs = NULL; +#if defined(_DEBUG) +GETDEF JDBConn::GetDefaultJavaVMInitArgs = NULL; +#endif // _DEBUG /***********************************************************************/ /* Some macro's (should be defined elsewhere to be more accessible) */ @@ -62,6 +78,9 @@ int GetConvSize(); #define DEBUG_ONLY(f) ((void)0) #endif // !_DEBUG +// To avoid gcc warning +int TranslateJDBCType(int stp, int prec, int& len, char& v); + /***********************************************************************/ /* GetJDBCType: returns the SQL_TYPE corresponding to a PLG type. */ /***********************************************************************/ @@ -102,6 +121,7 @@ int TranslateJDBCType(int stp, int prec, int& len, char& v) break; case 2: // NUMERIC case 3: // DECIMAL + case -3: // VARBINARY type = TYPE_DECIM; break; case 4: // INTEGER @@ -139,7 +159,6 @@ int TranslateJDBCType(int stp, int prec, int& len, char& v) break; case 0: // NULL case -2: // BINARY - case -3: // VARBINARY case -4: // LONGVARBINARY default: type = TYPE_ERROR; @@ -155,42 +174,20 @@ int TranslateJDBCType(int stp, int prec, int& len, char& v) static JCATPARM *AllocCatInfo(PGLOBAL g, JCATINFO fid, char *db, char *tab, PQRYRES qrp) { - size_t m, n; JCATPARM *cap; #if defined(_DEBUG) assert(qrp); #endif - // Save stack and allocation environment and prepare error return - if (g->jump_level == MAX_JUMP) { - strcpy(g->Message, MSG(TOO_MANY_JUMPS)); - return NULL; - } // endif jump_level - - if (setjmp(g->jumper[++g->jump_level]) != 0) { - printf("%s\n", g->Message); - cap = NULL; - goto fin; - } // endif rc + if ((cap = (JCATPARM *)PlgDBSubAlloc(g, NULL, sizeof(JCATPARM)))) { + memset(cap, 0, sizeof(JCATPARM)); + cap->Id = fid; + cap->Qrp = qrp; + cap->DB = db; + cap->Tab = tab; + } // endif cap - m = (size_t)qrp->Maxres; - n = (size_t)qrp->Nbcol; - cap = (JCATPARM *)PlugSubAlloc(g, NULL, sizeof(JCATPARM)); - memset(cap, 0, sizeof(JCATPARM)); - cap->Id = fid; - cap->Qrp = qrp; - cap->DB = (PUCHAR)db; - cap->Tab = (PUCHAR)tab; -//cap->Vlen = (SQLLEN* *)PlugSubAlloc(g, NULL, n * sizeof(SQLLEN *)); - -//for (i = 0; i < n; i++) -// cap->Vlen[i] = (SQLLEN *)PlugSubAlloc(g, NULL, m * sizeof(SQLLEN)); - -//cap->Status = (UWORD *)PlugSubAlloc(g, NULL, m * sizeof(UWORD)); - -fin: - g->jump_level--; return cap; } // end of AllocCatInfo @@ -198,8 +195,8 @@ fin: /* JDBCColumns: constructs the result blocks containing all columns */ /* of a JDBC table that will be retrieved by GetData commands. */ /***********************************************************************/ -PQRYRES JDBCColumns(PGLOBAL g, char *jpath, char *db, char *table, - char *colpat, int maxres, bool info, PJPARM sjp) +PQRYRES JDBCColumns(PGLOBAL g, char *db, char *table, char *colpat, + int maxres, bool info, PJPARM sjp) { int buftyp[] = {TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_INT, TYPE_INT, @@ -221,7 +218,7 @@ PQRYRES JDBCColumns(PGLOBAL g, char *jpath, char *db, char *table, if (!info) { jcp = new(g)JDBConn(g, NULL); - if (jcp->Open(jpath, sjp) != RC_OK) // openReadOnly + noJDBCdialog + if (jcp->Open(sjp) != RC_OK) // openReadOnly + noJDBCdialog return NULL; if (table && !strchr(table, '%')) { @@ -272,7 +269,8 @@ PQRYRES JDBCColumns(PGLOBAL g, char *jpath, char *db, char *table, if (!(cap = AllocCatInfo(g, CAT_COL, db, table, qrp))) return NULL; - cap->Pat = (PUCHAR)colpat; + // Colpat cannot be null or empty for some drivers + cap->Pat = (colpat && *colpat) ? colpat : "%"; /************************************************************************/ /* Now get the results into blocks. */ @@ -300,22 +298,25 @@ PQRYRES JDBCColumns(PGLOBAL g, char *jpath, char *db, char *table, /* JDBCSrcCols: constructs the result blocks containing the */ /* description of all the columns of a Srcdef option. */ /**************************************************************************/ -PQRYRES JDBCSrcCols(PGLOBAL g, char *jpath, char *src, PJPARM sjp) +PQRYRES JDBCSrcCols(PGLOBAL g, char *src, PJPARM sjp) { + PQRYRES qrp; JDBConn *jcp = new(g)JDBConn(g, NULL); - if (jcp->Open(jpath, sjp)) + if (jcp->Open(sjp)) return NULL; - return jcp->GetMetaData(g, src); + qrp = jcp->GetMetaData(g, src); + jcp->Close(); + return qrp; } // end of JDBCSrcCols /**************************************************************************/ /* JDBCTables: constructs the result blocks containing all tables in */ /* an JDBC database that will be retrieved by GetData commands. */ /**************************************************************************/ -PQRYRES JDBCTables(PGLOBAL g, char *jpath, char *db, char *tabpat, - char *tabtyp, int maxres, bool info, PJPARM sjp) +PQRYRES JDBCTables(PGLOBAL g, char *db, char *tabpat, char *tabtyp, + int maxres, bool info, PJPARM sjp) { int buftyp[] = {TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_STRING}; @@ -337,7 +338,7 @@ PQRYRES JDBCTables(PGLOBAL g, char *jpath, char *db, char *tabpat, /**********************************************************************/ jcp = new(g)JDBConn(g, NULL); - if (jcp->Open(jpath, sjp) == RC_FX) + if (jcp->Open(sjp) == RC_FX) return NULL; if (!maxres) @@ -345,14 +346,14 @@ PQRYRES JDBCTables(PGLOBAL g, char *jpath, char *db, char *tabpat, n = jcp->GetMaxValue(2); // Max catalog name length - if (n < 0) - return NULL; +// if (n < 0) +// return NULL; - length[0] = (n) ? (n + 1) : 0; + length[0] = (n > 0) ? (n + 1) : 0; n = jcp->GetMaxValue(3); // Max schema name length - length[1] = (n) ? (n + 1) : 0; + length[1] = (n > 0) ? (n + 1) : 0; n = jcp->GetMaxValue(4); // Max table name length - length[2] = (n) ? (n + 1) : 128; + length[2] = (n > 0) ? (n + 1) : 128; } else { maxres = 0; length[0] = 128; @@ -380,7 +381,7 @@ PQRYRES JDBCTables(PGLOBAL g, char *jpath, char *db, char *tabpat, if (!(cap = AllocCatInfo(g, CAT_TAB, db, tabpat, qrp))) return NULL; - cap->Pat = (PUCHAR)tabtyp; + cap->Pat = tabtyp; if (trace) htrc("Getting table results ncol=%d\n", cap->Qrp->Nbcol); @@ -414,7 +415,7 @@ PQRYRES JDBCTables(PGLOBAL g, char *jpath, char *db, char *tabpat, /* drivers available on the local host. */ /* Called with info=true to have result column names. */ /*************************************************************************/ -PQRYRES JDBCDrivers(PGLOBAL g, char *jpath, int maxres, bool info) +PQRYRES JDBCDrivers(PGLOBAL g, int maxres, bool info) { int buftyp[] ={TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_STRING}; XFLD fldtyp[] ={FLD_NAME, FLD_EXTRA, FLD_DEFAULT, FLD_REM }; @@ -431,7 +432,7 @@ PQRYRES JDBCDrivers(PGLOBAL g, char *jpath, int maxres, bool info) if (!info) { jcp = new(g) JDBConn(g, NULL); - if (jcp->Open(jpath, NULL) != RC_OK) + if (jcp->Open(NULL) != RC_OK) return NULL; if (!maxres) @@ -613,90 +614,6 @@ PQRYRES JDBCPrimaryKeys(PGLOBAL g, JDBConn *op, char *dsn, char *table) /************************************************************************/ return qrp; } // end of JDBCPrimaryKeys - -/**************************************************************************/ -/* Statistics: constructs the result blocks containing statistics */ -/* about one or several tables to be retrieved by GetData commands. */ -/**************************************************************************/ -PQRYRES JDBCStatistics(PGLOBAL g, JDBConn *op, char *dsn, char *pat, - int un, int acc) -{ - static int buftyp[] ={ TYPE_STRING, - TYPE_STRING, TYPE_STRING, TYPE_SHORT, TYPE_STRING, - TYPE_STRING, TYPE_SHORT, TYPE_SHORT, TYPE_STRING, - TYPE_STRING, TYPE_INT, TYPE_INT, TYPE_STRING }; - static unsigned int length[] ={ 0, 0, 0, 6, 0, 0, 6, 6, 0, 2, 10, 10, 128 }; - int n, ncol = 13; - int maxres; - PQRYRES qrp; - JCATPARM *cap; - JDBConn *jcp = op; - - if (!op) { - /**********************************************************************/ - /* Open the connection with the JDBC data source. */ - /**********************************************************************/ - jcp = new(g)JDBConn(g, NULL); - - if (jcp->Open(dsn, 2) < 1) // 2 is openReadOnly - return NULL; - - } // endif op - - /************************************************************************/ - /* Do an evaluation of the result size. */ - /************************************************************************/ - n = 1 + jcp->GetMaxValue(SQL_MAX_COLUMNS_IN_INDEX); - maxres = (n) ? (int)n : 32; - n = jcp->GetMaxValue(SQL_MAX_SCHEMA_NAME_LEN); - length[1] = (n) ? (n + 1) : 128; - n = jcp->GetMaxValue(SQL_MAX_TABLE_NAME_LEN); - length[2] = length[5] = (n) ? (n + 1) : 128; - n = jcp->GetMaxValue(SQL_MAX_CATALOG_NAME_LEN); - length[0] = length[4] = (n) ? (n + 1) : length[2]; - n = jcp->GetMaxValue(SQL_MAX_COLUMN_NAME_LEN); - length[7] = (n) ? (n + 1) : 128; - - if (trace) - htrc("SemStatistics: max=%d pat=%s\n", maxres, SVP(pat)); - - /************************************************************************/ - /* Allocate the structure used to refer to the result set. */ - /************************************************************************/ - qrp = PlgAllocResult(g, ncol, maxres, IDS_STAT, - buftyp, NULL, length, false, true); - - if (trace) - htrc("Getting stat results ncol=%d\n", qrp->Nbcol); - - cap = AllocCatInfo(g, CAT_STAT, NULL, pat, qrp); - cap->Unique = (un < 0) ? SQL_INDEX_UNIQUE : (UWORD)un; - cap->Accuracy = (acc < 0) ? SQL_QUICK : (UWORD)acc; - - /************************************************************************/ - /* Now get the results into blocks. */ - /************************************************************************/ - if ((n = jcp->GetCatInfo(cap)) >= 0) { - qrp->Nblin = n; - // ResetNullValues(cap); - - if (trace) - htrc("Statistics: NBCOL=%d NBLIN=%d\n", qrp->Nbcol, qrp->Nblin); - - } else - qrp = NULL; - - /************************************************************************/ - /* Close any local connection. */ - /************************************************************************/ - if (!op) - jcp->Close(); - - /************************************************************************/ - /* Return the result pointer for use by GetData routines. */ - /************************************************************************/ - return qrp; -} // end of Statistics #endif // 0 /***********************************************************************/ @@ -708,13 +625,15 @@ JDBConn::JDBConn(PGLOBAL g, TDBJDBC *tdbp) m_Tdb = tdbp; jvm = nullptr; // Pointer to the JVM (Java Virtual Machine) env= nullptr; // Pointer to native interface - jdi = nullptr; // Pointer to the JdbcInterface class - job = nullptr; // The JdbcInterface class object - xqid = xuid = xid = grs = readid = fetchid = typid = nullptr; + jdi = nullptr; // Pointer to the java wrapper class + job = nullptr; // The java wrapper class object + xqid = xuid = xid = grs = readid = fetchid = typid = errid = nullptr; prepid = xpid = pcid = nullptr; + chrfldid = intfldid = dblfldid = fltfldid = datfldid = bigfldid = nullptr; //m_LoginTimeout = DEFAULT_LOGIN_TIMEOUT; //m_QueryTimeout = DEFAULT_QUERY_TIMEOUT; //m_UpdateOptions = 0; + Msg = NULL; m_Driver = NULL; m_Url = NULL; m_User = NULL; @@ -741,33 +660,57 @@ JDBConn::JDBConn(PGLOBAL g, TDBJDBC *tdbp) // } // end of ~JDBConn -#if 0 /***********************************************************************/ /* Screen for errors. */ /***********************************************************************/ -bool JDBConn::Check(RETCODE rc) +bool JDBConn::Check(jint rc) { - switch (rc) { - case SQL_SUCCESS_WITH_INFO: - if (trace) { - DJX x(rc); - - if (x.BuildErrorMessage(this, m_hstmt)) - htrc("JDBC Success With Info, hstmt=%p %s\n", - m_hstmt, x.GetErrorMessage(0)); + jstring s; - } // endif trace + if (env->ExceptionCheck()) { + jthrowable exc = env->ExceptionOccurred(); + jmethodID tid = env->GetMethodID(env->FindClass("java/lang/Object"), + "toString", "()Ljava/lang/String;"); + + if (exc != nullptr && tid != nullptr) { + jstring s = (jstring)env->CallObjectMethod(exc, tid); + const char *utf = env->GetStringUTFChars(s, (jboolean)false); + env->DeleteLocalRef(s); + Msg = PlugDup(m_G, utf); + } else + Msg = "Exception occured"; - // Fall through - case SQL_SUCCESS: - case SQL_NO_DATA_FOUND: - return true; - } // endswitch rc + env->ExceptionClear(); + } else if (rc < 0) { + s = (jstring)env->CallObjectMethod(job, errid); + Msg = (char*)env->GetStringUTFChars(s, (jboolean)false); + } else + Msg = NULL; - return false; + return (Msg != NULL); } // end of Check /***********************************************************************/ +/* Get MethodID if not exists yet. */ +/***********************************************************************/ +bool JDBConn::gmID(PGLOBAL g, jmethodID& mid, const char *name, const char *sig) +{ + if (mid == nullptr) { + mid = env->GetMethodID(jdi, name, sig); + + if (Check()) { + strcpy(g->Message, Msg); + return true; + } else + return false; + + } else + return false; + +} // end of gmID + +#if 0 +/***********************************************************************/ /* Utility routine. */ /***********************************************************************/ PSZ JDBConn::GetStringInfo(ushort infotype) @@ -825,132 +768,297 @@ void JDBConn::OnSetOptions(HSTMT hstmt) /***********************************************************************/ int JDBConn::GetMaxValue(int n) { - jmethodID maxid = env->GetMethodID(jdi, "GetMaxValue", "(I)I"); + jint m; + jmethodID maxid = nullptr; - if (maxid == nullptr) { - strcpy(m_G->Message, "ERROR: method GetMaxValue not found !"); + if (gmID(m_G, maxid, "GetMaxValue", "(I)I")) return -1; - } // endif maxid // call method - return (int)env->CallIntMethod(job, maxid, n); + if (Check(m = env->CallIntMethod(job, maxid, n))) + htrc("GetMaxValue: %s", Msg); + + return (int)m; } // end of GetMaxValue /***********************************************************************/ -/* Open: connect to a data source. */ +/* Reset the JVM library. */ /***********************************************************************/ -int JDBConn::Open(PSZ jpath, PJPARM sop) +void JDBConn::ResetJVM(void) { - PGLOBAL& g = m_G; - PSTRG jpop = new(g) STRING(g, 512, "-Djava.class.path="); - char sep; + if (LibJvm) { +#if defined(__WIN__) + FreeLibrary((HMODULE)LibJvm); +#else // !__WIN__ + dlclose(LibJvm); +#endif // !__WIN__ + LibJvm = NULL; + CreateJavaVM = NULL; + GetCreatedJavaVMs = NULL; +#if defined(_DEBUG) + GetDefaultJavaVMInitArgs = NULL; +#endif // _DEBUG + } // endif LibJvm + +} // end of ResetJVM + +/***********************************************************************/ +/* Dynamically link the JVM library. */ +/* The purpose of this function is to allow using the CONNECT plugin */ +/* for other table types when the Java JDK is not installed. */ +/***********************************************************************/ +bool JDBConn::GetJVM(PGLOBAL g) +{ + if (!LibJvm) { + char soname[512]; #if defined(__WIN__) - sep = ';'; -#else - sep = ':'; -#endif + if (JvmPath) + strcat(strcpy(soname, JvmPath), "\\jvm.dll"); + else + strcpy(soname, "jvm.dll"); + + // Load the desired shared library + if (!(LibJvm = LoadLibrary(soname))) { + char buf[256]; + DWORD rc = GetLastError(); + + sprintf(g->Message, MSG(DLL_LOAD_ERROR), rc, soname); + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, NULL, rc, 0, + (LPTSTR)buf, sizeof(buf), NULL); + strcat(strcat(g->Message, ": "), buf); + } else if (!(CreateJavaVM = (CRTJVM)GetProcAddress((HINSTANCE)LibJvm, + "JNI_CreateJavaVM"))) { + sprintf(g->Message, MSG(PROCADD_ERROR), GetLastError(), "JNI_CreateJavaVM"); + FreeLibrary((HMODULE)LibJvm); + LibJvm = NULL; + } else if (!(GetCreatedJavaVMs = (GETJVM)GetProcAddress((HINSTANCE)LibJvm, + "JNI_GetCreatedJavaVMs"))) { + sprintf(g->Message, MSG(PROCADD_ERROR), GetLastError(), "JNI_GetCreatedJavaVMs"); + FreeLibrary((HMODULE)LibJvm); + LibJvm = NULL; +#if defined(_DEBUG) + } else if (!(GetDefaultJavaVMInitArgs = (GETDEF)GetProcAddress((HINSTANCE)LibJvm, + "JNI_GetDefaultJavaVMInitArgs"))) { + sprintf(g->Message, MSG(PROCADD_ERROR), GetLastError(), + "JNI_GetDefaultJavaVMInitArgs"); + FreeLibrary((HMODULE)LibJvm); + LibJvm = NULL; +#endif // _DEBUG + } // endif LibJvm +#else // !__WIN__ + const char *error = NULL; + + if (JvmPath) + strcat(strcpy(soname, JvmPath), "/libjvm.so"); + else + strcpy(soname, "libjvm.so"); + + // Load the desired shared library + if (!(LibJvm = dlopen(soname, RTLD_LAZY))) { + error = dlerror(); + sprintf(g->Message, MSG(SHARED_LIB_ERR), soname, SVP(error)); + } else if (!(CreateJavaVM = (CRTJVM)dlsym(LibJvm, "JNI_CreateJavaVM"))) { + error = dlerror(); + sprintf(g->Message, MSG(GET_FUNC_ERR), "JNI_CreateJavaVM", SVP(error)); + dlclose(LibJvm); + LibJvm = NULL; + } else if (!(GetCreatedJavaVMs = (GETJVM)dlsym(LibJvm, "JNI_GetCreatedJavaVMs"))) { + error = dlerror(); + sprintf(g->Message, MSG(GET_FUNC_ERR), "JNI_GetCreatedJavaVMs", SVP(error)); + dlclose(LibJvm); + LibJvm = NULL; +#if defined(_DEBUG) + } else if (!(GetDefaultJavaVMInitArgs = (GETDEF)dlsym(LibJvm, + "JNI_GetDefaultJavaVMInitArgs"))) { + error = dlerror(); + sprintf(g->Message, MSG(GET_FUNC_ERR), "JNI_GetDefaultJavaVMInitArgs", SVP(error)); + dlclose(LibJvm); + LibJvm = NULL; +#endif // _DEBUG + } // endif LibJvm +#endif // !__WIN__ - if (sop) { - m_Driver = sop->Driver; - m_Url = sop->Url; - m_User = sop->User; - m_Pwd = sop->Pwd; - m_Scrollable = sop->Scrollable; - m_RowsetSize = sop->Fsize; - //m_LoginTimeout = sop->Cto; - //m_QueryTimeout = sop->Qto; - //m_UseCnc = sop->UseCnc; - } // endif sop - - //================== prepare loading of Java VM ============================ - JavaVMInitArgs vm_args; // Initialization arguments - JavaVMOption* options = new JavaVMOption[1]; // JVM invocation options - - // where to find java .class - jpop->Append(getenv("CLASSPATH")); - - if (jpath) { - jpop->Append(sep); - jpop->Append(jpath); - } // endif jpath + } // endif LibJvm - options[0].optionString = jpop->GetStr(); -//options[1].optionString = "-verbose:jni"; - vm_args.version = JNI_VERSION_1_6; // minimum Java version - vm_args.nOptions = 1; // number of options - vm_args.options = options; - vm_args.ignoreUnrecognized = false; // invalid options make the JVM init fail + return LibJvm == NULL; +} // end of GetJVM - //=============== load and initialize Java VM and JNI interface ============= - jint rc = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args); // YES !! - delete options; // we then no longer need the initialisation options. +/***********************************************************************/ +/* Open: connect to a data source. */ +/***********************************************************************/ +int JDBConn::Open(PJPARM sop) +{ + bool err = false; + PGLOBAL& g = m_G; - switch (rc) { - case JNI_OK: - strcpy(g->Message, "VM successfully created"); - break; - case JNI_ERR: - strcpy(g->Message, "Initialising JVM failed: unknown error"); - return RC_FX; - case JNI_EDETACHED: - strcpy(g->Message, "Thread detached from the VM"); - return RC_FX; - case JNI_EVERSION: - strcpy(g->Message, "JNI version error"); - return RC_FX; - case JNI_ENOMEM: - strcpy(g->Message, "Not enough memory"); + // Link or check whether jvm library was linked + if (GetJVM(g)) return RC_FX; - case JNI_EEXIST: - strcpy(g->Message, "VM already created"); - { - JavaVM* jvms[1]; - jsize jsz; - rc = JNI_GetCreatedJavaVMs(jvms, 1, &jsz); + // Firstly check whether the jvm was already created + JavaVM* jvms[1]; + jsize jsz; + jint rc = GetCreatedJavaVMs(jvms, 1, &jsz); - if (rc == JNI_OK && jsz == 1) { - JavaVMAttachArgs args; + if (rc == JNI_OK && jsz == 1) { + // jvm already existing + jvm = jvms[0]; + rc = jvm->AttachCurrentThread((void**)&env, nullptr); - args.version = JNI_VERSION_1_6; - args.name = NULL; - args.group = NULL; - jvm = jvms[0]; - rc = jvm->AttachCurrentThread((void**)&env, &args); - } // endif rc - } // end of block + if (rc != JNI_OK) { + strcpy(g->Message, "Cannot attach jvm to the current thread"); + return RC_FX; + } // endif rc - if (rc == JNI_OK) + } else { + /*******************************************************************/ + /* Create a new jvm */ + /*******************************************************************/ + PSTRG jpop = new(g)STRING(g, 512, "-Djava.class.path=."); + char *cp = NULL; + char sep; + +#if defined(__WIN__) + sep = ';'; +#define N 1 +//#define N 2 +//#define N 3 +#else + sep = ':'; +#define N 1 +#endif + + //================== prepare loading of Java VM ============================ + JavaVMInitArgs vm_args; // Initialization arguments + JavaVMOption* options = new JavaVMOption[N]; // JVM invocation options + + // where to find java .class + if (ClassPath && *ClassPath) { + jpop->Append(sep); + jpop->Append(ClassPath); + } // endif ClassPath + + if ((cp = getenv("CLASSPATH"))) { + jpop->Append(sep); + jpop->Append(cp); + } // endif cp + + if (trace) { + htrc("ClassPath=%s\n", ClassPath); + htrc("CLASSPATH=%s\n", cp); + htrc("%s\n", jpop->GetStr()); + } // endif trace + + options[0].optionString = jpop->GetStr(); +#if N == 2 + options[1].optionString = "-Xcheck:jni"; +#endif +#if N == 3 + options[1].optionString = "-Xms256M"; + options[2].optionString = "-Xmx512M"; +#endif +#if defined(_DEBUG) + vm_args.version = JNI_VERSION_1_2; // minimum Java version + rc = GetDefaultJavaVMInitArgs(&vm_args); +#else + vm_args.version = JNI_VERSION_1_6; // minimum Java version +#endif // _DEBUG + vm_args.nOptions = N; // number of options + vm_args.options = options; + vm_args.ignoreUnrecognized = false; // invalid options make the JVM init fail + + //=============== load and initialize Java VM and JNI interface ============= + rc = CreateJavaVM(&jvm, (void**)&env, &vm_args); // YES !! + delete options; // we then no longer need the initialisation options. + + switch (rc) { + case JNI_OK: + strcpy(g->Message, "VM successfully created"); break; - else + case JNI_ERR: + strcpy(g->Message, "Initialising JVM failed: unknown error"); + return RC_FX; + case JNI_EDETACHED: + strcpy(g->Message, "Thread detached from the VM"); + return RC_FX; + case JNI_EVERSION: + strcpy(g->Message, "JNI version error"); return RC_FX; + case JNI_ENOMEM: + strcpy(g->Message, "Not enough memory"); + return RC_FX; + case JNI_EEXIST: + strcpy(g->Message, "VM already created"); + return RC_FX; + case JNI_EINVAL: + strcpy(g->Message, "Invalid arguments"); + return RC_FX; + default: + sprintf(g->Message, "Unknown return code %d", rc); + return RC_FX; + } // endswitch rc - case JNI_EINVAL: - strcpy(g->Message, "Invalid arguments"); - return RC_FX; - default: - sprintf(g->Message, "Unknown return code %d", rc); - return RC_FX; - } // endswitch rc + } // endif rc //=============== Display JVM version ======================================= -//jint ver = env->GetVersion(); -//cout << ((ver>>16)&0x0f) << "."<<(ver&0x0f) << endl; +#if defined(_DEBUG) + jint ver = env->GetVersion(); + printf("JVM Version %d.%d\n", ((ver>>16)&0x0f), (ver&0x0f)); +#endif //_DEBUG - // try to find the JdbcInterface class - jdi = env->FindClass("JdbcInterface"); + // try to find the java wrapper class + jdi = env->FindClass(Wrapper); if (jdi == nullptr) { - strcpy(g->Message, "ERROR: class JdbcInterface not found !"); + sprintf(g->Message, "ERROR: class %s not found!", Wrapper); return RC_FX; } // endif jdi +#if 0 // Suppressed because it does not make any usable change + if (b && jpath && *jpath) { + // Try to add that path the the jvm class path + jmethodID alp = env->GetStaticMethodID(jdi, "addLibraryPath", + "(Ljava/lang/String;)I"); + + if (alp == nullptr) { + env->ExceptionDescribe(); + env->ExceptionClear(); + } else { + char *msg; + jstring path = env->NewStringUTF(jpath); + rc = env->CallStaticIntMethod(jdi, alp, path); + + if ((msg = Check(rc))) { + strcpy(g->Message, msg); + env->DeleteLocalRef(path); + return RC_FX; + } else switch (rc) { + case JNI_OK: + printf("jpath added\n"); + break; + case JNI_EEXIST: + printf("jpath already exist\n"); + break; + case JNI_ERR: + default: + strcpy(g->Message, "Error adding jpath"); + env->DeleteLocalRef(path); + return RC_FX; + } // endswitch rc + + env->DeleteLocalRef(path); + } // endif alp + + } // endif jpath +#endif // 0 + // if class found, continue jmethodID ctor = env->GetMethodID(jdi, "<init>", "()V"); if (ctor == nullptr) { - strcpy(g->Message, "ERROR: JdbcInterface constructor not found !"); + sprintf(g->Message, "ERROR: %s constructor not found!", Wrapper); return RC_FX; } else job = env->NewObject(jdi, ctor); @@ -959,26 +1067,41 @@ int JDBConn::Open(PSZ jpath, PJPARM sop) // we can then search for the method we want to call, // and invoke it for the object: if (job == nullptr) { - strcpy(g->Message, "JdbcInterface class object not constructed !"); + sprintf(g->Message, "%s class object not constructed!", Wrapper); return RC_FX; } // endif job - if (!sop) // DRIVER catalog table - return RC_OK; - - jmethodID cid = env->GetMethodID(jdi, "JdbcConnect", "([Ljava/lang/String;IZ)I"); + errid = env->GetMethodID(jdi, "GetErrmsg", "()Ljava/lang/String;"); if (env->ExceptionCheck()) { - strcpy(g->Message, "ERROR: method JdbcConnect() not found!"); + strcpy(g->Message, "ERROR: method GetErrmsg() not found!"); env->ExceptionDescribe(); env->ExceptionClear(); return RC_FX; } // endif Check + if (!sop) // DRIVER catalog table + return RC_OK; + + jmethodID cid = nullptr; + + if (gmID(g, cid, "JdbcConnect", "([Ljava/lang/String;IZ)I")) + return RC_FX; + // Build the java string array jobjectArray parms = env->NewObjectArray(4, // constructs java array of 4 env->FindClass("java/lang/String"), NULL); // Strings + m_Driver = sop->Driver; + m_Url = sop->Url; + m_User = sop->User; + m_Pwd = sop->Pwd; + m_Scrollable = sop->Scrollable; + m_RowsetSize = sop->Fsize; + //m_LoginTimeout = sop->Cto; + //m_QueryTimeout = sop->Qto; + //m_UseCnc = sop->UseCnc; + // change some elements if (m_Driver) env->SetObjectArrayElement(parms, 0, env->NewStringUTF(m_Driver)); @@ -994,23 +1117,17 @@ int JDBConn::Open(PSZ jpath, PJPARM sop) // call method rc = env->CallIntMethod(job, cid, parms, m_RowsetSize, m_Scrollable); + err = Check(rc); + env->DeleteLocalRef(parms); // Not used anymore - // Not used anymore - env->DeleteLocalRef(parms); - - if (rc != (jint)0) { - strcpy(g->Message, "Connection failed"); + if (err) { + sprintf(g->Message, "Connecting: %s rc=%d", Msg, (int)rc); return RC_FX; - } // endif rc + } // endif Msg - typid = env->GetMethodID(jdi, "ColumnType", "(ILjava/lang/String;)I"); - - if (env->ExceptionCheck()) { - strcpy(g->Message, "ERROR: method ColumnType() not found!"); - env->ExceptionDescribe(); - env->ExceptionClear(); + if (gmID(g, typid, "ColumnType", "(ILjava/lang/String;)I")) return RC_FX; - } else + else m_Opened = true; return RC_OK; @@ -1021,43 +1138,37 @@ int JDBConn::Open(PSZ jpath, PJPARM sop) /***********************************************************************/ int JDBConn::ExecSQLcommand(char *sql) { - int rc = RC_NF; + int rc; jint n; jstring qry; PGLOBAL& g = m_G; - if (xid == nullptr) { - // Get the methods used to execute a query and get the result - xid = env->GetMethodID(jdi, "Execute", "(Ljava/lang/String;)I"); - - if (xid == nullptr) { - strcpy(g->Message, "Cannot find method Execute"); - return RC_FX; - } else - grs = env->GetMethodID(jdi, "GetResult", "()I"); - - if (grs == nullptr) { - strcpy(g->Message, "Cannot find method GetResult"); - return RC_FX; - } // endif grs - - } // endif xid + // Get the methods used to execute a query and get the result + if (gmID(g, xid, "Execute", "(Ljava/lang/String;)I") || + gmID(g, grs, "GetResult", "()I")) + return RC_FX; qry = env->NewStringUTF(sql); n = env->CallIntMethod(job, xid, qry); env->DeleteLocalRef(qry); - if (n < 0) { - sprintf(g->Message, "Error executing %s", sql); + if (Check(n)) { + sprintf(g->Message, "Execute: %s", Msg); return RC_FX; } // endif n - if ((m_Ncol = env->CallIntMethod(job, grs))) { + m_Ncol = env->CallIntMethod(job, grs); + + if (Check(m_Ncol)) { + sprintf(g->Message, "GetResult: %s", Msg); + rc = RC_FX; + } else if (m_Ncol) { strcpy(g->Message, "Result set column number"); rc = RC_OK; // A result set was returned } else { m_Aff = (int)n; // Affected rows strcpy(g->Message, "Affected rows"); + rc = RC_NF; } // endif ncol return rc; @@ -1068,44 +1179,29 @@ int JDBConn::ExecSQLcommand(char *sql) /***********************************************************************/ int JDBConn::Fetch(int pos) { - jint rc; + jint rc = JNI_ERR; + PGLOBAL& g = m_G; if (m_Full) // Result set has one row return 1; if (pos) { if (!m_Scrollable) { - strcpy(m_G->Message, "Cannot fetch(pos) if FORWARD ONLY"); - return -1; - } else if (fetchid == nullptr) { - fetchid = env->GetMethodID(jdi, "Fetch", "(I)Z"); - - if (fetchid == nullptr) { - strcpy(m_G->Message, "Cannot find method Fetch"); - return -1; - } // endif fetchid - - } // endif's + strcpy(g->Message, "Cannot fetch(pos) if FORWARD ONLY"); + return rc; + } else if (gmID(m_G, fetchid, "Fetch", "(I)Z")) + return rc; if (env->CallBooleanMethod(job, fetchid, pos)) rc = m_Rows; - else - rc = -1; } else { - if (readid == nullptr) { - readid = env->GetMethodID(jdi, "ReadNext", "()I"); - - if (readid == nullptr) { - strcpy(m_G->Message, "Cannot find method ReadNext"); - return -1; - } // endif readid - - } // endif readid + if (gmID(g, readid, "ReadNext", "()I")) + return rc; rc = env->CallBooleanMethod(job, readid); - if (rc >= 0) { + if (!Check(rc)) { if (rc == 0) m_Full = (m_Fetch == 1); else @@ -1113,7 +1209,7 @@ int JDBConn::Fetch(int pos) m_Rows += (int)rc; } else - strcpy(m_G->Message, "Error fetching next row"); + sprintf(g->Message, "Fetch: %s", Msg); } // endif pos @@ -1130,15 +1226,8 @@ int JDBConn::Rewind(char *sql) if (m_Full) rbuf = m_Rows; // No need to "rewind" else if (m_Scrollable) { - if (fetchid == nullptr) { - fetchid = env->GetMethodID(jdi, "Fetch", "(I)Z"); - - if (fetchid == nullptr) { - strcpy(m_G->Message, "Cannot find method Fetch"); - return -1; - } // endif readid - - } // endif readid + if (gmID(m_G, fetchid, "Fetch", "(I)Z")) + return -1; jboolean b = env->CallBooleanMethod(job, fetchid, 0); @@ -1156,14 +1245,16 @@ void JDBConn::Close() { if (m_Opened) { jint rc; - jmethodID did = env->GetMethodID(jdi, "JdbcDisconnect", "()I"); + jmethodID did = nullptr; - if (did == nullptr) - printf("ERROR: method JdbcDisconnect() not found !"); - else - rc = env->CallIntMethod(job, did); + if (gmID(m_G, did, "JdbcDisconnect", "()I")) + printf("%s\n", Msg); + else if (Check(env->CallIntMethod(job, did))) + printf("jdbcDisconnect: %s\n", Msg); + + if ((rc = jvm->DetachCurrentThread()) != JNI_OK) + printf("DetachCurrentThread: rc=%d\n", (int)rc); - rc = jvm->DetachCurrentThread(); //rc = jvm->DestroyJavaVM(); m_Opened = false; } // endif m_Opened @@ -1180,8 +1271,6 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val) jlong dtv; jstring cn, jn = nullptr; jobject dob; - jthrowable exc; - jmethodID fldid = nullptr; if (rank == 0) if (!name || (jn = env->NewStringUTF(name)) == nullptr) { @@ -1189,16 +1278,11 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val) longjmp(g->jumper[g->jump_level], TYPE_AM_JDBC); } // endif name + // Returns 666 is case of error ctyp = env->CallIntMethod(job, typid, rank, jn); - if ((exc = env->ExceptionOccurred()) != nullptr) { - jboolean isCopy = false; - jmethodID tid = env->GetMethodID(env->FindClass("java/lang/Object"), "toString", "()Ljava/lang/String;"); - jstring s = (jstring)env->CallObjectMethod(exc, tid); - const char* utf = env->GetStringUTFChars(s, &isCopy); - sprintf(g->Message, "SetColumnValue: %s", utf); - env->DeleteLocalRef(s); - env->ExceptionClear(); + if (Check((ctyp == 666) ? -1 : 1)) { + sprintf(g->Message, "Getting ctyp: %s", Msg); longjmp(g->jumper[g->jump_level], TYPE_AM_JDBC); } // endif Check @@ -1206,11 +1290,8 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val) case 12: // VARCHAR case -1: // LONGVARCHAR case 1: // CHAR - fldid = env->GetMethodID(jdi, "StringField", - "(ILjava/lang/String;)Ljava/lang/String;"); - - if (fldid != nullptr) { - cn = (jstring)env->CallObjectMethod(job, fldid, (jint)rank, jn); + if (!gmID(g, chrfldid, "StringField", "(ILjava/lang/String;)Ljava/lang/String;")) { + cn = (jstring)env->CallObjectMethod(job, chrfldid, (jint)rank, jn); if (cn) { const char *field = env->GetStringUTFChars(cn, (jboolean)false); @@ -1227,30 +1308,26 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val) case 4: // INTEGER case 5: // SMALLINT case -6: // TINYINT - fldid = env->GetMethodID(jdi, "IntField", "(ILjava/lang/String;)I"); - - if (fldid != nullptr) - val->SetValue((int)env->CallIntMethod(job, fldid, rank, jn)); + case -7: // BIT + if (!gmID(g, intfldid, "IntField", "(ILjava/lang/String;)I")) + val->SetValue((int)env->CallIntMethod(job, intfldid, rank, jn)); else val->Reset(); break; case 8: // DOUBLE + case 2: // NUMERIC case 3: // DECIMAL - fldid = env->GetMethodID(jdi, "DoubleField", "(ILjava/lang/String;)D"); - - if (fldid != nullptr) - val->SetValue((double)env->CallDoubleMethod(job, fldid, rank, jn)); + if (!gmID(g, dblfldid, "DoubleField", "(ILjava/lang/String;)D")) + val->SetValue((double)env->CallDoubleMethod(job, dblfldid, rank, jn)); else val->Reset(); break; case 7: // REAL case 6: // FLOAT - fldid = env->GetMethodID(jdi, "FloatField", "(ILjava/lang/String;)F"); - - if (fldid != nullptr) - val->SetValue((float)env->CallFloatMethod(job, fldid, rank, jn)); + if (!gmID(g, fltfldid, "FloatField", "(ILjava/lang/String;)F")) + val->SetValue((float)env->CallFloatMethod(job, fltfldid, rank, jn)); else val->Reset(); @@ -1258,11 +1335,9 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val) case 91: // DATE case 92: // TIME case 93: // TIMESTAMP - fldid = env->GetMethodID(jdi, "TimestampField", - "(ILjava/lang/String;)Ljava/sql/Timestamp;"); - - if (fldid != nullptr) { - dob = env->CallObjectMethod(job, fldid, (jint)rank, jn); + if (!gmID(g, datfldid, "TimestampField", + "(ILjava/lang/String;)Ljava/sql/Timestamp;")) { + dob = env->CallObjectMethod(job, datfldid, (jint)rank, jn); if (dob) { jclass jts = env->FindClass("java/sql/Timestamp"); @@ -1288,10 +1363,8 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val) break; case -5: // BIGINT - fldid = env->GetMethodID(jdi, "BigintField", "(ILjava/lang/String;)J"); - - if (fldid != nullptr) - val->SetValue((long long)env->CallLongMethod(job, fldid, (jint)rank, jn)); + if (!gmID(g, bigfldid, "BigintField", "(ILjava/lang/String;)J")) + val->SetValue((long long)env->CallLongMethod(job, bigfldid, (jint)rank, jn)); else val->Reset(); @@ -1301,10 +1374,21 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val) break; case java.sql.Types.BOOLEAN: System.out.print(jdi.BooleanField(i)); */ + case 0: // NULL + val->SetNull(true); + // passthru default: val->Reset(); } // endswitch Type + if (Check()) { + if (rank == 0) + env->DeleteLocalRef(jn); + + sprintf(g->Message, "SetColumnValue: %s rank=%d ctyp=%d", Msg, rank, (int)ctyp); + longjmp(g->jumper[g->jump_level], TYPE_AM_JDBC); + } // endif Check + if (rank == 0) env->DeleteLocalRef(jn); @@ -1315,21 +1399,22 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val) /***********************************************************************/ bool JDBConn::PrepareSQL(char *sql) { - if (prepid == nullptr) { - prepid = env->GetMethodID(jdi, "CreatePrepStmt", "(Ljava/lang/String;)Z"); + bool b = true; + PGLOBAL& g = m_G; - if (prepid == nullptr) { - strcpy(m_G->Message, "Cannot find method CreatePrepStmt"); - return true; - } // endif prepid + if (!gmID(g, prepid, "CreatePrepStmt", "(Ljava/lang/String;)I")) { + // Create the prepared statement + jstring qry = env->NewStringUTF(sql); + + if (Check(env->CallBooleanMethod(job, prepid, qry))) + sprintf(g->Message, "CreatePrepStmt: %s", Msg); + else + b = false; + env->DeleteLocalRef(qry); } // endif prepid - - // Create the prepared statement - jstring qry = env->NewStringUTF(sql); - jboolean b = env->CallBooleanMethod(job, prepid, qry); - env->DeleteLocalRef(qry); - return (bool)b; + + return b; } // end of PrepareSQL /***********************************************************************/ @@ -1337,34 +1422,27 @@ bool JDBConn::PrepareSQL(char *sql) /***********************************************************************/ int JDBConn::ExecuteQuery(char *sql) { + int rc = RC_FX; jint ncol; jstring qry; PGLOBAL& g = m_G; - if (xqid == nullptr) { - // Get the methods used to execute a query and get the result - xqid = env->GetMethodID(jdi, "ExecuteQuery", "(Ljava/lang/String;)I"); + // Get the methods used to execute a query and get the result + if (!gmID(g, xqid, "ExecuteQuery", "(Ljava/lang/String;)I")) { + qry = env->NewStringUTF(sql); + ncol = env->CallIntMethod(job, xqid, qry); - if (xqid == nullptr) { - strcpy(g->Message, "Cannot find method ExecuteQuery"); - return RC_FX; - } // endif !xqid - - } // endif xqid - - qry = env->NewStringUTF(sql); - ncol = env->CallIntMethod(job, xqid, qry); - env->DeleteLocalRef(qry); + if (!Check(ncol)) { + m_Ncol = (int)ncol; + m_Aff = 0; // Affected rows + rc = RC_OK; + } else + sprintf(g->Message, "ExecuteQuery: %s", Msg); - if (ncol < 0) { - sprintf(g->Message, "Error executing %s: ncol = %d", sql, ncol); - return RC_FX; - } else { - m_Ncol = (int)ncol; - m_Aff = 0; // Affected rows - } // endif ncol + env->DeleteLocalRef(qry); + } // endif xqid - return RC_OK; + return rc; } // end of ExecuteQuery /***********************************************************************/ @@ -1372,34 +1450,27 @@ int JDBConn::ExecuteQuery(char *sql) /***********************************************************************/ int JDBConn::ExecuteUpdate(char *sql) { + int rc = RC_FX; jint n; jstring qry; PGLOBAL& g = m_G; - if (xuid == nullptr) { - // Get the methods used to execute a query and get the affected rows - xuid = env->GetMethodID(jdi, "ExecuteUpdate", "(Ljava/lang/String;)I"); - - if (xuid == nullptr) { - strcpy(g->Message, "Cannot find method ExecuteUpdate"); - return RC_FX; - } // endif !xuid - - } // endif xuid + // Get the methods used to execute a query and get the affected rows + if (!gmID(g, xuid, "ExecuteUpdate", "(Ljava/lang/String;)I")) { + qry = env->NewStringUTF(sql); + n = env->CallIntMethod(job, xuid, qry); - qry = env->NewStringUTF(sql); - n = env->CallIntMethod(job, xuid, qry); - env->DeleteLocalRef(qry); + if (!Check(n)) { + m_Ncol = 0; + m_Aff = (int)n; // Affected rows + rc = RC_OK; + } else + sprintf(g->Message, "ExecuteUpdate: %s n=%d", Msg, n); - if (n < 0) { - sprintf(g->Message, "Error executing %s: n = %d", sql, n); - return RC_FX; - } else { - m_Ncol = 0; - m_Aff = (int)n; // Affected rows - } // endif n + env->DeleteLocalRef(qry); + } // endif xuid - return RC_OK; + return rc; } // end of ExecuteUpdate /***********************************************************************/ @@ -1432,32 +1503,21 @@ int JDBConn::ExecuteSQL(void) int rc = RC_FX; PGLOBAL& g = m_G; - if (xpid == nullptr) { - // Get the methods used to execute a prepared statement - xpid = env->GetMethodID(jdi, "ExecutePrep", "()I"); + // Get the methods used to execute a prepared statement + if (!gmID(g, xpid, "ExecutePrep", "()I")) { + jint n = env->CallIntMethod(job, xpid); - if (xpid == nullptr) { - strcpy(g->Message, "Cannot find method ExecutePrep"); - return rc; - } // endif xpid + if (n == -3) + strcpy(g->Message, "SQL statement is not prepared"); + else if (Check(n)) + sprintf(g->Message, "ExecutePrep: %s", Msg); + else { + m_Aff = (int)n; + rc = RC_OK; + } // endswitch n } // endif xpid - jint n = env->CallIntMethod(job, xpid); - - switch ((int)n) { - case -1: - case -2: - strcpy(g->Message, "Exception error thrown while executing SQL"); - break; - case -3: - strcpy(g->Message, "SQL statement is not prepared"); - break; - default: - m_Aff = (int)n; - rc = RC_OK; - } // endswitch n - return rc; } // end of ExecuteSQL @@ -1467,7 +1527,7 @@ int JDBConn::ExecuteSQL(void) bool JDBConn::SetParam(JDBCCOL *colp) { PGLOBAL& g = m_G; - int rc = false; + bool rc = false; PVAL val = colp->GetValue(); jint n, i = (jint)colp->GetRank(); jshort s; @@ -1477,63 +1537,42 @@ bool JDBConn::SetParam(JDBCCOL *colp) jclass dat; jobject datobj; jstring jst = nullptr; - jthrowable exc; jmethodID dtc, setid = nullptr; switch (val->GetType()) { case TYPE_STRING: - setid = env->GetMethodID(jdi, "SetStringParm", "(ILjava/lang/String;)V"); - - if (setid == nullptr) { - strcpy(g->Message, "Cannot fing method SetStringParm"); + if (gmID(g, setid, "SetStringParm", "(ILjava/lang/String;)V")) return true; - } // endif setid jst = env->NewStringUTF(val->GetCharValue()); env->CallVoidMethod(job, setid, i, jst); break; case TYPE_INT: - setid = env->GetMethodID(jdi, "SetIntParm", "(II)V"); - - if (setid == nullptr) { - strcpy(g->Message, "Cannot fing method SetIntParm"); + if (gmID(g, setid, "SetIntParm", "(II)V")) return true; - } // endif setid n = (jint)val->GetIntValue(); env->CallVoidMethod(job, setid, i, n); break; case TYPE_TINY: case TYPE_SHORT: - setid = env->GetMethodID(jdi, "SetShortParm", "(IS)V"); - - if (setid == nullptr) { - strcpy(g->Message, "Cannot fing method SetShortParm"); + if (gmID(g, setid, "SetShortParm", "(IS)V")) return true; - } // endif setid s = (jshort)val->GetShortValue(); env->CallVoidMethod(job, setid, i, s); break; case TYPE_BIGINT: - setid = env->GetMethodID(jdi, "SetBigintParm", "(IJ)V"); - - if (setid == nullptr) { - strcpy(g->Message, "Cannot fing method SetBigintParm"); + if (gmID(g, setid, "SetBigintParm", "(IJ)V")) return true; - } // endif setid lg = (jlong)val->GetBigintValue(); env->CallVoidMethod(job, setid, i, lg); break; case TYPE_DOUBLE: case TYPE_DECIM: - setid = env->GetMethodID(jdi, "SetDoubleParm", "(ID)V"); - - if (setid == nullptr) { - strcpy(g->Message, "Cannot fing method SetDoubleParm"); + if (gmID(g, setid, "SetDoubleParm", "(ID)V")) return true; - } // endif setid d = (jdouble)val->GetFloatValue(); env->CallVoidMethod(job, setid, i, d); @@ -1552,11 +1591,8 @@ bool JDBConn::SetParam(JDBCCOL *colp) if ((datobj = env->NewObject(dat, dtc, lg)) == nullptr) { strcpy(g->Message, "Cannot make Timestamp object"); return true; - } else if ((setid = env->GetMethodID(jdi, "SetTimestampParm", - "(ILjava/sql/Timestamp;)V")) == nullptr) { - strcpy(g->Message, "Cannot find method SetTimestampParm"); + } else if (gmID(g, setid, "SetTimestampParm", "(ILjava/sql/Timestamp;)V")) return true; - } // endif setid env->CallVoidMethod(job, setid, i, datobj); break; @@ -1565,16 +1601,10 @@ bool JDBConn::SetParam(JDBCCOL *colp) return true; } // endswitch Type - if ((exc = env->ExceptionOccurred()) != nullptr) { - jboolean isCopy = false; - jmethodID tid = env->GetMethodID(env->FindClass("java/lang/Object"), "toString", "()Ljava/lang/String;"); - jstring s = (jstring)env->CallObjectMethod(exc, tid); - const char* utf = env->GetStringUTFChars(s, &isCopy); - sprintf(g->Message, "SetParam: %s", utf); - env->DeleteLocalRef(s); - env->ExceptionClear(); + if (Check()) { + sprintf(g->Message, "SetParam: col=%s msg=%s", colp->GetName(), Msg); rc = true; - } // endif exc + } // endif msg if (jst) env->DeleteLocalRef(jst); @@ -1638,14 +1668,10 @@ bool JDBConn::SetParam(JDBCCOL *colp) int i, n, size; PCOLRES crp; jstring js; - jmethodID gdid = env->GetMethodID(jdi, "GetDrivers", "([Ljava/lang/String;I)I"); - - if (env->ExceptionCheck()) { - strcpy(m_G->Message, "ERROR: method GetDrivers() not found!"); - env->ExceptionDescribe(); - env->ExceptionClear(); + jmethodID gdid = nullptr; + + if (gmID(m_G, gdid, "GetDrivers", "([Ljava/lang/String;I)I")) return true; - } // endif Check // Build the java string array jobjectArray s = env->NewObjectArray(4 * qrp->Maxres, @@ -1694,10 +1720,10 @@ bool JDBConn::SetParam(JDBCCOL *colp) int len, qcol = 5; PQRYRES qrp = NULL; PCOLRES crp; - USHORT i; - jint *n; + ushort i; + jint *n = nullptr; jstring label; - jmethodID colid; + jmethodID colid = nullptr; int rc = ExecSQLcommand(src); if (rc == RC_NF) { @@ -1710,20 +1736,8 @@ bool JDBConn::SetParam(JDBCCOL *colp) return NULL; } // endif's - colid = env->GetMethodID(jdi, "ColumnDesc", "(I[I)Ljava/lang/String;"); - - if (colid == nullptr) { - strcpy(m_G->Message, "ERROR: method ColumnDesc() not found!"); + if (gmID(g, colid, "ColumnDesc", "(I[I)Ljava/lang/String;")) return NULL; - } // endif colid - - // Build the java string array - jintArray val = env->NewIntArray(4); - - if (val == nullptr) { - strcpy(m_G->Message, "Cannot allocate jint array"); - return NULL; - } // endif colid // Get max column name length len = GetMaxValue(5); @@ -1744,11 +1758,28 @@ bool JDBConn::SetParam(JDBCCOL *colp) case 5: crp->Name = "Nullable"; break; } // endswitch i + // Build the java string array + jintArray val = env->NewIntArray(4); + + if (val == nullptr) { + strcpy(m_G->Message, "Cannot allocate jint array"); + return NULL; + } // endif colid + /************************************************************************/ /* Now get the results into blocks. */ /************************************************************************/ for (i = 0; i < m_Ncol; i++) { - label = (jstring)env->CallObjectMethod(job, colid, i + 1, val); + if (!(label = (jstring)env->CallObjectMethod(job, colid, i + 1, val))) { + if (Check()) + sprintf(g->Message, "ColumnDesc: %s", Msg); + else + strcpy(g->Message, "No result metadata"); + + env->ReleaseIntArrayElements(val, n, 0); + return NULL; + } // endif label + name = env->GetStringUTFChars(label, (jboolean)false); crp = qrp->Colresp; // Column_Name crp->Kdata->SetValue((char*)name, i); @@ -1766,7 +1797,6 @@ bool JDBConn::SetParam(JDBCCOL *colp) /* Cleanup */ env->ReleaseIntArrayElements(val, n, 0); - Close(); /************************************************************************/ /* Return the result pointer for use by GetData routines. */ @@ -1879,10 +1909,10 @@ bool JDBConn::SetParam(JDBCCOL *colp) int JDBConn::GetCatInfo(JCATPARM *cap) { PGLOBAL& g = m_G; - void *buffer; - int i; +// void *buffer; + int i, ncol; PSZ fnc = "Unknown"; - uint n, ncol; + uint n; short len, tp; int crow = 0; PQRYRES qrp = cap->Qrp; @@ -1893,7 +1923,7 @@ bool JDBConn::SetParam(JDBCCOL *colp) PVAL *pval = NULL; char* *pbuf = NULL; jobjectArray parms; - jmethodID catid; + jmethodID catid = nullptr; if (qrp->Maxres <= 0) return 0; // 0-sized result" @@ -1905,9 +1935,7 @@ bool JDBConn::SetParam(JDBCCOL *colp) env->SetObjectArrayElement(parms, 0, env->NewStringUTF(name.ptr(2))); env->SetObjectArrayElement(parms, 1, env->NewStringUTF(name.ptr(1))); env->SetObjectArrayElement(parms, 2, env->NewStringUTF(name.ptr(0))); - - if (cap->Pat) - env->SetObjectArrayElement(parms, 3, env->NewStringUTF((const char*)cap->Pat)); + env->SetObjectArrayElement(parms, 3, env->NewStringUTF((const char*)cap->Pat)); // Now do call the proper JDBC API switch (cap->Id) { @@ -1939,21 +1967,26 @@ bool JDBConn::SetParam(JDBCCOL *colp) return -1; } // endswitch infotype - catid = env->GetMethodID(jdi, fnc, "([Ljava/lang/String;)I"); - - if (catid == nullptr) { - sprintf(g->Message, "ERROR: method %s not found !", fnc); + if (gmID(g, catid, fnc, "([Ljava/lang/String;)I")) return -1; - } // endif maxid // call method ncol = env->CallIntMethod(job, catid, parms); + if (Check(ncol)) { + sprintf(g->Message, "%s: %s", fnc, Msg); + env->DeleteLocalRef(parms); + return -1; + } // endif Check + // Not used anymore env->DeleteLocalRef(parms); + if (trace) + htrc("Method %s returned %d columns\n", fnc, ncol); + // n because we no more ignore the first column - if ((n = qrp->Nbcol) > (int)ncol) { + if ((n = qrp->Nbcol) > (uint)ncol) { strcpy(g->Message, MSG(COL_NUM_MISM)); return -1; } // endif n @@ -1979,20 +2012,25 @@ bool JDBConn::SetParam(JDBCCOL *colp) if (crp->Type == TYPE_STRING) { pbuf[n] = (char*)PlugSubAlloc(g, NULL, len); - buffer = pbuf[n]; - } else - buffer = pval[n]->GetTo_Val(); +// buffer = pbuf[n]; + } // endif Type +// } else +// buffer = pval[n]->GetTo_Val(); n++; } // endfor n // Now fetch the result - // Extended fetch cannot be used because of STRBLK's for (i = 0; i < qrp->Maxres; i++) { - if ((rc = Fetch(0)) == 0) - break; - else if (rc < 0) + if (Check(rc = Fetch(0))) { + sprintf(g->Message, "Fetch: %s", Msg); return -1; + } if (rc == 0) { + if (trace) + htrc("End of fetches i=%d\n", i); + + break; + } // endif rc for (n = 0, crp = qrp->Colresp; crp; n++, crp = crp->Next) { SetColumnValue(n + 1, nullptr, pval[n]); @@ -2001,7 +2039,7 @@ bool JDBConn::SetParam(JDBCCOL *colp) } // endfor i - if (rc == RC_OK) + if (rc > 0) qrp->Truncated = true; return i; @@ -2020,7 +2058,7 @@ bool JDBConn::SetParam(JDBCCOL *colp) if (!m_Rows) { strcpy(g->Message, "Void result"); return NULL; - } // endif m_Res + } // endif m_Rows /*********************************************************************/ /* Allocate the result storage for future retrieval. */ diff --git a/storage/connect/jdbconn.h b/storage/connect/jdbconn.h index 0646fee845b..abec3919e52 100644 --- a/storage/connect/jdbconn.h +++ b/storage/connect/jdbconn.h @@ -32,15 +32,6 @@ typedef unsigned char *PUCHAR; #endif // !__WIN__ -// Field Flags, used to indicate status of fields -//efine SQL_FIELD_FLAG_DIRTY 0x1 -//efine SQL_FIELD_FLAG_NULL 0x2 - -// Update options flags -//efine SQL_SETPOSUPDATES 0x0001 -//efine SQL_POSITIONEDSQL 0x0002 -//efine SQL_GDBOUND 0x0004 - enum JCATINFO { CAT_TAB = 1, // JDBC Tables CAT_COL = 2, // JDBC Columns @@ -55,11 +46,17 @@ enum JCATINFO { typedef struct tagJCATPARM { JCATINFO Id; // Id to indicate function PQRYRES Qrp; // Result set pointer - PUCHAR DB; // Database (Schema) - PUCHAR Tab; // Table name or pattern - PUCHAR Pat; // Table type or column pattern + char *DB; // Database (Schema) + char *Tab; // Table name or pattern + char *Pat; // Table type or column pattern } JCATPARM; +typedef jint(JNICALL *CRTJVM) (JavaVM **, void **, void *); +typedef jint(JNICALL *GETJVM) (JavaVM **, jsize, jsize *); +#if defined(_DEBUG) +typedef jint(JNICALL *GETDEF) (void *); +#endif // _DEBUG + // JDBC connection to a data source class TDBJDBC; class JDBCCOL; @@ -79,7 +76,7 @@ private: public: JDBConn(PGLOBAL g, TDBJDBC *tdbp); - int Open(PSZ jpath, PJPARM sop); + int Open(PJPARM sop); int Rewind(char *sql); void Close(void); PQRYRES AllocateResult(PGLOBAL g); @@ -114,8 +111,18 @@ public: PQRYRES GetMetaData(PGLOBAL g, char *src); public: - // Set special options -//void OnSetOptions(HSTMT hstmt); + // Set static variables + static void SetJVM(void) { + LibJvm = NULL; + CreateJavaVM = NULL; + GetCreatedJavaVMs = NULL; +#if defined(_DEBUG) + GetDefaultJavaVMInitArgs = NULL; +#endif // _DEBUG + } // end of SetJVM + + static void ResetJVM(void); + static bool GetJVM(PGLOBAL g); // Implementation public: @@ -123,24 +130,30 @@ public: // JDBC operations protected: -//bool Check(RETCODE rc); + bool gmID(PGLOBAL g, jmethodID& mid, const char *name, const char *sig); + bool Check(jint rc = 0); //void ThrowDJX(int rc, PSZ msg/*, HSTMT hstmt = SQL_NULL_HSTMT*/); //void ThrowDJX(PSZ msg); -//void AllocConnect(DWORD dwOptions); -//void Connect(void); -//bool DriverConnect(DWORD Options); -//void VerifyConnect(void); -//void GetConnectInfo(void); //void Free(void); protected: // Members +#if defined(__WIN__) + static HANDLE LibJvm; // Handle to the jvm DLL +#else // !__WIN__ + static void *LibJvm; // Handle for the jvm shared library +#endif // !__WIN__ + static CRTJVM CreateJavaVM; + static GETJVM GetCreatedJavaVMs; +#if defined(_DEBUG) + static GETDEF GetDefaultJavaVMInitArgs; +#endif // _DEBUG PGLOBAL m_G; TDBJDBC *m_Tdb; JavaVM *jvm; // Pointer to the JVM (Java Virtual Machine) JNIEnv *env; // Pointer to native interface - jclass jdi; // Pointer to the JdbcInterface class - jobject job; // The JdbcInterface class object + jclass jdi; // Pointer to the java wrapper class + jobject job; // The java wrapper class object jmethodID xqid; // The ExecuteQuery method ID jmethodID xuid; // The ExecuteUpdate method ID jmethodID xid; // The Execute method ID @@ -151,9 +164,17 @@ protected: jmethodID prepid; // The CreatePrepStmt method ID jmethodID xpid; // The ExecutePrep method ID jmethodID pcid; // The ClosePrepStmt method ID + jmethodID errid; // The GetErrmsg method ID + jmethodID chrfldid; // The StringField method ID + jmethodID intfldid; // The IntField method ID + jmethodID dblfldid; // The DoubleField method ID + jmethodID fltfldid; // The FloatField method ID + jmethodID datfldid; // The TimestampField method ID + jmethodID bigfldid; // The BigintField method ID //DWORD m_LoginTimeout; //DWORD m_QueryTimeout; //DWORD m_UpdateOptions; + char *Msg; char m_IDQuoteChar[2]; PSZ m_Driver; PSZ m_Url; diff --git a/storage/connect/odbccat.h b/storage/connect/odbccat.h index 1b5febadd3a..3b729bcb4bb 100644 --- a/storage/connect/odbccat.h +++ b/storage/connect/odbccat.h @@ -21,5 +21,5 @@ PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *db, char *table, char *colpat, int maxres, bool info, POPARM sop); PQRYRES ODBCSrcCols(PGLOBAL g, char *dsn, char *src, POPARM sop); PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *db, char *tabpat, - int maxres, bool info, POPARM sop); + char *tabtyp, int maxres, bool info, POPARM sop); PQRYRES ODBCDrivers(PGLOBAL g, int maxres, bool info); diff --git a/storage/connect/odbconn.cpp b/storage/connect/odbconn.cpp index 8b2626fe962..f1f8327f91a 100644 --- a/storage/connect/odbconn.cpp +++ b/storage/connect/odbconn.cpp @@ -606,7 +606,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, bool info, POPARM sop) + char *tabtyp, int maxres, bool info, POPARM sop) { int buftyp[] = {TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_STRING}; @@ -668,7 +668,7 @@ PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *db, char *tabpat, if (!(cap = AllocCatInfo(g, CAT_TAB, db, tabpat, qrp))) return NULL; -//cap->Pat = (PUCHAR)tabtyp; + cap->Pat = (PUCHAR)tabtyp; if (trace) htrc("Getting table results ncol=%d\n", cap->Qrp->Nbcol); diff --git a/storage/connect/tabjdbc.cpp b/storage/connect/tabjdbc.cpp index 97168646ba0..e6782e71753 100644 --- a/storage/connect/tabjdbc.cpp +++ b/storage/connect/tabjdbc.cpp @@ -1,7 +1,7 @@ /************* TabJDBC C++ Program Source Code File (.CPP) *************/ /* PROGRAM NAME: TABJDBC */ /* ------------- */ -/* Version 1.0 */ +/* Version 1.1 */ /* */ /* COPYRIGHT: */ /* ---------- */ @@ -34,8 +34,10 @@ /***********************************************************************/ /* Include relevant MariaDB header file. */ /***********************************************************************/ +#define MYSQL_SERVER 1 #include "my_global.h" #include "sql_class.h" +#include "sql_servers.h" #if defined(__WIN__) #include <io.h> #include <fcntl.h> @@ -67,7 +69,6 @@ #include "plgdbsem.h" #include "mycat.h" #include "xtable.h" -#include "jdbccat.h" #include "tabjdbc.h" #include "tabmul.h" #include "reldef.h" @@ -95,48 +96,160 @@ bool ExactInfo(void); /***********************************************************************/ JDBCDEF::JDBCDEF(void) { - Jpath = Driver = Url = Tabname = Tabschema = Username = NULL; + Driver = Url = Tabname = Tabschema = Username = Colpat = NULL; Password = Tabcat = Tabtype = Srcdef = Qchar = Qrystr = Sep = NULL; Options = Quoted = Maxerr = Maxres = Memory = 0; Scrollable = Xsrc = false; } // end of JDBCDEF constructor /***********************************************************************/ +/* Called on table construction. */ +/***********************************************************************/ +bool JDBCDEF::SetParms(PJPARM sjp) +{ + sjp->Url= Url; + sjp->User= Username; + sjp->Pwd= Password; + return true; +} // end of SetParms + +/***********************************************************************/ +/* Parse connection string */ +/* */ +/* SYNOPSIS */ +/* ParseURL() */ +/* Url The connection string to parse */ +/* */ +/* DESCRIPTION */ +/* This is used to set the Url in case a wrapper server as been */ +/* specified. This is rather experimental yet. */ +/* */ +/* RETURN VALUE */ +/* RC_OK Url was a true URL */ +/* RC_NF Url was a server name/table */ +/* RC_FX Error */ +/* */ +/***********************************************************************/ +int JDBCDEF::ParseURL(PGLOBAL g, char *url, bool b) +{ + if (strncmp(url, "jdbc:", 5)) { + // No "jdbc:" in connection string. Must be a straight + // "server" or "server/table" + // ok, so we do a little parsing, but not completely! + if ((Tabname= strchr(url, '/'))) { + // If there is a single '/' in the connection string, + // this means the user is specifying a table name + *Tabname++= '\0'; + + // there better not be any more '/'s ! + if (strchr(Tabname, '/')) + return RC_FX; + + } else if (b) { + // Otherwise, straight server name, + Tabname = GetStringCatInfo(g, "Name", NULL); + Tabname = GetStringCatInfo(g, "Tabname", Tabname); + } // endelse + + if (trace) + htrc("server: %s Tabname: %s", url, Tabname); + + // Now make the required URL + FOREIGN_SERVER *server, server_buffer; + + // get_server_by_name() clones the server if exists + if (!(server= get_server_by_name(current_thd->mem_root, url, &server_buffer))) { + sprintf(g->Message, "Server %s does not exist!", url); + return RC_FX; + } // endif server + + if (strncmp(server->host, "jdbc:", 5)) { + // Now make the required URL + Url = (PSZ)PlugSubAlloc(g, NULL, 0); + strcat(strcpy(Url, "jdbc:"), server->scheme); + strcat(strcat(Url, "://"), server->host); + + if (server->port) { + char buf[16]; + + sprintf(buf, "%ld", server->port); + strcat(strcat(Url, ":"), buf); + } // endif port + + if (server->db) + strcat(strcat(Url, "/"), server->db); + + PlugSubAlloc(g, NULL, strlen(Url) + 1); + } else // host is a URL + Url = PlugDup(g, server->host); + + if (server->username) + Username = PlugDup(g, server->username); + + if (server->password) + Password = PlugDup(g, server->password); + + return RC_NF; + } // endif + + // Url was a JDBC URL, nothing to do + return RC_OK; +} // end of ParseURL + +/***********************************************************************/ /* DefineAM: define specific AM block values from JDBC file. */ /***********************************************************************/ bool JDBCDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) { - Jpath = GetStringCatInfo(g, "Jpath", ""); + int rc = RC_OK; + Driver = GetStringCatInfo(g, "Driver", NULL); - Desc = Url = GetStringCatInfo(g, "Url", NULL); + Desc = Url = GetStringCatInfo(g, "Connect", NULL); if (!Url && !Catfunc) { - sprintf(g->Message, "Missing URL for JDBC table %s", Name); - return true; + // Look in the option list (deprecated) + Url = GetStringCatInfo(g, "Url", NULL); + + if (!Url) { + sprintf(g->Message, "Missing URL for JDBC table %s", Name); + return true; + } // endif Url + } // endif Connect - Tabname = GetStringCatInfo(g, "Name", - (Catfunc & (FNC_TABLE | FNC_COL)) ? NULL : Name); - Tabname = GetStringCatInfo(g, "Tabname", Tabname); - Tabschema = GetStringCatInfo(g, "Dbname", NULL); - Tabschema = GetStringCatInfo(g, "Schema", Tabschema); - Tabcat = GetStringCatInfo(g, "Qualifier", NULL); - Tabcat = GetStringCatInfo(g, "Catalog", Tabcat); - Tabtype = GetStringCatInfo(g, "Tabtype", NULL); - Username = GetStringCatInfo(g, "User", NULL); - Password = GetStringCatInfo(g, "Password", NULL); + if (Url) + rc = ParseURL(g, Url); + + if (rc == RC_FX) // Error + return true; + else if (rc == RC_OK) { // Url was not a server name + Tabname = GetStringCatInfo(g, "Name", + (Catfunc & (FNC_TABLE | FNC_COL)) ? NULL : Name); + Tabname = GetStringCatInfo(g, "Tabname", Tabname); + Username = GetStringCatInfo(g, "User", NULL); + Password = GetStringCatInfo(g, "Password", NULL); + } // endif rc if ((Srcdef = GetStringCatInfo(g, "Srcdef", NULL))) Read_Only = true; + Tabcat = GetStringCatInfo(g, "Qualifier", NULL); + Tabcat = GetStringCatInfo(g, "Catalog", Tabcat); + Tabschema = GetStringCatInfo(g, "Dbname", NULL); + Tabschema = GetStringCatInfo(g, "Schema", Tabschema); + + if (Catfunc == FNC_COL) + Colpat = GetStringCatInfo(g, "Colpat", NULL); + + if (Catfunc == FNC_TABLE) + Tabtype = GetStringCatInfo(g, "Tabtype", NULL); + Qrystr = GetStringCatInfo(g, "Query_String", "?"); Sep = GetStringCatInfo(g, "Separator", NULL); Xsrc = GetBoolCatInfo("Execsrc", FALSE); Maxerr = GetIntCatInfo("Maxerr", 0); Maxres = GetIntCatInfo("Maxres", 0); Quoted = GetIntCatInfo("Quoted", 0); -//Options = JDBConn::noJDBCDialog; -//Options = JDBConn::noJDBCDialog | JDBConn::useCursorLib; //Cto= GetIntCatInfo("ConnectTimeout", DEFAULT_LOGIN_TIMEOUT); //Qto= GetIntCatInfo("QueryTimeout", DEFAULT_QUERY_TIMEOUT); Scrollable = GetBoolCatInfo("Scrollable", false); @@ -198,7 +311,7 @@ int JDBCPARM::CheckSize(int rows) if (Url && rows == 1) { // Are we connected to a MySQL JDBC connector? bool b = (!strncmp(Url, "jdbc:mysql:", 11) || - !strncmp(Url, "jdbc:mariadb:", 13)); + !strncmp(Url, "jdbc:mariadb:", 13)); return b ? INT_MIN32 : rows; } else return rows; @@ -216,7 +329,6 @@ TDBJDBC::TDBJDBC(PJDBCDEF tdp) : TDBASE(tdp) Cnp = NULL; if (tdp) { - Jpath = tdp->Jpath; Ops.Driver = tdp->Driver; Ops.Url = tdp->Url; TableName = tdp->Tabname; @@ -235,7 +347,6 @@ TDBJDBC::TDBJDBC(PJDBCDEF tdp) : TDBASE(tdp) Memory = tdp->Memory; Ops.Scrollable = tdp->Scrollable; } else { - Jpath = NULL; TableName = NULL; Schema = NULL; Ops.Driver = NULL; @@ -271,6 +382,7 @@ TDBJDBC::TDBJDBC(PJDBCDEF tdp) : TDBASE(tdp) Ncol = 0; Nparm = 0; Placed = false; + Prepared = false; Werr = false; Rerr = false; Ops.Fsize = Ops.CheckSize(Rows); @@ -280,7 +392,6 @@ TDBJDBC::TDBJDBC(PTDBJDBC tdbp) : TDBASE(tdbp) { Jcp = tdbp->Jcp; // is that right ? Cnp = tdbp->Cnp; - Jpath = tdbp->Jpath; TableName = tdbp->TableName; Schema = tdbp->Schema; Ops = tdbp->Ops; @@ -678,7 +789,7 @@ int TDBJDBC::Cardinality(PGLOBAL g) char qry[96], tbn[64]; JDBConn *jcp = new(g)JDBConn(g, this); - if (jcp->Open(Jpath, &Ops) == RC_FX) + if (jcp->Open(&Ops) == RC_FX) return -1; // Table name can be encoded in UTF-8 @@ -789,7 +900,7 @@ bool TDBJDBC::OpenDB(PGLOBAL g) else if (Jcp->IsOpen()) Jcp->Close(); - if (Jcp->Open(Jpath, &Ops) == RC_FX) + if (Jcp->Open(&Ops) == RC_FX) return true; else if (Quoted) Quote = Jcp->GetQuoteChar(); @@ -1539,7 +1650,7 @@ bool TDBXJDC::OpenDB(PGLOBAL g) } else if (Jcp->IsOpen()) Jcp->Close(); - if (Jcp->Open(Jpath, &Ops) == RC_FX) + if (Jcp->Open(&Ops) == RC_FX) return true; Use = USE_OPEN; // Do it now in case we are recursively called @@ -1651,7 +1762,7 @@ void JSRCCOL::WriteColumn(PGLOBAL g) /***********************************************************************/ PQRYRES TDBJDRV::GetResult(PGLOBAL g) { - return JDBCDrivers(g, Jpath, Maxres, false); + return JDBCDrivers(g, Maxres, false); } // end of GetResult /* ---------------------------TDBJTB class --------------------------- */ @@ -1661,7 +1772,6 @@ PQRYRES TDBJDRV::GetResult(PGLOBAL g) /***********************************************************************/ TDBJTB::TDBJTB(PJDBCDEF tdp) : TDBJDRV(tdp) { - Jpath = tdp->Jpath; Schema = tdp->Tabschema; Tab = tdp->Tabname; Tabtype = tdp->Tabtype; @@ -1669,6 +1779,8 @@ TDBJTB::TDBJTB(PJDBCDEF tdp) : TDBJDRV(tdp) Ops.Url = tdp->Url; Ops.User = tdp->Username; Ops.Pwd = tdp->Password; + Ops.Fsize = 0; + Ops.Scrollable = false; } // end of TDBJTB constructor /***********************************************************************/ @@ -1676,17 +1788,25 @@ TDBJTB::TDBJTB(PJDBCDEF tdp) : TDBJDRV(tdp) /***********************************************************************/ PQRYRES TDBJTB::GetResult(PGLOBAL g) { - return JDBCTables(g, Jpath, Schema, Tab, Tabtype, Maxres, false, &Ops); + return JDBCTables(g, Schema, Tab, Tabtype, Maxres, false, &Ops); } // end of GetResult /* --------------------------TDBJDBCL class -------------------------- */ /***********************************************************************/ +/* TDBJDBCL class constructor. */ +/***********************************************************************/ +TDBJDBCL::TDBJDBCL(PJDBCDEF tdp) : TDBJTB(tdp) +{ + Colpat = tdp->Colpat; +} // end of TDBJDBCL constructor + +/***********************************************************************/ /* GetResult: Get the list of JDBC table columns. */ /***********************************************************************/ PQRYRES TDBJDBCL::GetResult(PGLOBAL g) { - return JDBCColumns(g, Jpath, Schema, Tab, NULL, Maxres, false, &Ops); + return JDBCColumns(g, Schema, Tab, Colpat, Maxres, false, &Ops); } // end of GetResult #if 0 diff --git a/storage/connect/tabjdbc.h b/storage/connect/tabjdbc.h index b6cf91e28b8..cf5e662c9d1 100644 --- a/storage/connect/tabjdbc.h +++ b/storage/connect/tabjdbc.h @@ -7,6 +7,7 @@ /***********************************************************************/ #include "colblk.h" #include "resource.h" +#include "jdbccat.h" typedef class JDBCDEF *PJDBCDEF; typedef class TDBJDBC *PTDBJDBC; @@ -25,13 +26,13 @@ class DllExport JDBCDEF : public TABDEF { /* Logical table description */ friend class TDBXJDC; friend class TDBJDRV; friend class TDBJTB; + friend class TDBJDBCL; public: // Constructor JDBCDEF(void); // Implementation virtual const char *GetType(void) { return "JDBC"; } - PSZ GetJpath(void) { return Jpath; } PSZ GetTabname(void) { return Tabname; } PSZ GetTabschema(void) { return Tabschema; } PSZ GetTabcat(void) { return Tabcat; } @@ -45,10 +46,11 @@ public: virtual int Indexable(void) { return 2; } virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff); virtual PTDB GetTable(PGLOBAL g, MODE m); + int ParseURL(PGLOBAL g, char *url, bool b = true); + bool SetParms(PJPARM sjp); protected: // Members - PSZ Jpath; /* Java class path */ PSZ Driver; /* JDBC driver */ PSZ Url; /* JDBC driver URL */ PSZ Tabname; /* External table name */ @@ -57,6 +59,7 @@ protected: PSZ Password; /* Password connect info */ PSZ Tabcat; /* External table catalog */ PSZ Tabtype; /* External table type */ + PSZ Colpat; /* Catalog column pattern */ PSZ Srcdef; /* The source table SQL definition */ PSZ Qchar; /* Identifier quoting character */ PSZ Qrystr; /* The original query */ @@ -73,7 +76,7 @@ protected: }; // end of JDBCDEF #if !defined(NJDBC) -#include "JDBConn.h" +#include "jdbconn.h" /***********************************************************************/ /* This is the JDBC Access Method class declaration for files from */ @@ -130,7 +133,6 @@ protected: JDBCCOL *Cnp; // Points to count(*) column JDBCPARM Ops; // Additional parameters PSTRG Query; // Constructed SQL query - char *Jpath; // Java class path char *TableName; // Points to JDBC table name char *Schema; // Points to JDBC table Schema char *User; // User connect info @@ -282,7 +284,7 @@ protected: class TDBJDRV : public TDBCAT { public: // Constructor - TDBJDRV(PJDBCDEF tdp) : TDBCAT(tdp) {Maxres = tdp->Maxres; Jpath = tdp->Jpath;} + TDBJDRV(PJDBCDEF tdp) : TDBCAT(tdp) {Maxres = tdp->Maxres;} protected: // Specific routines @@ -290,7 +292,6 @@ protected: // Members int Maxres; // Returned lines limit - char *Jpath; // Java class path }; // end of class TDBJDRV /***********************************************************************/ @@ -306,7 +307,6 @@ protected: virtual PQRYRES GetResult(PGLOBAL g); // Members - char *Jpath; // Points to Java classpath char *Schema; // Points to schema name or NULL char *Tab; // Points to JDBC table name or pattern char *Tabtype; // Points to JDBC table type @@ -319,14 +319,15 @@ protected: class TDBJDBCL : public TDBJTB { public: // Constructor - TDBJDBCL(PJDBCDEF tdp) : TDBJTB(tdp) {} + TDBJDBCL(PJDBCDEF tdp); protected: // Specific routines virtual PQRYRES GetResult(PGLOBAL g); - // No additional Members -}; // end of class TDBJCL + // Members + char *Colpat; // Points to catalog column pattern +}; // end of class TDBJDBCL #if 0 /***********************************************************************/ diff --git a/storage/connect/tabodbc.cpp b/storage/connect/tabodbc.cpp index 5fd0534210d..8a43ca9e591 100644 --- a/storage/connect/tabodbc.cpp +++ b/storage/connect/tabodbc.cpp @@ -1,7 +1,7 @@ /************* Tabodbc C++ Program Source Code File (.CPP) *************/ /* PROGRAM NAME: TABODBC */ /* ------------- */ -/* Version 3.0 */ +/* Version 3.1 */ /* */ /* COPYRIGHT: */ /* ---------- */ @@ -96,7 +96,7 @@ bool ExactInfo(void); ODBCDEF::ODBCDEF(void) { Connect = Tabname = Tabschema = Username = Password = NULL; - Tabcat = Srcdef = Qchar = Qrystr = Sep = NULL; + Tabcat = Colpat = Srcdef = Qchar = Qrystr = Sep = NULL; Catver = Options = Cto = Qto = Quoted = Maxerr = Maxres = Memory = 0; Scrollable = Xsrc = UseCnc = false; } // end of ODBCDEF constructor @@ -120,7 +120,7 @@ bool ODBCDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) Tabschema = GetStringCatInfo(g, "Schema", Tabschema); Tabcat = GetStringCatInfo(g, "Qualifier", NULL); Tabcat = GetStringCatInfo(g, "Catalog", Tabcat); - Username = GetStringCatInfo(g, "User", NULL); + Username = GetStringCatInfo(g, "User", NULL); Password = GetStringCatInfo(g, "Password", NULL); if ((Srcdef = GetStringCatInfo(g, "Srcdef", NULL))) @@ -141,7 +141,13 @@ bool ODBCDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) if ((Scrollable = GetBoolCatInfo("Scrollable", false)) && !Elemt) Elemt = 1; // Cannot merge SQLFetch and SQLExtendedFetch - UseCnc = GetBoolCatInfo("UseDSN", false); + if (Catfunc == FNC_COL) + Colpat = GetStringCatInfo(g, "Colpat", NULL); + + if (Catfunc == FNC_TABLE) + Tabtyp = GetStringCatInfo(g, "Tabtype", NULL); + + UseCnc = GetBoolCatInfo("UseDSN", false); // Memory was Boolean, it is now integer if (!(Memory = GetIntCatInfo("Memory", 0))) @@ -1768,6 +1774,7 @@ TDBOTB::TDBOTB(PODEF tdp) : TDBDRV(tdp) Dsn = tdp->GetConnect(); Schema = tdp->GetTabschema(); Tab = tdp->GetTabname(); + Tabtyp = tdp->Tabtyp; Ops.User = tdp->Username; Ops.Pwd = tdp->Password; Ops.Cto = tdp->Cto; @@ -1780,17 +1787,25 @@ TDBOTB::TDBOTB(PODEF tdp) : TDBDRV(tdp) /***********************************************************************/ PQRYRES TDBOTB::GetResult(PGLOBAL g) { - return ODBCTables(g, Dsn, Schema, Tab, Maxres, false, &Ops); + return ODBCTables(g, Dsn, Schema, Tab, Tabtyp, Maxres, false, &Ops); } // end of GetResult /* ---------------------------TDBOCL class --------------------------- */ /***********************************************************************/ +/* TDBOCL class constructor. */ +/***********************************************************************/ +TDBOCL::TDBOCL(PODEF tdp) : TDBOTB(tdp) +{ + Colpat = tdp->Colpat; +} // end of TDBOTB constructor + +/***********************************************************************/ /* GetResult: Get the list of ODBC table columns. */ /***********************************************************************/ PQRYRES TDBOCL::GetResult(PGLOBAL g) { - return ODBCColumns(g, Dsn, Schema, Tab, NULL, Maxres, false, &Ops); + return ODBCColumns(g, Dsn, Schema, Tab, Colpat, Maxres, false, &Ops); } // end of GetResult /* ------------------------ End of Tabodbc --------------------------- */ diff --git a/storage/connect/tabodbc.h b/storage/connect/tabodbc.h index 6440dee830d..aa6592d8abf 100644 --- a/storage/connect/tabodbc.h +++ b/storage/connect/tabodbc.h @@ -25,7 +25,8 @@ class DllExport ODBCDEF : public TABDEF { /* Logical table description */ friend class TDBXDBC; friend class TDBDRV; friend class TDBOTB; - public: + friend class TDBOCL; +public: // Constructor ODBCDEF(void); @@ -54,7 +55,9 @@ class DllExport ODBCDEF : public TABDEF { /* Logical table description */ PSZ Username; /* User connect name */ PSZ Password; /* Password connect info */ PSZ Tabcat; /* External table catalog */ - PSZ Srcdef; /* The source table SQL definition */ + PSZ Tabtyp; /* Catalog table type */ + PSZ Colpat; /* Catalog column pattern */ + PSZ Srcdef; /* The source table SQL definition */ PSZ Qchar; /* Identifier quoting character */ PSZ Qrystr; /* The original query */ PSZ Sep; /* Decimal separator */ @@ -326,7 +329,8 @@ class TDBOTB : public TDBDRV { char *Dsn; // Points to connection string char *Schema; // Points to schema name or NULL char *Tab; // Points to ODBC table name or pattern - ODBCPARM Ops; // Additional parameters + char *Tabtyp; // Points to ODBC table type + ODBCPARM Ops; // Additional parameters }; // end of class TDBOTB /***********************************************************************/ @@ -335,13 +339,14 @@ class TDBOTB : public TDBDRV { class TDBOCL : public TDBOTB { public: // Constructor - TDBOCL(PODEF tdp) : TDBOTB(tdp) {} + TDBOCL(PODEF tdp); protected: // Specific routines virtual PQRYRES GetResult(PGLOBAL g); - // No additional Members + // Members + char *Colpat; // Points to column pattern }; // end of class TDBOCL #endif // !NODBC |