diff options
author | Olivier Bertrand <bertrandop@gmail.com> | 2016-07-14 20:12:22 +0200 |
---|---|---|
committer | Olivier Bertrand <bertrandop@gmail.com> | 2016-07-14 20:12:22 +0200 |
commit | 44012db6350b51ad7e78f286dfa6e5d4ae84f807 (patch) | |
tree | 8dfef1aecad87a3a6f7e10c921120dc3f1d23a9c /storage/connect/jdbconn.cpp | |
parent | f2dded9bac48de391cdd796283769691872ba911 (diff) | |
download | mariadb-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.cpp | 233 |
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) { |