1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

All changes made on 10.1 for last 11 commits

This commit is contained in:
Olivier Bertrand
2016-07-14 20:12:22 +02:00
parent f2dded9bac
commit 44012db635
33 changed files with 910 additions and 1677 deletions

View File

@@ -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 ((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
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));
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
if (!gmID(g, datfldid, "DateField", "(ILjava/lang/String;)I")) {
val->SetValue((int)env->CallIntMethod(job, datfldid, (jint)rank, jn));
} 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, 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
} else
val->Reset();
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) {