summaryrefslogtreecommitdiff
path: root/storage/connect/jdbconn.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'storage/connect/jdbconn.cpp')
-rw-r--r--storage/connect/jdbconn.cpp365
1 files changed, 239 insertions, 126 deletions
diff --git a/storage/connect/jdbconn.cpp b/storage/connect/jdbconn.cpp
index 4c21c2c9681..ddbc3115f0b 100644
--- a/storage/connect/jdbconn.cpp
+++ b/storage/connect/jdbconn.cpp
@@ -1,7 +1,7 @@
/************ Jdbconn C++ Functions Source Code File (.CPP) ************/
-/* Name: JDBCONN.CPP Version 1.1 */
+/* Name: JDBCONN.CPP Version 1.2 */
/* */
-/* (C) Copyright to the author Olivier BERTRAND 2016-2017 */
+/* (C) Copyright to the author Olivier BERTRAND 2016-2018 */
/* */
/* This file contains the JDBC connection classes functions. */
/***********************************************************************/
@@ -116,10 +116,26 @@ int TranslateJDBCType(int stp, char *tn, int prec, int& len, char& v)
return TYPE_ERROR;
else
len = MY_MIN(abs(len), GetConvSize());
+
// Pass through
case 12: // VARCHAR
+ if (tn && !stricmp(tn, "TEXT"))
+ // Postgresql returns 12 for TEXT
+ if (GetTypeConv() == TPC_NO)
+ return TYPE_ERROR;
+
+ // Postgresql can return this
+ if (len == 0x7FFFFFFF)
+ len = GetConvSize();
+
+ // Pass through
case -9: // NVARCHAR (unicode)
+ // Postgresql can return this when size is unknown
+ if (len == 0x7FFFFFFF)
+ len = GetConvSize();
+
v = 'V';
+ // Pass through
case 1: // CHAR
case -15: // NCHAR (unicode)
case -8: // ROWID
@@ -154,13 +170,13 @@ int TranslateJDBCType(int stp, char *tn, int prec, int& len, char& v)
case 91: // DATE, YEAR
type = TYPE_DATE;
- if (!tn || toupper(tn[0]) != 'Y') {
- len = 10;
- v = 'D';
- } else {
- len = 4;
- v = 'Y';
- } // endif len
+ if (!tn || toupper(tn[0]) != 'Y') {
+ len = 10;
+ v = 'D';
+ } else {
+ len = 4;
+ v = 'Y';
+ } // endif len
break;
case 92: // TIME
@@ -192,6 +208,104 @@ int TranslateJDBCType(int stp, char *tn, int prec, int& len, char& v)
return type;
} // end of TranslateJDBCType
+ /***********************************************************************/
+ /* A helper class to split an optionally qualified table name into */
+ /* components. */
+ /* These formats are understood: */
+ /* "CatalogName.SchemaName.TableName" */
+ /* "SchemaName.TableName" */
+ /* "TableName" */
+ /***********************************************************************/
+class SQLQualifiedName {
+ static const uint max_parts = 3; // Catalog.Schema.Table
+ MYSQL_LEX_STRING m_part[max_parts];
+ char m_buf[512];
+
+ void lex_string_set(MYSQL_LEX_STRING *S, char *str, size_t length)
+ {
+ S->str = str;
+ S->length = length;
+ } // end of lex_string_set
+
+ void lex_string_shorten_down(MYSQL_LEX_STRING *S, size_t offs)
+ {
+ DBUG_ASSERT(offs <= S->length);
+ S->str += offs;
+ S->length -= offs;
+ } // end of lex_string_shorten_down
+
+ /*********************************************************************/
+ /* Find the rightmost '.' delimiter and return the length */
+ /* of the qualifier, including the rightmost '.' delimier. */
+ /* For example, for the string {"a.b.c",5} it will return 4, */
+ /* which is the length of the qualifier "a.b." */
+ /*********************************************************************/
+ size_t lex_string_find_qualifier(MYSQL_LEX_STRING *S)
+ {
+ size_t i;
+ for (i = S->length; i > 0; i--)
+ {
+ if (S->str[i - 1] == '.')
+ {
+ S->str[i - 1] = '\0';
+ return i;
+ }
+ }
+ return 0;
+ } // end of lex_string_find_qualifier
+
+public:
+ /*********************************************************************/
+ /* Initialize to the given optionally qualified name. */
+ /* NULL pointer in "name" is supported. */
+ /* name qualifier has precedence over schema. */
+ /*********************************************************************/
+ SQLQualifiedName(JCATPARM *cap)
+ {
+ const char *name = (const char *)cap->Tab;
+ char *db = (char *)cap->DB;
+ size_t len, i;
+
+ // Initialize the parts
+ for (i = 0; i < max_parts; i++)
+ lex_string_set(&m_part[i], NULL, 0);
+
+ if (name) {
+ // Initialize the first (rightmost) part
+ lex_string_set(&m_part[0], m_buf,
+ strmake(m_buf, name, sizeof(m_buf) - 1) - m_buf);
+
+ // Initialize the other parts, if exist.
+ for (i = 1; i < max_parts; i++) {
+ if (!(len = lex_string_find_qualifier(&m_part[i - 1])))
+ break;
+
+ lex_string_set(&m_part[i], m_part[i - 1].str, len - 1);
+ lex_string_shorten_down(&m_part[i - 1], len);
+ } // endfor i
+
+ } // endif name
+
+ // If it was not specified, set schema as the passed db name
+ if (db && !m_part[1].length)
+ lex_string_set(&m_part[1], db, strlen(db));
+
+ } // end of SQLQualifiedName
+
+ char *ptr(uint i)
+ {
+ DBUG_ASSERT(i < max_parts);
+ return (char *)(m_part[i].length ? m_part[i].str : NULL);
+ } // end of ptr
+
+ size_t length(uint i)
+ {
+ DBUG_ASSERT(i < max_parts);
+ return m_part[i].length;
+ } // end of length
+
+}; // end of class SQLQualifiedName
+
/***********************************************************************/
/* Allocate the structure used to refer to the result set. */
/***********************************************************************/
@@ -270,7 +384,7 @@ PQRYRES JDBCColumns(PGLOBAL g, PCSZ db, PCSZ table, PCSZ colpat,
length[11] = 255;
} // endif jcp
- if (trace)
+ if (trace(1))
htrc("JDBCColumns: max=%d len=%d,%d,%d,%d\n",
maxres, length[0], length[1], length[2], length[3]);
@@ -287,7 +401,7 @@ PQRYRES JDBCColumns(PGLOBAL g, PCSZ db, PCSZ table, PCSZ colpat,
if (info || !qrp) // Info table
return qrp;
- if (trace)
+ if (trace(1))
htrc("Getting col results ncol=%d\n", qrp->Nbcol);
if (!(cap = AllocCatInfo(g, JCAT_COL, db, table, qrp)))
@@ -303,7 +417,7 @@ PQRYRES JDBCColumns(PGLOBAL g, PCSZ db, PCSZ table, PCSZ colpat,
qrp->Nblin = n;
// ResetNullValues(cap);
- if (trace)
+ if (trace(1))
htrc("Columns: NBCOL=%d NBLIN=%d\n", qrp->Nbcol, qrp->Nblin);
} else
@@ -394,7 +508,7 @@ PQRYRES JDBCTables(PGLOBAL g, PCSZ db, PCSZ tabpat, PCSZ tabtyp,
length[4] = 255;
} // endif info
- if (trace)
+ if (trace(1))
htrc("JDBCTables: max=%d len=%d,%d\n", maxres, length[0], length[1]);
/************************************************************************/
@@ -417,7 +531,7 @@ PQRYRES JDBCTables(PGLOBAL g, PCSZ db, PCSZ tabpat, PCSZ tabtyp,
cap->Pat = tabtyp;
- if (trace)
+ if (trace(1))
htrc("Getting table results ncol=%d\n", cap->Qrp->Nbcol);
/************************************************************************/
@@ -427,7 +541,7 @@ PQRYRES JDBCTables(PGLOBAL g, PCSZ db, PCSZ tabpat, PCSZ tabtyp,
qrp->Nblin = n;
// ResetNullValues(cap);
- if (trace)
+ if (trace(1))
htrc("Tables: NBCOL=%d NBLIN=%d\n", qrp->Nbcol, qrp->Nblin);
} else
@@ -475,7 +589,7 @@ PQRYRES JDBCDrivers(PGLOBAL g, int maxres, bool info)
} else
maxres = 0;
- if (trace)
+ if (trace(1))
htrc("JDBCDrivers: max=%d len=%d\n", maxres, length[0]);
/************************************************************************/
@@ -519,7 +633,7 @@ JDBConn::JDBConn(PGLOBAL g, PCSZ wrapper) : JAVAConn(g, wrapper)
xqid = xuid = xid = grs = readid = fetchid = typid = errid = nullptr;
prepid = xpid = pcid = nullptr;
chrfldid = intfldid = dblfldid = fltfldid = bigfldid = nullptr;
- objfldid = datfldid = timfldid = tspfldid = nullptr;
+ objfldid = datfldid = timfldid = tspfldid = uidfldid = nullptr;
DiscFunc = "JdbcDisconnect";
m_Ncol = 0;
m_Aff = 0;
@@ -535,12 +649,84 @@ JDBConn::JDBConn(PGLOBAL g, PCSZ wrapper) : JAVAConn(g, wrapper)
m_IDQuoteChar[1] = 0;
} // end of JDBConn
-//JDBConn::~JDBConn()
-// {
-//if (Connected())
-// EndCom();
+/***********************************************************************/
+/* Search for UUID columns. */
+/***********************************************************************/
+bool JDBConn::SetUUID(PGLOBAL g, PTDBJDBC tjp)
+{
+ int ncol, ctyp;
+ bool brc = true;
+ PCSZ fnc = "GetColumns";
+ PCOL colp;
+ JCATPARM *cap;
+ //jint jtyp;
+ jboolean rc = false;
+ jobjectArray parms;
+ jmethodID catid = nullptr;
+
+ if (gmID(g, catid, fnc, "([Ljava/lang/String;)I"))
+ return true;
+ else if (gmID(g, intfldid, "IntField", "(ILjava/lang/String;)I"))
+ return true;
+ else if (gmID(g, readid, "ReadNext", "()I"))
+ return true;
+
+ cap = AllocCatInfo(g, JCAT_COL, tjp->Schema, tjp->TableName, NULL);
+ SQLQualifiedName name(cap);
+
+ // Build the java string array
+ parms = env->NewObjectArray(4, env->FindClass("java/lang/String"), NULL);
+ 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)));
+
+ for (colp = tjp->GetColumns(); colp; colp = colp->GetNext()) {
+ env->SetObjectArrayElement(parms, 3, env->NewStringUTF(colp->GetName()));
+ ncol = env->CallIntMethod(job, catid, parms);
+
+ if (Check(ncol)) {
+ sprintf(g->Message, "%s: %s", fnc, Msg);
+ goto err;
+ } // endif Check
+
+ rc = env->CallBooleanMethod(job, readid);
+
+ if (Check(rc)) {
+ sprintf(g->Message, "ReadNext: %s", Msg);
+ goto err;
+ } else if (rc == 0) {
+ sprintf(g->Message, "table %s does not exist", tjp->TableName);
+ goto err;
+ } // endif rc
-// } // end of ~JDBConn
+ // Returns 666 is case of error
+ //jtyp = env->CallIntMethod(job, typid, 5, nullptr);
+
+ //if (Check((jtyp == 666) ? -1 : 1)) {
+ // sprintf(g->Message, "Getting jtyp: %s", Msg);
+ // goto err;
+ //} // endif ctyp
+
+ ctyp = (int)env->CallIntMethod(job, intfldid, 5, nullptr);
+
+ if (Check(ctyp)) {
+ sprintf(g->Message, "Getting ctyp: %s", Msg);
+ goto err;
+ } // endif ctyp
+
+ if (ctyp == 1111)
+ ((PJDBCCOL)colp)->uuid = true;
+
+ } // endfor colp
+
+ // All is Ok
+ brc = false;
+
+ err:
+ // Not used anymore
+ env->DeleteLocalRef(parms);
+ return brc;
+} // end of SetUUID
/***********************************************************************/
/* Utility routine. */
@@ -586,7 +772,7 @@ bool JDBConn::Connect(PJPARM sop)
int irc = RC_FX;
bool err = false;
jint rc;
- jboolean jt = (trace > 0);
+ jboolean jt = (trace(1));
PGLOBAL& g = m_G;
/*******************************************************************/
@@ -770,6 +956,7 @@ int JDBConn::Rewind(PCSZ sql)
/***********************************************************************/
void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val)
{
+ const char *field;
PGLOBAL& g = m_G;
jint ctyp;
jstring cn, jn = nullptr;
@@ -793,6 +980,11 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val)
if (!gmID(g, objfldid, "ObjectField", "(ILjava/lang/String;)Ljava/lang/Object;")) {
jb = env->CallObjectMethod(job, objfldid, (jint)rank, jn);
+ if (Check(0)) {
+ sprintf(g->Message, "Getting jp: %s", Msg);
+ throw (int)TYPE_AM_JDBC;
+ } // endif Check
+
if (jb == nullptr) {
val->Reset();
val->SetNull(true);
@@ -818,7 +1010,7 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val)
cn = nullptr;
if (cn) {
- const char *field = env->GetStringUTFChars(cn, (jboolean)false);
+ field = env->GetStringUTFChars(cn, (jboolean)false);
val->SetValue_psz((PSZ)field);
} else
val->Reset();
@@ -885,6 +1077,19 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val)
break;
case java.sql.Types.BOOLEAN:
System.out.print(jdi.BooleanField(i)); */
+ case 1111: // UUID
+ if (!gmID(g, uidfldid, "UuidField", "(ILjava/lang/String;)Ljava/lang/String;"))
+ cn = (jstring)env->CallObjectMethod(job, uidfldid, (jint)rank, jn);
+ else
+ cn = nullptr;
+
+ if (cn) {
+ const char *field = env->GetStringUTFChars(cn, (jboolean)false);
+ val->SetValue_psz((PSZ)field);
+ } else
+ val->Reset();
+
+ break;
case 0: // NULL
val->SetNull(true);
// passthru
@@ -1055,7 +1260,14 @@ bool JDBConn::SetParam(JDBCCOL *colp)
if (gmID(g, setid, "SetNullParm", "(II)I"))
return true;
- jrc = env->CallIntMethod(job, setid, i, (jint)GetJDBCType(val->GetType()));
+ jrc = env->CallIntMethod(job, setid, i,
+ (colp->uuid ? 1111 : (jint)GetJDBCType(val->GetType())));
+ } else if (colp->uuid) {
+ if (gmID(g, setid, "SetUuidParm", "(ILjava/lang/String;)V"))
+ return true;
+
+ jst = env->NewStringUTF(val->GetCharValue());
+ env->CallVoidMethod(job, setid, i, jst);
} else switch (val->GetType()) {
case TYPE_STRING:
if (gmID(g, setid, "SetStringParm", "(ILjava/lang/String;)V"))
@@ -1275,105 +1487,6 @@ bool JDBConn::SetParam(JDBCCOL *colp)
} // end of GetMetaData
/***********************************************************************/
- /* A helper class to split an optionally qualified table name into */
- /* components. */
- /* These formats are understood: */
- /* "CatalogName.SchemaName.TableName" */
- /* "SchemaName.TableName" */
- /* "TableName" */
- /***********************************************************************/
- class SQLQualifiedName
- {
- static const uint max_parts= 3; // Catalog.Schema.Table
- MYSQL_LEX_STRING m_part[max_parts];
- char m_buf[512];
-
- void lex_string_set(MYSQL_LEX_STRING *S, char *str, size_t length)
- {
- S->str= str;
- S->length= length;
- } // end of lex_string_set
-
- void lex_string_shorten_down(MYSQL_LEX_STRING *S, size_t offs)
- {
- DBUG_ASSERT(offs <= S->length);
- S->str+= offs;
- S->length-= offs;
- } // end of lex_string_shorten_down
-
- /*********************************************************************/
- /* Find the rightmost '.' delimiter and return the length */
- /* of the qualifier, including the rightmost '.' delimier. */
- /* For example, for the string {"a.b.c",5} it will return 4, */
- /* which is the length of the qualifier "a.b." */
- /*********************************************************************/
- size_t lex_string_find_qualifier(MYSQL_LEX_STRING *S)
- {
- size_t i;
- for (i= S->length; i > 0; i--)
- {
- if (S->str[i - 1] == '.')
- {
- S->str[i - 1]= '\0';
- return i;
- }
- }
- return 0;
- } // end of lex_string_find_qualifier
-
- public:
- /*********************************************************************/
- /* Initialize to the given optionally qualified name. */
- /* NULL pointer in "name" is supported. */
- /* name qualifier has precedence over schema. */
- /*********************************************************************/
- SQLQualifiedName(JCATPARM *cap)
- {
- const char *name = (const char *)cap->Tab;
- char *db = (char *)cap->DB;
- size_t len, i;
-
- // Initialize the parts
- for (i = 0; i < max_parts; i++)
- lex_string_set(&m_part[i], NULL, 0);
-
- if (name) {
- // Initialize the first (rightmost) part
- lex_string_set(&m_part[0], m_buf,
- strmake(m_buf, name, sizeof(m_buf) - 1) - m_buf);
-
- // Initialize the other parts, if exist.
- for (i= 1; i < max_parts; i++) {
- if (!(len= lex_string_find_qualifier(&m_part[i - 1])))
- break;
-
- lex_string_set(&m_part[i], m_part[i - 1].str, len - 1);
- lex_string_shorten_down(&m_part[i - 1], len);
- } // endfor i
-
- } // endif name
-
- // If it was not specified, set schema as the passed db name
- if (db && !m_part[1].length)
- lex_string_set(&m_part[1], db, strlen(db));
-
- } // end of SQLQualifiedName
-
- char *ptr(uint i)
- {
- DBUG_ASSERT(i < max_parts);
- return (char *)(m_part[i].length ? m_part[i].str : NULL);
- } // end of ptr
-
- size_t length(uint i)
- {
- DBUG_ASSERT(i < max_parts);
- return m_part[i].length;
- } // end of length
-
- }; // end of class SQLQualifiedName
-
- /***********************************************************************/
/* Allocate recset and call SQLTables, SQLColumns or SQLPrimaryKeys. */
/***********************************************************************/
int JDBConn::GetCatInfo(JCATPARM *cap)
@@ -1443,7 +1556,7 @@ bool JDBConn::SetParam(JDBCCOL *colp)
// Not used anymore
env->DeleteLocalRef(parms);
- if (trace)
+ if (trace(1))
htrc("Method %s returned %d columns\n", fnc, ncol);
// n because we no more ignore the first column
@@ -1488,7 +1601,7 @@ bool JDBConn::SetParam(JDBCCOL *colp)
sprintf(g->Message, "Fetch: %s", Msg);
return -1;
} if (rc == 0) {
- if (trace)
+ if (trace(1))
htrc("End of fetches i=%d\n", i);
break;