diff options
author | Olivier Bertrand <bertrandop@gmail.com> | 2018-03-14 11:31:28 +0100 |
---|---|---|
committer | Olivier Bertrand <bertrandop@gmail.com> | 2018-03-14 11:31:28 +0100 |
commit | a0f47c39b7a706ad8fc4770af87ac7187aaf3ffd (patch) | |
tree | d7a3af1f3c25404973490ace4b5118ee4b87d937 | |
parent | c195e05132466fb017730d6b19c46681b33a6909 (diff) | |
parent | 46defc4373832dfad3b2676df8b90fd4f15eeb24 (diff) | |
download | mariadb-git-a0f47c39b7a706ad8fc4770af87ac7187aaf3ffd.tar.gz |
Merge branch 'ob-10.1' into 10.1
-rw-r--r-- | storage/connect/Client.java | 27 | ||||
-rw-r--r-- | storage/connect/JavaWrappers.jar | bin | 44053 -> 19192 bytes | |||
-rw-r--r-- | storage/connect/JdbcInterface.java | 54 | ||||
-rw-r--r-- | storage/connect/PostgresqlInterface.java | 5 | ||||
-rw-r--r-- | storage/connect/global.h | 6 | ||||
-rw-r--r-- | storage/connect/ha_connect.cc | 21 | ||||
-rw-r--r-- | storage/connect/jdbconn.cpp | 339 | ||||
-rw-r--r-- | storage/connect/jdbconn.h | 11 | ||||
-rw-r--r-- | storage/connect/mysql-test/connect/r/jdbc_postgresql.result | 35 | ||||
-rw-r--r-- | storage/connect/mysql-test/connect/std_data/JavaWrappers.jar | bin | 0 -> 19192 bytes | |||
-rw-r--r-- | storage/connect/mysql-test/connect/t/jdbc_postgresql.test | 33 | ||||
-rw-r--r-- | storage/connect/mysql-test/connect/t/jdbconn.inc | 7 | ||||
-rw-r--r-- | storage/connect/plgdbsem.h | 3 | ||||
-rw-r--r-- | storage/connect/tabjdbc.cpp | 11 | ||||
-rw-r--r-- | storage/connect/tabjdbc.h | 2 |
15 files changed, 383 insertions, 171 deletions
diff --git a/storage/connect/Client.java b/storage/connect/Client.java index aaf1b7bf2f8..afa54fa4256 100644 --- a/storage/connect/Client.java +++ b/storage/connect/Client.java @@ -1,9 +1,13 @@ + package wrappers; import java.io.BufferedReader; import java.io.Console; import java.io.IOException; import java.io.InputStreamReader; +import java.sql.Date; +import java.sql.Time; +import java.sql.Timestamp; public class Client { static boolean DEBUG = true; @@ -58,6 +62,9 @@ public class Client { String query; System.out.println("Successfully connected to " + parms[1]); + s = jdi.GetQuoteString(); + System.out.println("Qstr = '" + s + "'"); + while ((query = getLine("Query: ", false)) != null) { n = jdi.Execute(query); System.out.println("Returned n = " + n); @@ -79,7 +86,11 @@ public class Client { private static void PrintResult(int ncol) { // Get result set meta data int i; + Date date = new Date(0); + Time time = new Time(0); + Timestamp tsp = new Timestamp(0); String columnName; + Object job; // Get the column names; column indices start from 1 for (i = 1; i <= ncol; i++) { @@ -112,6 +123,7 @@ public class Client { case java.sql.Types.VARCHAR: case java.sql.Types.LONGVARCHAR: case java.sql.Types.CHAR: + case 1111: System.out.print(jdi.StringField(i, null)); break; case java.sql.Types.INTEGER: @@ -120,14 +132,17 @@ public class Client { case java.sql.Types.BIGINT: System.out.print(jdi.BigintField(i, null)); break; - case java.sql.Types.TIMESTAMP: - System.out.print(jdi.TimestampField(i, null)); - break; case java.sql.Types.TIME: - System.out.print(jdi.TimeField(i, null)); + time.setTime((long)jdi.TimeField(i, null) * 1000); + System.out.print(time); break; case java.sql.Types.DATE: - System.out.print(jdi.DateField(i, null)); + date.setTime((long)jdi.DateField(i, null) * 1000); + System.out.print(date); + break; + case java.sql.Types.TIMESTAMP: + tsp.setTime((long)jdi.TimestampField(i, null) * 1000); + System.out.print(tsp); break; case java.sql.Types.SMALLINT: System.out.print(jdi.IntField(i, null)); @@ -141,6 +156,8 @@ public class Client { case java.sql.Types.BOOLEAN: System.out.print(jdi.BooleanField(i, null)); default: + job = jdi.ObjectField(i, null); + System.out.print(job.toString()); break; } // endswitch Type diff --git a/storage/connect/JavaWrappers.jar b/storage/connect/JavaWrappers.jar Binary files differindex ef407f6a9c2..33b29e7685b 100644 --- a/storage/connect/JavaWrappers.jar +++ b/storage/connect/JavaWrappers.jar diff --git a/storage/connect/JdbcInterface.java b/storage/connect/JdbcInterface.java index a1b1360e6ea..72ee4ab0d39 100644 --- a/storage/connect/JdbcInterface.java +++ b/storage/connect/JdbcInterface.java @@ -1,10 +1,22 @@ package wrappers; -import java.math.*; -import java.sql.*; +import java.math.BigDecimal; +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.Date; +import java.sql.Driver; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.sql.Statement; +import java.sql.Time; +import java.sql.Timestamp; import java.util.Collections; import java.util.Hashtable; import java.util.List; +import java.util.UUID; import javax.sql.DataSource; @@ -223,6 +235,24 @@ public class JdbcInterface { } // end of SetTimestampParm + public void SetUuidParm(int i, String s) { + try { + UUID uuid; + + if (s == null) + uuid = null; + else if (s.isEmpty()) + uuid = UUID.randomUUID(); + else + uuid = UUID.fromString(s); + + pstmt.setObject(i, uuid); + } catch (Exception e) { + SetErrmsg(e); + } // end try/catch + + } // end of SetUuidParm + public int SetNullParm(int i, int typ) { int rc = 0; @@ -481,6 +511,8 @@ public class JdbcInterface { System.out.println("Executing query '" + query + "'"); try { + if (rs != null) + rs.close(); rs = stmt.executeQuery(query); rsmd = rs.getMetaData(); ncol = rsmd.getColumnCount(); @@ -708,7 +740,7 @@ public class JdbcInterface { return 0; } // end of TimestampField - public Object ObjectField(int n, String name) { + public Object ObjectField(int n, String name) { if (rs == null) { System.out.println("No result set"); } else try { @@ -720,6 +752,22 @@ public class JdbcInterface { return null; } // end of ObjectField + public String UuidField(int n, String name) { + Object job; + + if (rs == null) { + System.out.println("No result set"); + } else + try { + job = (n > 0) ? rs.getObject(n) : rs.getObject(name); + return job.toString(); + } catch (SQLException se) { + SetErrmsg(se); + } // end try/catch + + return null; + } // end of UuidField + public int GetDrivers(String[] s, int mxs) { int n = 0; List<Driver> drivers = Collections.list(DriverManager.getDrivers()); diff --git a/storage/connect/PostgresqlInterface.java b/storage/connect/PostgresqlInterface.java index adce0616a1b..9f611eeb23b 100644 --- a/storage/connect/PostgresqlInterface.java +++ b/storage/connect/PostgresqlInterface.java @@ -1,9 +1,10 @@ package wrappers; -import java.sql.*; +import java.sql.SQLException; import java.util.Hashtable; import javax.sql.DataSource; + import org.postgresql.jdbc2.optional.PoolingDataSource; public class PostgresqlInterface extends JdbcInterface { @@ -19,7 +20,7 @@ public class PostgresqlInterface extends JdbcInterface { } // end of constructor - @Override + @Override public int JdbcConnect(String[] parms, int fsize, boolean scrollable) { int rc = 0; String url = parms[1]; diff --git a/storage/connect/global.h b/storage/connect/global.h index d8d03f606ba..472d09408c3 100644 --- a/storage/connect/global.h +++ b/storage/connect/global.h @@ -220,7 +220,6 @@ DllExport BOOL PlugIsAbsolutePath(LPCSTR path); DllExport bool AllocSarea(PGLOBAL, uint); DllExport void FreeSarea(PGLOBAL); DllExport BOOL PlugSubSet(PGLOBAL, void *, uint); - void *PlugSubAlloc(PGLOBAL, void *, size_t); // Does throw DllExport char *PlugDup(PGLOBAL g, const char *str); DllExport void *MakePtr(void *, OFFSET); DllExport void htrc(char const *fmt, ...); @@ -231,4 +230,9 @@ DllExport uint GetTraceValue(void); } // extern "C" #endif +/***********************************************************************/ +/* Non exported routine declarations. */ +/***********************************************************************/ +void *PlugSubAlloc(PGLOBAL, void *, size_t); // Does throw + /*-------------------------- End of Global.H --------------------------*/ diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 2efed93ee2a..c878bf2a7de 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -174,9 +174,9 @@ #define JSONMAX 10 // JSON Default max grp size extern "C" { - char version[]= "Version 1.06.0006 February 02, 2018"; + char version[]= "Version 1.06.0007 March 11, 2018"; #if defined(__WIN__) - char compver[]= "Version 1.06.0006 " __DATE__ " " __TIME__; + char compver[]= "Version 1.06.0007 " __DATE__ " " __TIME__; char slash= '\\'; #else // !__WIN__ char slash= '/'; @@ -288,11 +288,16 @@ static MYSQL_THDVAR_SET( 0, // def (NO) &xtrace_typelib); // typelib - // Getting exact info values +// Getting exact info values static MYSQL_THDVAR_BOOL(exact_info, PLUGIN_VAR_RQCMDARG, "Getting exact info values", NULL, NULL, 0); +// Enabling cond_push +static MYSQL_THDVAR_BOOL(cond_push, PLUGIN_VAR_RQCMDARG, + "Enabling cond_push", + NULL, NULL, 1); // YES by default + /** Temporary file usage: no: Not using temporary file @@ -427,6 +432,7 @@ handlerton *connect_hton= NULL; uint GetTraceValue(void) {return (uint)(connect_hton ? THDVAR(current_thd, xtrace) : 0);} bool ExactInfo(void) {return THDVAR(current_thd, exact_info);} +bool CondPushEnabled(void) {return THDVAR(current_thd, cond_push);} USETEMP UseTemp(void) {return (USETEMP)THDVAR(current_thd, use_tempfile);} int GetConvSize(void) {return THDVAR(current_thd, conv_size);} TYPCONV GetTypeConv(void) {return (TYPCONV)THDVAR(current_thd, type_conv);} @@ -3196,7 +3202,7 @@ const COND *ha_connect::cond_push(const COND *cond) { DBUG_ENTER("ha_connect::cond_push"); - if (tdbp) { + if (tdbp && CondPushEnabled()) { PGLOBAL& g= xp->g; AMT tty= tdbp->GetAmType(); bool x= (tty == TYPE_AM_MYX || tty == TYPE_AM_XDBC); @@ -7243,7 +7249,8 @@ static struct st_mysql_sys_var* connect_system_variables[]= { #if defined(JAVA_SUPPORT) || defined(CMGO_SUPPORT) MYSQL_SYSVAR(enable_mongo), #endif // JAVA_SUPPORT || CMGO_SUPPORT -NULL + MYSQL_SYSVAR(cond_push), + NULL }; maria_declare_plugin(connect) @@ -7256,10 +7263,10 @@ maria_declare_plugin(connect) PLUGIN_LICENSE_GPL, connect_init_func, /* Plugin Init */ connect_done_func, /* Plugin Deinit */ - 0x0106, /* version number (1.05) */ + 0x0107, /* version number (1.05) */ NULL, /* status variables */ connect_system_variables, /* system variables */ - "1.06.0006", /* string version */ + "1.06.0007", /* string version */ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */ } maria_declare_plugin_end; diff --git a/storage/connect/jdbconn.cpp b/storage/connect/jdbconn.cpp index ff84c75b67f..33414ca74c2 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 @@ -171,6 +187,14 @@ int TranslateJDBCType(int stp, char *tn, int prec, int& len, char& v) case -5: // BIGINT type = TYPE_BIGINT; break; + case 1111: // UNKNOWN or UUID + if (!tn || !stricmp(tn, "UUID")) { + type = TYPE_STRING; + len = 36; + break; + } // endif tn + + // Pass through case 0: // NULL case -2: // BINARY case -4: // LONGVARBINARY @@ -192,6 +216,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. */ /***********************************************************************/ @@ -519,7 +641,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 +657,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 + + // 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; -// } // end of ~JDBConn + err: + // Not used anymore + env->DeleteLocalRef(parms); + return brc; +} // end of SetUUID /***********************************************************************/ /* Utility routine. */ @@ -770,6 +964,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 +988,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 +1018,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 +1085,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 +1268,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 +1495,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) diff --git a/storage/connect/jdbconn.h b/storage/connect/jdbconn.h index 56f318d238b..0c36cccadcf 100644 --- a/storage/connect/jdbconn.h +++ b/storage/connect/jdbconn.h @@ -29,6 +29,7 @@ public: // Attributes public: char *GetQuoteChar(void) { return m_IDQuoteChar; } + bool SetUUID(PGLOBAL g, PTDBJDBC tjp); virtual int GetMaxValue(int infotype); public: @@ -58,13 +59,6 @@ public: protected: // Members -#if 0 - JavaVM *jvm; // Pointer to the JVM (Java Virtual Machine) - JNIEnv *env; // Pointer to native interface - jclass jdi; // Pointer to the java wrapper class - jobject job; // The java wrapper class object - jmethodID errid; // The GetErrmsg method ID -#endif // 0 jmethodID xqid; // The ExecuteQuery method ID jmethodID xuid; // The ExecuteUpdate method ID jmethodID xid; // The Execute method ID @@ -84,8 +78,7 @@ protected: jmethodID timfldid; // The TimeField method ID jmethodID tspfldid; // The TimestampField method ID jmethodID bigfldid; // The BigintField method ID -// PCSZ Msg; -// PCSZ m_Wrap; + jmethodID uidfldid; // The UuidField method ID char m_IDQuoteChar[2]; PCSZ m_Pwd; int m_Ncol; diff --git a/storage/connect/mysql-test/connect/r/jdbc_postgresql.result b/storage/connect/mysql-test/connect/r/jdbc_postgresql.result index 6d77d79d5d3..7969672dd66 100644 --- a/storage/connect/mysql-test/connect/r/jdbc_postgresql.result +++ b/storage/connect/mysql-test/connect/r/jdbc_postgresql.result @@ -1,9 +1,11 @@ +SET GLOBAL connect_class_path='C:/MariaDB-10.2/MariaDB/storage/connect/mysql-test/connect/std_data/JavaWrappers.jar;C:/Jconnectors/postgresql-42.2.1.jar'; CREATE TABLE t2 ( command varchar(128) not null, number int(5) not null flag=1, message varchar(255) flag=2) -ENGINE=CONNECT TABLE_TYPE=JDBC CONNECTION='jdbc:postgresql://localhost/mtr' -OPTION_LIST='User=mtr,Password=mtr,Schema=public,Execsrc=1'; +ENGINE=CONNECT TABLE_TYPE=JDBC +CONNECTION='jdbc:postgresql://localhost/test?user=postgres&password=tinono' +OPTION_LIST='Execsrc=1'; SELECT * FROM t2 WHERE command='drop table employee'; command number message drop table employee 0 Execute: org.postgresql.util.PSQLException: ERREUR: la table « employee » n'existe pas @@ -14,17 +16,18 @@ SELECT * FROM t2 WHERE command = "insert into employee values(4567,'Johnson', 'E command number message insert into employee values(4567,'Johnson', 'Engineer', 12560.50) 1 Affected rows CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC CATFUNC=tables -CONNECTION='jdbc:postgresql://localhost/mtr' -OPTION_LIST='User=mtr,Password=mtr,Schema=public,Tabtype=TABLE,Maxres=10'; +CONNECTION='jdbc:postgresql://localhost/test?user=postgres&password=tinono' +OPTION_LIST='Tabtype=TABLE,Maxres=10'; SELECT * FROM t1; Table_Cat Table_Schema Table_Name Table_Type Remark - public employee TABLE NULL - public t1 TABLE NULL - public t2 TABLE NULL +NULL public employee TABLE NULL +NULL public t1 TABLE NULL +NULL public t2 TABLE NULL +NULL public tchar TABLE NULL +NULL public testuuid TABLE NULL DROP TABLE t1; -CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC CATFUNC=columns -CONNECTION='jdbc:postgresql://localhost/mtr' tabname=employee -OPTION_LIST='User=mtr,Password=mtr,Maxres=10'; +CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC tabname=employee CATFUNC=columns +CONNECTION='jdbc:postgresql://localhost/test?user=postgres&password=tinono'; SELECT * FROM t1; Table_Cat Table_Schema Table_Name Column_Name Data_Type Type_Name Column_Size Buffer_Length Decimal_Digits Radix Nullable Remarks NULL public employee id 4 int4 10 0 0 10 0 NULL @@ -34,13 +37,14 @@ NULL public employee salary 2 numeric 8 0 2 10 1 NULL DROP TABLE t1; CREATE SERVER 'postgresql' FOREIGN DATA WRAPPER 'postgresql' OPTIONS ( HOST 'localhost', -DATABASE 'mtr', -USER 'mtr', -PASSWORD 'mtr', +DATABASE 'test', +USER 'postgres', +PASSWORD 'tinono', PORT 0, SOCKET '', OWNER 'root'); -CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC CONNECTION='postgresql/public.employee'; +CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC +CONNECTION='postgresql/public.employee'; SELECT * FROM t1; id name title salary 4567 Johnson Engineer 12560.50 @@ -60,6 +64,3 @@ SELECT * FROM t2 WHERE command='drop table employee'; command number message drop table employee 0 Affected rows DROP TABLE t2; -SET GLOBAL connect_jvm_path=NULL; -SET GLOBAL connect_class_path=NULL; -SET GLOBAL time_zone = SYSTEM; diff --git a/storage/connect/mysql-test/connect/std_data/JavaWrappers.jar b/storage/connect/mysql-test/connect/std_data/JavaWrappers.jar Binary files differnew file mode 100644 index 00000000000..33b29e7685b --- /dev/null +++ b/storage/connect/mysql-test/connect/std_data/JavaWrappers.jar diff --git a/storage/connect/mysql-test/connect/t/jdbc_postgresql.test b/storage/connect/mysql-test/connect/t/jdbc_postgresql.test index 1041ef468d7..8036f71020d 100644 --- a/storage/connect/mysql-test/connect/t/jdbc_postgresql.test +++ b/storage/connect/mysql-test/connect/t/jdbc_postgresql.test @@ -3,25 +3,32 @@ # # This test is run against Postgresql driver # +eval SET GLOBAL connect_class_path='$MTR_SUITE_DIR/std_data/JavaWrappers.jar;C:/Jconnectors/postgresql-42.2.1.jar'; CREATE TABLE t2 ( command varchar(128) not null, number int(5) not null flag=1, message varchar(255) flag=2) -ENGINE=CONNECT TABLE_TYPE=JDBC CONNECTION='jdbc:postgresql://localhost/mtr' -OPTION_LIST='User=mtr,Password=mtr,Schema=public,Execsrc=1'; +ENGINE=CONNECT TABLE_TYPE=JDBC +CONNECTION='jdbc:postgresql://localhost/test?user=postgres&password=tinono' +OPTION_LIST='Execsrc=1'; +#CONNECTION='jdbc:postgresql://localhost/mtr' +#OPTION_LIST='User=mtr,Password=mtr,Schema=public,Execsrc=1'; SELECT * FROM t2 WHERE command='drop table employee'; SELECT * FROM t2 WHERE command = 'create table employee (id int not null, name varchar(32), title char(16), salary decimal(8,2))'; SELECT * FROM t2 WHERE command = "insert into employee values(4567,'Johnson', 'Engineer', 12560.50)"; CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC CATFUNC=tables -CONNECTION='jdbc:postgresql://localhost/mtr' -OPTION_LIST='User=mtr,Password=mtr,Schema=public,Tabtype=TABLE,Maxres=10'; +CONNECTION='jdbc:postgresql://localhost/test?user=postgres&password=tinono' +OPTION_LIST='Tabtype=TABLE,Maxres=10'; +#CONNECTION='jdbc:postgresql://localhost/mtr' +#OPTION_LIST='User=mtr,Password=mtr,Schema=public,Tabtype=TABLE,Maxres=10'; SELECT * FROM t1; DROP TABLE t1; -CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC CATFUNC=columns -CONNECTION='jdbc:postgresql://localhost/mtr' tabname=employee -OPTION_LIST='User=mtr,Password=mtr,Maxres=10'; +CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC tabname=employee CATFUNC=columns +CONNECTION='jdbc:postgresql://localhost/test?user=postgres&password=tinono'; +#CONNECTION='jdbc:postgresql://localhost/mtr' tabname=employee; +#OPTION_LIST='User=mtr,Password=mtr,Maxres=10'; SELECT * FROM t1; DROP TABLE t1; @@ -30,14 +37,18 @@ DROP TABLE t1; # CREATE SERVER 'postgresql' FOREIGN DATA WRAPPER 'postgresql' OPTIONS ( HOST 'localhost', -DATABASE 'mtr', -USER 'mtr', -PASSWORD 'mtr', +DATABASE 'test', +USER 'postgres', +PASSWORD 'tinono', PORT 0, SOCKET '', OWNER 'root'); +#DATABASE 'mtr', +#USER 'mtr', +#PASSWORD 'mtr', -CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC CONNECTION='postgresql/public.employee'; +CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC +CONNECTION='postgresql/public.employee'; SELECT * FROM t1; INSERT INTO t1 VALUES(3126,'Smith', 'Clerk', 5230.00); UPDATE t1 SET salary = salary + 100.00; diff --git a/storage/connect/mysql-test/connect/t/jdbconn.inc b/storage/connect/mysql-test/connect/t/jdbconn.inc index 05122f51924..81ec80c13d6 100644 --- a/storage/connect/mysql-test/connect/t/jdbconn.inc +++ b/storage/connect/mysql-test/connect/t/jdbconn.inc @@ -22,10 +22,11 @@ DROP TABLE t1; # 1 - The current directory. # 2 - The paths of the connect_class_path global variable. # 3 - The paths of the CLASSPATH environment variable. -# In this test we use an executable jar file that contains all what is needed. -eval SET GLOBAL connect_class_path='$MTR_SUITE_DIR/std_data/JdbcMariaDB.jar'; +# In this test we use an executable jar file that contains all the eisting wrappers. +#eval SET GLOBAL connect_class_path='$MTR_SUITE_DIR/std_data/JdbcMariaDB.jar'; +eval SET GLOBAL connect_class_path='$MTR_SUITE_DIR/std_data/JavaWrappers.jar'; -# Paths to the JDK classes and to the MySQL and MariaDB drivers can be defined in the CLASSPATH environment variable +# Paths to the JDK classes and to the JDBC drivers should be defined in the CLASSPATH environment variable #CREATE FUNCTION envar RETURNS STRING SONAME 'ha_connect.dll'; #SELECT envar('CLASSPATH'); diff --git a/storage/connect/plgdbsem.h b/storage/connect/plgdbsem.h index 6a0a8be8ff8..5446e0d2a07 100644 --- a/storage/connect/plgdbsem.h +++ b/storage/connect/plgdbsem.h @@ -362,7 +362,8 @@ enum COLUSE {U_P = 0x01, /* the projection list. */ U_IS_NULL = 0x80, /* The column has a null value */ U_SPECIAL = 0x100, /* The column is special */ U_UNSIGNED = 0x200, /* The column type is unsigned */ - U_ZEROFILL = 0x400}; /* The column is zero filled */ + U_ZEROFILL = 0x400, /* The column is zero filled */ + U_UUID = 0x800}; /* The column is a UUID */ /***********************************************************************/ /* DB description class and block pointer definitions. */ diff --git a/storage/connect/tabjdbc.cpp b/storage/connect/tabjdbc.cpp index c0fda584381..adbfb2168ae 100644 --- a/storage/connect/tabjdbc.cpp +++ b/storage/connect/tabjdbc.cpp @@ -605,6 +605,10 @@ bool TDBJDBC::OpenDB(PGLOBAL g) else if (Quoted) Quote = Jcp->GetQuoteChar(); + if (Mode != MODE_READ && Mode != MODE_READX) + if (Jcp->SetUUID(g, this)) + PushWarning(g, this, 1); + Use = USE_OPEN; // Do it now in case we are recursively called /*********************************************************************/ @@ -970,6 +974,7 @@ void TDBJDBC::CloseDB(PGLOBAL g) JDBCCOL::JDBCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am) : EXTCOL(cdp, tdbp, cprec, i, am) { + uuid = false; } // end of JDBCCOL constructor /***********************************************************************/ @@ -977,6 +982,7 @@ JDBCCOL::JDBCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am) /***********************************************************************/ JDBCCOL::JDBCCOL(void) : EXTCOL() { + uuid = false; } // end of JDBCCOL constructor /***********************************************************************/ @@ -985,12 +991,11 @@ JDBCCOL::JDBCCOL(void) : EXTCOL() /***********************************************************************/ JDBCCOL::JDBCCOL(JDBCCOL *col1, PTDB tdbp) : EXTCOL(col1, tdbp) { + uuid = col1->uuid; } // end of JDBCCOL copy constructor /***********************************************************************/ -/* ReadColumn: when SQLFetch is used there is nothing to do as the */ -/* column buffer was bind to the record set. This is also the case */ -/* when calculating MaxSize (Bufp is NULL even when Rows is not). */ +/* ReadColumn: retrieve the column value via the JDBC driver. */ /***********************************************************************/ void JDBCCOL::ReadColumn(PGLOBAL g) { diff --git a/storage/connect/tabjdbc.h b/storage/connect/tabjdbc.h index d422ed26ef2..078129a14e3 100644 --- a/storage/connect/tabjdbc.h +++ b/storage/connect/tabjdbc.h @@ -101,6 +101,7 @@ protected: /***********************************************************************/ class JDBCCOL : public EXTCOL { friend class TDBJDBC; + friend class JDBConn; public: // Constructors JDBCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am = "JDBC"); @@ -119,6 +120,7 @@ protected: JDBCCOL(void); // Members + bool uuid; // For PostgreSQL }; // end of class JDBCCOL /***********************************************************************/ |