summaryrefslogtreecommitdiff
path: root/storage/connect/jdbconn.cpp
diff options
context:
space:
mode:
authorOlivier Bertrand <bertrandop@gmail.com>2016-07-14 20:12:22 +0200
committerOlivier Bertrand <bertrandop@gmail.com>2016-07-14 20:12:22 +0200
commit44012db6350b51ad7e78f286dfa6e5d4ae84f807 (patch)
tree8dfef1aecad87a3a6f7e10c921120dc3f1d23a9c /storage/connect/jdbconn.cpp
parentf2dded9bac48de391cdd796283769691872ba911 (diff)
downloadmariadb-git-44012db6350b51ad7e78f286dfa6e5d4ae84f807.tar.gz
All changes made on 10.1 for last 11 commits
Diffstat (limited to 'storage/connect/jdbconn.cpp')
-rw-r--r--storage/connect/jdbconn.cpp233
1 files changed, 137 insertions, 96 deletions
diff --git a/storage/connect/jdbconn.cpp b/storage/connect/jdbconn.cpp
index a8c0b193dcd..d3e573e692c 100644
--- a/storage/connect/jdbconn.cpp
+++ b/storage/connect/jdbconn.cpp
@@ -6,6 +6,13 @@
/* This file contains the JDBC connection classes functions. */
/***********************************************************************/
+#if defined(__WIN__)
+// This is needed for RegGetValue
+#define _WINVER 0x0601
+#undef _WIN32_WINNT
+#define _WIN32_WINNT 0x0601
+#endif // __WIN__
+
/***********************************************************************/
/* Include relevant MariaDB header file. */
/***********************************************************************/
@@ -55,7 +62,8 @@ extern "C" HINSTANCE s_hModule; // Saved module handle
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
+
+char *GetJavaWrapper(void); // The connect_java_wrapper variable value
/***********************************************************************/
/* Static JDBConn objects. */
@@ -79,7 +87,7 @@ GETDEF JDBConn::GetDefaultJavaVMInitArgs = NULL;
#endif // !_DEBUG
// To avoid gcc warning
-int TranslateJDBCType(int stp, int prec, int& len, char& v);
+int TranslateJDBCType(int stp, char *tn, int prec, int& len, char& v);
/***********************************************************************/
/* GetJDBCType: returns the SQL_TYPE corresponding to a PLG type. */
@@ -107,7 +115,7 @@ static short GetJDBCType(int type)
/***********************************************************************/
/* TranslateJDBCType: translate a JDBC Type to a PLG type. */
/***********************************************************************/
-int TranslateJDBCType(int stp, int prec, int& len, char& v)
+int TranslateJDBCType(int stp, char *tn, int prec, int& len, char& v)
{
int type;
@@ -139,17 +147,24 @@ int TranslateJDBCType(int stp, int prec, int& len, char& v)
case 8: // DOUBLE
type = TYPE_DOUBLE;
break;
- case 93: // TIMESTAMP
+ case 93: // TIMESTAMP, DATETIME
type = TYPE_DATE;
len = 19 + ((prec) ? (prec+1) : 0);
- v = 'S';
+ v = (tn && toupper(tn[0]) == 'T') ? 'S' : 'E';
break;
- case 91: // TYPE_DATE
+ case 91: // DATE, YEAR
type = TYPE_DATE;
- len = 10;
- v = 'D';
+
+ if (!tn || toupper(tn[0]) != 'Y') {
+ len = 10;
+ v = 'D';
+ } else {
+ len = 4;
+ v = 'Y';
+ } // endif len
+
break;
- case 92: // TYPE_TIME
+ case 92: // TIME
type = TYPE_DATE;
len = 8 + ((prec) ? (prec+1) : 0);
v = 'T';
@@ -174,42 +189,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
-
-//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));
+ 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
-fin:
- g->jump_level--;
return cap;
} // end of AllocCatInfo
@@ -291,7 +284,8 @@ PQRYRES JDBCColumns(PGLOBAL g, char *db, char *table, char *colpat,
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 : PlugDup(g, "%");
/************************************************************************/
/* Now get the results into blocks. */
@@ -399,10 +393,12 @@ PQRYRES JDBCTables(PGLOBAL g, char *db, char *tabpat, char *tabtyp,
if (info || !qrp)
return qrp;
- if (!(cap = AllocCatInfo(g, CAT_TAB, db, tabpat, qrp)))
+ // Tabpat cannot be null or empty for some drivers
+ if (!(cap = AllocCatInfo(g, CAT_TAB, db,
+ (tabpat && *tabpat) ? tabpat : PlugDup(g, "%"), qrp)))
return NULL;
- cap->Pat = (PUCHAR)tabtyp;
+ cap->Pat = tabtyp;
if (trace)
htrc("Getting table results ncol=%d\n", cap->Qrp->Nbcol);
@@ -650,11 +646,20 @@ JDBConn::JDBConn(PGLOBAL g, TDBJDBC *tdbp)
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;
+ chrfldid = intfldid = dblfldid = fltfldid = bigfldid = nullptr;
+ datfldid = timfldid = tspfldid = nullptr;
+ //m_LoginTimeout = DEFAULT_LOGIN_TIMEOUT;
//m_QueryTimeout = DEFAULT_QUERY_TIMEOUT;
//m_UpdateOptions = 0;
Msg = NULL;
+ m_Wrap = (tdbp && tdbp->WrapName) ? tdbp->WrapName : GetJavaWrapper();
+
+ if (!strchr(m_Wrap, '/')) {
+ // Add the wrapper package name
+ char *wn = (char*)PlugSubAlloc(g, NULL, strlen(m_Wrap) + 10);
+ m_Wrap = strcat(strcpy(wn, "wrappers/"), m_Wrap);
+ } // endif m_Wrap
+
m_Driver = NULL;
m_Url = NULL;
m_User = NULL;
@@ -830,17 +835,52 @@ void JDBConn::ResetJVM(void)
/***********************************************************************/
bool JDBConn::GetJVM(PGLOBAL g)
{
+ int ntry;
+
if (!LibJvm) {
char soname[512];
#if defined(__WIN__)
- if (JvmPath)
- strcat(strcpy(soname, JvmPath), "\\jvm.dll");
- else
- strcpy(soname, "jvm.dll");
+ for (ntry = 0; !LibJvm && ntry < 3; ntry++) {
+ if (!ntry && JvmPath) {
+ strcat(strcpy(soname, JvmPath), "\\jvm.dll");
+ ntry = 3; // No other try
+ } else if (ntry < 2 && getenv("JAVA_HOME")) {
+ strcpy(soname, getenv("JAVA_HOME"));
- // Load the desired shared library
- if (!(LibJvm = LoadLibrary(soname))) {
+ if (ntry == 1)
+ strcat(soname, "\\jre");
+
+ strcat(soname, "\\bin\\client\\jvm.dll");
+ } else {
+ // Try to find it through the registry
+ char version[16];
+ char javaKey[64] = "SOFTWARE\\JavaSoft\\Java Runtime Environment";
+ LONG rc;
+ DWORD BufferSize = 16;
+
+ strcpy(soname, "jvm.dll"); // In case it fails
+
+ if ((rc = RegGetValue(HKEY_LOCAL_MACHINE, javaKey, "CurrentVersion",
+ RRF_RT_ANY, NULL, (PVOID)&version, &BufferSize)) == ERROR_SUCCESS) {
+ strcat(strcat(javaKey, "\\"), version);
+ BufferSize = sizeof(soname);
+
+ if ((rc = RegGetValue(HKEY_LOCAL_MACHINE, javaKey, "RuntimeLib",
+ RRF_RT_ANY, NULL, (PVOID)&soname, &BufferSize)) != ERROR_SUCCESS)
+ printf("RegGetValue: rc=%ld\n", rc);
+
+ } // endif rc
+
+ ntry = 3; // Try this only once
+ } // endelse
+
+ // Load the desired shared library
+ LibJvm = LoadLibrary(soname);
+ } // endfor ntry
+
+ // Get the needed entries
+ if (!LibJvm) {
char buf[256];
DWORD rc = GetLastError();
@@ -871,13 +911,23 @@ bool JDBConn::GetJVM(PGLOBAL g)
#else // !__WIN__
const char *error = NULL;
- if (JvmPath)
- strcat(strcpy(soname, JvmPath), "/libjvm.so");
- else
- strcpy(soname, "libjvm.so");
+ for (ntry = 0; !LibJvm && ntry < 2; ntry++) {
+ if (!ntry && JvmPath) {
+ strcat(strcpy(soname, JvmPath), "/libjvm.so");
+ ntry = 2;
+ } else if (!ntry && getenv("JAVA_HOME")) {
+ // TODO: Replace i386 by a better guess
+ strcat(strcpy(soname, getenv("JAVA_HOME")), "/jre/lib/i386/client/libjvm.so");
+ } else { // Will need LD_LIBRARY_PATH to be set
+ strcpy(soname, "libjvm.so");
+ ntry = 2;
+ } // endelse
+
+ LibJvm = dlopen(soname, RTLD_LAZY);
+ } // endfor ntry
// Load the desired shared library
- if (!(LibJvm = dlopen(soname, RTLD_LAZY))) {
+ if (!LibJvm) {
error = dlerror();
sprintf(g->Message, MSG(SHARED_LIB_ERR), soname, SVP(error));
} else if (!(CreateJavaVM = (CRTJVM)dlsym(LibJvm, "JNI_CreateJavaVM"))) {
@@ -911,7 +961,9 @@ bool JDBConn::GetJVM(PGLOBAL g)
/***********************************************************************/
int JDBConn::Open(PJPARM sop)
{
+
bool err = false;
+ jboolean jt = (trace > 0);
PGLOBAL& g = m_G;
// Link or check whether jvm library was linked
@@ -951,6 +1003,11 @@ int JDBConn::Open(PJPARM sop)
#define N 1
#endif
+ // Java source will be compiled as ajar file installed in the plugin dir
+ jpop->Append(sep);
+ jpop->Append(GetPluginDir());
+ jpop->Append("JdbcInterface.jar");
+
//================== prepare loading of Java VM ============================
JavaVMInitArgs vm_args; // Initialization arguments
JavaVMOption* options = new JavaVMOption[N]; // JVM invocation options
@@ -1021,19 +1078,16 @@ int JDBConn::Open(PJPARM sop)
return RC_FX;
} // endswitch rc
+ //=============== Display JVM version ===============
+ jint ver = env->GetVersion();
+ printf("JVM Version %d.%d\n", ((ver>>16)&0x0f), (ver&0x0f));
} // endif rc
- //=============== Display JVM version =======================================
-#if defined(_DEBUG)
- jint ver = env->GetVersion();
- printf("JVM Version %d.%d\n", ((ver>>16)&0x0f), (ver&0x0f));
-#endif //_DEBUG
-
// try to find the java wrapper class
- jdi = env->FindClass(Wrapper);
+ jdi = env->FindClass(m_Wrap);
if (jdi == nullptr) {
- sprintf(g->Message, "ERROR: class %s not found!", Wrapper);
+ sprintf(g->Message, "ERROR: class %s not found!", m_Wrap);
return RC_FX;
} // endif jdi
@@ -1076,19 +1130,19 @@ int JDBConn::Open(PJPARM sop)
#endif // 0
// if class found, continue
- jmethodID ctor = env->GetMethodID(jdi, "<init>", "()V");
+ jmethodID ctor = env->GetMethodID(jdi, "<init>", "(Z)V");
if (ctor == nullptr) {
- sprintf(g->Message, "ERROR: %s constructor not found!", Wrapper);
+ sprintf(g->Message, "ERROR: %s constructor not found!", m_Wrap);
return RC_FX;
} else
- job = env->NewObject(jdi, ctor);
+ job = env->NewObject(jdi, ctor, jt);
// If the object is successfully constructed,
// we can then search for the method we want to call,
// and invoke it for the object:
if (job == nullptr) {
- sprintf(g->Message, "%s class object not constructed!", Wrapper);
+ sprintf(g->Message, "%s class object not constructed!", m_Wrap);
return RC_FX;
} // endif job
@@ -1289,9 +1343,7 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val)
{
PGLOBAL& g = m_G;
jint ctyp;
- jlong dtv;
jstring cn, jn = nullptr;
- jobject dob;
if (rank == 0)
if (!name || (jn = env->NewStringUTF(name)) == nullptr) {
@@ -1354,31 +1406,22 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val)
break;
case 91: // DATE
- case 92: // TIME
- case 93: // TIMESTAMP
- 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");
-
- if (env->ExceptionCheck()) {
- val->Reset();
- } else {
- jmethodID getTime = env->GetMethodID(jts, "getTime", "()J");
-
- if (getTime != nullptr) {
- dtv = env->CallLongMethod(dob, getTime);
- val->SetValue((int)(dtv / 1000));
- } else
- val->Reset();
-
- } // endif check
+ if (!gmID(g, datfldid, "DateField", "(ILjava/lang/String;)I")) {
+ val->SetValue((int)env->CallIntMethod(job, datfldid, (jint)rank, jn));
+ } else
+ val->Reset();
- } else
- val->Reset();
+ break;
+ case 92: // TIME
+ if (!gmID(g, timfldid, "TimeField", "(ILjava/lang/String;)I")) {
+ val->SetValue((int)env->CallIntMethod(job, timfldid, (jint)rank, jn));
+ } else
+ val->Reset();
+ break;
+ case 93: // TIMESTAMP
+ if (!gmID(g, tspfldid, "TimestampField", "(ILjava/lang/String;)I")) {
+ val->SetValue((int)env->CallIntMethod(job, tspfldid, (jint)rank, jn));
} else
val->Reset();
@@ -1931,9 +1974,9 @@ bool JDBConn::SetParam(JDBCCOL *colp)
{
PGLOBAL& g = m_G;
// void *buffer;
- int i;
+ int i, ncol;
PSZ fnc = "Unknown";
- uint n, ncol;
+ uint n;
short len, tp;
int crow = 0;
PQRYRES qrp = cap->Qrp;
@@ -1956,9 +1999,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) {