summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergei Golubchik <serg@mariadb.org>2016-06-28 22:12:50 +0200
committerSergei Golubchik <serg@mariadb.org>2016-06-28 22:12:50 +0200
commit736f821c420954912464b9ae521acc5b768438cc (patch)
tree6348f794bb3b1ec24d7064000b7ea6e941f9ec2c
parent62e0a4552f3b4a932f9aa055579dad716b371b9b (diff)
parent7e64b079680b5f0f1e1cb735e3c83e45e96ec0e3 (diff)
downloadmariadb-git-736f821c420954912464b9ae521acc5b768438cc.tar.gz
Merge branch 'connect/10.1' into 10.1
-rw-r--r--.gitattributes3
-rw-r--r--.gitignore2
-rw-r--r--storage/connect/JdbcInterface.classbin15215 -> 15215 bytes
-rw-r--r--storage/connect/JdbcInterface.java2
-rw-r--r--storage/connect/ha_connect.cc49
-rw-r--r--storage/connect/jdbccat.h8
-rw-r--r--storage/connect/jdbconn.cpp1094
-rw-r--r--storage/connect/jdbconn.h67
-rw-r--r--storage/connect/odbccat.h2
-rw-r--r--storage/connect/odbconn.cpp4
-rw-r--r--storage/connect/tabjdbc.cpp180
-rw-r--r--storage/connect/tabjdbc.h21
-rw-r--r--storage/connect/tabodbc.cpp27
-rw-r--r--storage/connect/tabodbc.h15
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
index 8c5ba6439f3..51a0e69bad5 100644
--- a/storage/connect/JdbcInterface.class
+++ b/storage/connect/JdbcInterface.class
Binary files differ
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