diff options
author | Olivier Bertrand <bertrandop@gmail.com> | 2016-05-20 00:18:29 +0200 |
---|---|---|
committer | Olivier Bertrand <bertrandop@gmail.com> | 2016-05-20 00:18:29 +0200 |
commit | 2f2797e52f235e6edae8627ac0700f8e43809859 (patch) | |
tree | ce081d95b1f6bf0573551ae7dcf84a0a53cc1b06 /storage | |
parent | 7972a45b4343cf620f4dc6d508ff9e0c1ca000e3 (diff) | |
download | mariadb-git-2f2797e52f235e6edae8627ac0700f8e43809859.tar.gz |
- JDBC tables can be connected via foreign server wrapper
Redesign the handling of errors and exceptions
modified: storage/connect/ha_connect.cc
modified: storage/connect/jdbconn.cpp
modified: storage/connect/jdbconn.h
modified: storage/connect/tabjdbc.cpp
modified: storage/connect/tabjdbc.h
Diffstat (limited to 'storage')
-rw-r--r-- | storage/connect/ha_connect.cc | 34 | ||||
-rw-r--r-- | storage/connect/jdbconn.cpp | 497 | ||||
-rw-r--r-- | storage/connect/jdbconn.h | 5 | ||||
-rw-r--r-- | storage/connect/tabjdbc.cpp | 131 | ||||
-rw-r--r-- | storage/connect/tabjdbc.h | 3 |
5 files changed, 373 insertions, 297 deletions
diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 58a761f442d..0534884e684 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -119,6 +119,7 @@ #undef OFFSET #define NOPARSE +#define NJDBC #if defined(UNIX) #include "osutil.h" #endif // UNIX @@ -128,7 +129,7 @@ #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" @@ -5224,7 +5225,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd, #endif #if defined(JDBC_SUPPORT) 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")); @@ -5325,18 +5326,31 @@ static int connect_assisted_discovery(handlerton *, THD* thd, case TAB_JDBC: if (fnc & FNC_DRIVER) { ok= true; - } else if (!url && !(url= strz(g, create_info->connect_string))) { + } 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); @@ -5775,12 +5789,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/jdbconn.cpp b/storage/connect/jdbconn.cpp index 88557fdd420..1d2242060e1 100644 --- a/storage/connect/jdbconn.cpp +++ b/storage/connect/jdbconn.cpp @@ -38,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 @@ -118,6 +117,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 @@ -155,7 +155,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; @@ -318,12 +317,15 @@ PQRYRES JDBCColumns(PGLOBAL g, char *db, char *table, char *colpat, /**************************************************************************/ PQRYRES JDBCSrcCols(PGLOBAL g, char *src, PJPARM sjp) { + PQRYRES qrp; JDBConn *jcp = new(g)JDBConn(g, NULL); if (jcp->Open(sjp)) return NULL; - return jcp->GetMetaData(g, src); + qrp = jcp->GetMetaData(g, src); + jcp->Close(); + return qrp; } // end of JDBCSrcCols /**************************************************************************/ @@ -361,14 +363,14 @@ PQRYRES JDBCTables(PGLOBAL g, char *db, char *tabpat, char *tabtyp, 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; @@ -642,11 +644,12 @@ JDBConn::JDBConn(PGLOBAL g, TDBJDBC *tdbp) 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; + xqid = xuid = xid = grs = readid = fetchid = typid = errid = nullptr; prepid = xpid = pcid = 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; @@ -676,10 +679,11 @@ JDBConn::JDBConn(PGLOBAL g, TDBJDBC *tdbp) /***********************************************************************/ /* Screen for errors. */ /***********************************************************************/ -char *JDBConn::Check(void) +bool JDBConn::Check(jint rc) { + jstring s; + if (env->ExceptionCheck()) { - char *msg; jthrowable exc = env->ExceptionOccurred(); jmethodID tid = env->GetMethodID(env->FindClass("java/lang/Object"), "toString", "()Ljava/lang/String;"); @@ -688,17 +692,39 @@ char *JDBConn::Check(void) jstring s = (jstring)env->CallObjectMethod(exc, tid); const char *utf = env->GetStringUTFChars(s, (jboolean)false); env->DeleteLocalRef(s); - msg = PlugDup(m_G, utf); + Msg = PlugDup(m_G, utf); } else - msg = "Exception occured"; + Msg = "Exception occured"; env->ExceptionClear(); - return msg; - } // endif Check + } else if (rc < 0) { + s = (jstring)env->CallObjectMethod(job, errid); + Msg = (char*)env->GetStringUTFChars(s, (jboolean)false); + } else + Msg = NULL; - return NULL; + 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. */ @@ -758,15 +784,17 @@ 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 /***********************************************************************/ @@ -859,6 +887,7 @@ bool JDBConn::GetJVM(PGLOBAL g) /***********************************************************************/ int JDBConn::Open(PJPARM sop) { + bool err = false; PGLOBAL& g = m_G; // Link or check whether jvm library was linked @@ -881,8 +910,10 @@ int JDBConn::Open(PJPARM sop) } // endif rc } else { - // Create a new jvm - PSTRG jpop = new(g)STRING(g, 512, "-Djava.class.path="); + /*******************************************************************/ + /* Create a new jvm */ + /*******************************************************************/ + PSTRG jpop = new(g)STRING(g, 512, "-Djava.class.path=."); char *cp = NULL; char sep; @@ -897,23 +928,21 @@ int JDBConn::Open(PJPARM sop) JavaVMOption* options = new JavaVMOption[1]; // JVM invocation options // where to find java .class - if ((cp = PlugDup(m_G, getenv("CLASSPATH")))) - jpop->Append(cp); - - if (trace) { - htrc("CLASSPATH=%s\n", getenv("CLASSPATH")); - htrc("ClassPath=%s\n", ClassPath); - } // endif trace - if (ClassPath && *ClassPath) { - if (cp) - jpop->Append(sep); - + jpop->Append(sep); jpop->Append(ClassPath); } // endif ClassPath - if (trace) + 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(); //options[1].optionString = "-verbose:jni"; @@ -981,7 +1010,7 @@ int JDBConn::Open(PJPARM sop) jstring path = env->NewStringUTF(jpath); rc = env->CallStaticIntMethod(jdi, alp, path); - if ((msg = Check())) { + if ((msg = Check(rc))) { strcpy(g->Message, msg); env->DeleteLocalRef(path); return RC_FX; @@ -1022,33 +1051,36 @@ int JDBConn::Open(PJPARM sop) 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 - 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 + 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) @@ -1065,23 +1097,17 @@ int JDBConn::Open(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; @@ -1092,43 +1118,37 @@ int JDBConn::Open(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; @@ -1139,44 +1159,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 @@ -1184,7 +1189,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 @@ -1201,15 +1206,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); @@ -1227,15 +1225,15 @@ 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 if ((rc = env->CallIntMethod(job, did))) - printf("jdbcDisconnect: rc=%d", (int)rc); + 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())) - printf("DetachCurrentThread: rc = %d", (int)rc); + if ((rc = jvm->DetachCurrentThread()) != JNI_OK) + printf("DetachCurrentThread: rc=%d\n", (int)rc); //rc = jvm->DestroyJavaVM(); m_Opened = false; @@ -1249,7 +1247,6 @@ void JDBConn::Close() void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val) { PGLOBAL& g = m_G; - char *msg; jint ctyp; jlong dtv; jstring cn, jn = nullptr; @@ -1262,10 +1259,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 ((msg = Check())) { - sprintf(g->Message, "Getting ctyp: %s", msg); + if (Check((ctyp == 666) ? -1 : 1)) { + sprintf(g->Message, "Getting ctyp: %s", Msg); longjmp(g->jumper[g->jump_level], TYPE_AM_JDBC); } // endif Check @@ -1303,6 +1301,7 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val) break; case 8: // DOUBLE + case 2: // NUMERIC case 3: // DECIMAL fldid = env->GetMethodID(jdi, "DoubleField", "(ILjava/lang/String;)D"); @@ -1372,11 +1371,11 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val) val->Reset(); } // endswitch Type - if ((msg = Check())) { + if (Check()) { if (rank == 0) env->DeleteLocalRef(jn); - sprintf(g->Message, "SetColumnValue: %s rank=%d ctyp=%d", msg, rank, (int)ctyp); + sprintf(g->Message, "SetColumnValue: %s rank=%d ctyp=%d", Msg, rank, (int)ctyp); longjmp(g->jumper[g->jump_level], TYPE_AM_JDBC); } // endif Check @@ -1390,21 +1389,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 /***********************************************************************/ @@ -1412,32 +1412,25 @@ 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; } // end of ExecuteQuery @@ -1447,34 +1440,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"); + // 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); - if (xuid == nullptr) { - strcpy(g->Message, "Cannot find method ExecuteUpdate"); - return RC_FX; - } // endif !xuid - - } // endif xuid + 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); - qry = env->NewStringUTF(sql); - n = env->CallIntMethod(job, xuid, qry); - env->DeleteLocalRef(qry); + env->DeleteLocalRef(qry); + } // endif xuid - 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 - - return RC_OK; + return rc; } // end of ExecuteUpdate /***********************************************************************/ @@ -1507,32 +1493,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 @@ -1542,8 +1517,7 @@ int JDBConn::ExecuteSQL(void) bool JDBConn::SetParam(JDBCCOL *colp) { PGLOBAL& g = m_G; - char *msg; - int rc = false; + bool rc = false; PVAL val = colp->GetValue(); jint n, i = (jint)colp->GetRank(); jshort s; @@ -1557,58 +1531,38 @@ bool JDBConn::SetParam(JDBCCOL *colp) 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 find method SetDoubleParm"); + if (gmID(g, setid, "SetDoubleParm", "(ID)V")) return true; - } // endif setid d = (jdouble)val->GetFloatValue(); env->CallVoidMethod(job, setid, i, d); @@ -1627,11 +1581,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; @@ -1640,8 +1591,8 @@ bool JDBConn::SetParam(JDBCCOL *colp) return true; } // endswitch Type - if ((msg = Check())) { - sprintf(g->Message, "SetParam: col=%s msg=%s", colp->GetName(), msg); + if (Check()) { + sprintf(g->Message, "SetParam: col=%s msg=%s", colp->GetName(), Msg); rc = true; } // endif msg @@ -1707,14 +1658,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, @@ -1766,7 +1713,7 @@ bool JDBConn::SetParam(JDBCCOL *colp) ushort i; jint *n = nullptr; jstring label; - jmethodID colid; + jmethodID colid = nullptr; int rc = ExecSQLcommand(src); if (rc == RC_NF) { @@ -1779,20 +1726,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); @@ -1813,11 +1748,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); @@ -1835,7 +1787,6 @@ bool JDBConn::SetParam(JDBCCOL *colp) /* Cleanup */ env->ReleaseIntArrayElements(val, n, 0); - Close(); /************************************************************************/ /* Return the result pointer for use by GetData routines. */ @@ -1962,7 +1913,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" @@ -2008,16 +1959,18 @@ 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); @@ -2061,13 +2014,15 @@ bool JDBConn::SetParam(JDBCCOL *colp) // Now fetch the result for (i = 0; i < qrp->Maxres; i++) { - if ((rc = Fetch(0)) == 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; - } else if (rc < 0) - return -1; + } // endif rc for (n = 0, crp = qrp->Colresp; crp; n++, crp = crp->Next) { SetColumnValue(n + 1, nullptr, pval[n]); diff --git a/storage/connect/jdbconn.h b/storage/connect/jdbconn.h index 4014a52cdcc..d8c36c6a637 100644 --- a/storage/connect/jdbconn.h +++ b/storage/connect/jdbconn.h @@ -120,7 +120,8 @@ public: // JDBC operations protected: - char *Check(void); + 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 Free(void); @@ -150,9 +151,11 @@ 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 //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/tabjdbc.cpp b/storage/connect/tabjdbc.cpp index 37850ce6358..fa5f093bae6 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" @@ -102,10 +103,106 @@ JDBCDEF::JDBCDEF(void) } // 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, "%d", 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) { + int rc = RC_OK; + Driver = GetStringCatInfo(g, "Driver", NULL); Desc = Url = GetStringCatInfo(g, "Connect", NULL); @@ -120,28 +217,33 @@ bool JDBCDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) } // 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); + 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); @@ -274,6 +376,7 @@ TDBJDBC::TDBJDBC(PJDBCDEF tdp) : TDBASE(tdp) Ncol = 0; Nparm = 0; Placed = false; + Prepared = false; Werr = false; Rerr = false; Ops.Fsize = Ops.CheckSize(Rows); diff --git a/storage/connect/tabjdbc.h b/storage/connect/tabjdbc.h index 1624b903610..537276a6a7f 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; @@ -44,6 +45,8 @@ 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 |