From 7b7414c0ef6a9f009c96483e60ebf1e5a6a6eb14 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Wed, 27 Apr 2016 12:36:55 +0200 Subject: [PATCH 01/18] - Add the JDBC table type compilation for CMAKE. modified: storage/connect/CMakeLists.txt - Fix MDEV-9993 modified: storage/connect/jsonudf.cpp --- storage/connect/CMakeLists.txt | 13 ++-- storage/connect/jsonudf.cpp | 128 ++++++++++++++++++++------------- 2 files changed, 86 insertions(+), 55 deletions(-) diff --git a/storage/connect/CMakeLists.txt b/storage/connect/CMakeLists.txt index fe8940eb493c7..80a5b3bdc60b8 100644 --- a/storage/connect/CMakeLists.txt +++ b/storage/connect/CMakeLists.txt @@ -265,14 +265,17 @@ OPTION(CONNECT_WITH_JDBC "Compile CONNECT storage engine with JDBC support" ON) IF(CONNECT_WITH_JDBC) # TODO: detect Java SDK and the presence of JDBC connectors + # TODO: Find how to compile and install the JdbcInterface.java class # Find required libraries and include directories - # Find how to compile and install the JdbcInterface.java class - IF(JDBC_OK) - INCLUDE_DIRECTORIES(${JDBC_INCLUDE_DIR}) + FIND_PACKAGE(JAVA) + FIND_PACKAGE(JNI) + IF (JAVA_FOUND AND JNI_FOUND) + INCLUDE_DIRECTORIES(${JNI_INCLUDE_DIR}) + SET(JNI_LIBRARY ${JNI_LIBRARIES}) + SET(CONNECT_SOURCES ${CONNECT_SOURCES} JdbcInterface.java + jdbconn.cpp tabjdbc.cpp jdbconn.h tabjdbc.h jdbccat.h) add_definitions(-DJDBC_SUPPORT) - SET(CONNECT_SOURCES ${CONNECT_SOURCES} - JdbcInterface.java tabjdbc.cpp jdbconn.cpp jdbccat.h jdbconn.h tabjdbc.h) ELSE() SET(JDBC_LIBRARY "") ENDIF() diff --git a/storage/connect/jsonudf.cpp b/storage/connect/jsonudf.cpp index eae872b81cc77..0b5688c58ab20 100644 --- a/storage/connect/jsonudf.cpp +++ b/storage/connect/jsonudf.cpp @@ -3538,37 +3538,9 @@ void jsoncontains_path_deinit(UDF_INIT* initid) } // end of jsoncontains_path_deinit /*********************************************************************************/ -/* Set Json items of a Json document according to path. */ +/* This function is used by the json_set/insert/update_item functions. */ /*********************************************************************************/ -my_bool json_set_item_init(UDF_INIT *initid, UDF_ARGS *args, char *message) -{ - unsigned long reslen, memlen; - int n = IsJson(args, 0); - - if (!(args->arg_count % 2)) { - strcpy(message, "This function must have an odd number of arguments"); - return true; - } else if (!n && args->arg_type[0] != STRING_RESULT) { - strcpy(message, "First argument must be a json item"); - return true; - } else - CalcLen(args, false, reslen, memlen); - - if (n == 2 && args->args[0]) { - char fn[_MAX_PATH]; - long fl; - - memcpy(fn, args->args[0], args->lengths[0]); - fn[args->lengths[0]] = 0; - fl = GetFileLength(fn); - memlen += fl * 3; - } else if (n != 3) - memlen += args->lengths[0] * 3; - - return JsonInit(initid, args, message, true, reslen, memlen); -} // end of json_set_item_init - -char *json_set_item(UDF_INIT *initid, UDF_ARGS *args, char *result, +char *handle_item(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *res_length, char *is_null, char *error) { char *p, *path, *str = NULL; @@ -3586,12 +3558,16 @@ char *json_set_item(UDF_INIT *initid, UDF_ARGS *args, char *result, } else if (initid->const_item) g->N = 1; - if (!strcmp(result, "$insert")) + if (!strcmp(result, "$set")) + w = 0; + else if (!strcmp(result, "$insert")) w = 1; else if (!strcmp(result, "$update")) w = 2; - else - w = 0; + else { + PUSH_WARNING("Logical error, please contact CONNECT developer"); + goto err; + } // endelse // Save stack and allocation environment and prepare error return if (g->jump_level == MAX_JUMP) { @@ -3660,10 +3636,10 @@ char *json_set_item(UDF_INIT *initid, UDF_ARGS *args, char *result, // Keep result of constant function g->Activityp = (PACTIVITY)str; - err: +err: g->jump_level--; - fin: +fin: if (!str) { *is_null = 1; *res_length = 0; @@ -3671,6 +3647,44 @@ char *json_set_item(UDF_INIT *initid, UDF_ARGS *args, char *result, *res_length = strlen(str); return str; +} // end of handle_item + +/*********************************************************************************/ +/* Set Json items of a Json document according to path. */ +/*********************************************************************************/ +my_bool json_set_item_init(UDF_INIT *initid, UDF_ARGS *args, char *message) +{ + unsigned long reslen, memlen; + int n = IsJson(args, 0); + + if (!(args->arg_count % 2)) { + strcpy(message, "This function must have an odd number of arguments"); + return true; + } else if (!n && args->arg_type[0] != STRING_RESULT) { + strcpy(message, "First argument must be a json item"); + return true; + } else + CalcLen(args, false, reslen, memlen); + + if (n == 2 && args->args[0]) { + char fn[_MAX_PATH]; + long fl; + + memcpy(fn, args->args[0], args->lengths[0]); + fn[args->lengths[0]] = 0; + fl = GetFileLength(fn); + memlen += fl * 3; + } else if (n != 3) + memlen += args->lengths[0] * 3; + + return JsonInit(initid, args, message, true, reslen, memlen); +} // end of json_set_item_init + +char *json_set_item(UDF_INIT *initid, UDF_ARGS *args, char *result, + unsigned long *res_length, char *is_null, char *p) +{ + strcpy(result, "$set"); + return handle_item(initid, args, result, res_length, is_null, p); } // end of json_set_item void json_set_item_deinit(UDF_INIT* initid) @@ -3690,7 +3704,7 @@ char *json_insert_item(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *res_length, char *is_null, char *p) { strcpy(result, "$insert"); - return json_set_item(initid, args, result, res_length, is_null, p); + return handle_item(initid, args, result, res_length, is_null, p); } // end of json_insert_item void json_insert_item_deinit(UDF_INIT* initid) @@ -3710,7 +3724,7 @@ char *json_update_item(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *res_length, char *is_null, char *p) { strcpy(result, "$update"); - return json_set_item(initid, args, result, res_length, is_null, p); + return handle_item(initid, args, result, res_length, is_null, p); } // end of json_update_item void json_update_item_deinit(UDF_INIT* initid) @@ -4706,14 +4720,9 @@ void jbin_item_merge_deinit(UDF_INIT* initid) } // end of jbin_item_merge_deinit /*********************************************************************************/ -/* Set Json items of a Json document according to path. */ +/* This function is used by the jbin_set/insert/update functions. */ /*********************************************************************************/ -my_bool jbin_set_item_init(UDF_INIT *initid, UDF_ARGS *args, char *message) -{ - return json_set_item_init(initid, args, message); -} // end of jbin_set_item_init - -char *jbin_set_item(UDF_INIT *initid, UDF_ARGS *args, char *result, +char *bin_handle_item(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *res_length, char *is_null, char *error) { char *p, *path; @@ -4732,12 +4741,16 @@ char *jbin_set_item(UDF_INIT *initid, UDF_ARGS *args, char *result, } else if (initid->const_item) g->N = 1; - if (!strcmp(result, "$insert")) + if (!strcmp(result, "$set")) + w = 0; + else if (!strcmp(result, "$insert")) w = 1; else if (!strcmp(result, "$update")) w = 2; - else - w = 0; + else { + PUSH_WARNING("Logical error, please contact CONNECT developer"); + goto fin; + } // endelse if (!g->Xchk) { if (CheckMemory(g, initid, args, 1, true, false, true)) { @@ -4791,7 +4804,7 @@ char *jbin_set_item(UDF_INIT *initid, UDF_ARGS *args, char *result, // Keep result of constant function g->Activityp = (PACTIVITY)bsp; - fin: +fin: if (!bsp) { *is_null = 1; *res_length = 0; @@ -4799,6 +4812,21 @@ char *jbin_set_item(UDF_INIT *initid, UDF_ARGS *args, char *result, *res_length = sizeof(BSON); return (char*)bsp; +} // end of bin_handle_item + +/*********************************************************************************/ +/* Set Json items of a Json document according to path. */ +/*********************************************************************************/ +my_bool jbin_set_item_init(UDF_INIT *initid, UDF_ARGS *args, char *message) +{ + return json_set_item_init(initid, args, message); +} // end of jbin_set_item_init + +char *jbin_set_item(UDF_INIT *initid, UDF_ARGS *args, char *result, + unsigned long *res_length, char *is_null, char *p) +{ + strcpy(result, "$set"); + return bin_handle_item(initid, args, result, res_length, is_null, p); } // end of jbin_set_item void jbin_set_item_deinit(UDF_INIT* initid) @@ -4818,7 +4846,7 @@ char *jbin_insert_item(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *res_length, char *is_null, char *p) { strcpy(result, "$insert"); - return jbin_set_item(initid, args, result, res_length, is_null, p); + return bin_handle_item(initid, args, result, res_length, is_null, p); } // end of jbin_insert_item void jbin_insert_item_deinit(UDF_INIT* initid) @@ -4838,7 +4866,7 @@ char *jbin_update_item(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *res_length, char *is_null, char *p) { strcpy(result, "$update"); - return jbin_set_item(initid, args, result, res_length, is_null, p); + return bin_handle_item(initid, args, result, res_length, is_null, p); } // end of jbin_update_item void jbin_update_item_deinit(UDF_INIT* initid) From bbdeb911b85ad10ae4a13308492e541384ec9889 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Wed, 27 Apr 2016 12:57:27 +0200 Subject: [PATCH 02/18] - Add the JdbcInterface.java to the project added: storage/connect/JdbcInterface.java - Add *.java to be handled modified: .gitattributes --- .gitattributes | 2 + storage/connect/JdbcInterface.java | 639 +++++++++++++++++++++++++++++ 2 files changed, 641 insertions(+) create mode 100644 storage/connect/JdbcInterface.java diff --git a/.gitattributes b/.gitattributes index 8aedbaa83d752..d11f212024910 100644 --- a/.gitattributes +++ b/.gitattributes @@ -9,6 +9,7 @@ *.cpp text *.h text *.test text +*.java text # Declare files that will always have LF line endings on checkout. *.result text eol=lf @@ -29,3 +30,4 @@ storage/connect/mysql-test/connect/std_data/*.dat binary *.cc diff=cpp *.ic diff=cpp *.cpp diff=cpp +*.java diff=cpp diff --git a/storage/connect/JdbcInterface.java b/storage/connect/JdbcInterface.java new file mode 100644 index 0000000000000..97f86b55a2ce9 --- /dev/null +++ b/storage/connect/JdbcInterface.java @@ -0,0 +1,639 @@ +import java.math.*; +import java.sql.*; +import java.util.Collections; +import java.util.List; + +public class JdbcInterface { + boolean DEBUG = false; + Connection conn = null; + DatabaseMetaData dbmd = null; + Statement stmt = null; + PreparedStatement pstmt = null; + ResultSet rs = null; + ResultSetMetaData rsmd = null; + + // === Constructors/finalize ========================================= + public JdbcInterface() { + this(true); + } // end of default constructor + + public JdbcInterface(boolean b) { + DEBUG = b; + } // end of constructor + + public int JdbcConnect(String[] parms, int fsize, boolean scrollable) { + int rc = 0; + + if (DEBUG) + System.out.println("In JdbcInterface: driver=" + parms[0]); + + try { + if (DEBUG) + System.out.println("In try block"); + + if (parms[0] != null && !parms[0].isEmpty()) { + System.out.println("b is true!"); + Class.forName(parms[0]); //loads the driver + } // endif driver + + if (DEBUG) + System.out.println("URL=" + parms[1]); + + if (parms[2] != null && !parms[2].isEmpty()) { + if (DEBUG) + System.out.println("user=" + parms[2] + " pwd=" + parms[3]); + + conn = DriverManager.getConnection(parms[1], parms[2], parms[3]); + } else + conn = DriverManager.getConnection(parms[1]); + + if (DEBUG) + System.out.println("Connection " + conn.toString() + " established"); + + // Get the data base meta data object + dbmd = conn.getMetaData(); + + // Get a statement from the connection + if (scrollable) + stmt = conn.createStatement(java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE, java.sql.ResultSet.CONCUR_READ_ONLY); + else + stmt = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY, java.sql.ResultSet.CONCUR_READ_ONLY); + + if (DEBUG) + System.out.println("Statement type = " + stmt.getResultSetType() + + " concurrency = " + stmt.getResultSetConcurrency()); + + if (DEBUG) // Get the fetch size of a statement + System.out.println("Default fetch size = " + stmt.getFetchSize()); + + if (fsize != 0) { + // Set the fetch size + stmt.setFetchSize(fsize); + + if (DEBUG) + System.out.println("New fetch size = " + stmt.getFetchSize()); + + } // endif fsize + + } catch(ClassNotFoundException e) { + System.err.println("ClassNotFoundException: " + e.getMessage()); + rc = 1; + } catch (SQLException se) { + System.out.println("SQL Exception:"); + + // Loop through the SQL Exceptions + while (se != null) { + System.out.println("State : " + se.getSQLState()); + System.out.println("Message: " + se.getMessage()); + System.out.println("Error : " + se.getErrorCode()); + + se = se.getNextException(); + } // end while se + + rc = 2; + } catch( Exception e ) { + System.out.println(e); + rc = 3; + } // end try/catch + + return rc; + } // end of JdbcConnect + + public boolean CreatePrepStmt(String sql) { + boolean b = false; + + try { + pstmt = conn.prepareStatement(sql); + } catch (SQLException se) { + System.out.println(se); + b = true; + } catch (Exception e) { + System.out.println(e); + b = true; + } // end try/catch + + return b; + } // end of CreatePrepStmt + + public void SetStringParm(int i, String s) { + try { + pstmt.setString(i, s); + } catch (Exception e) { + System.out.println(e); + } // end try/catch + + } // end of SetStringParm + + public void SetIntParm(int i, int n) { + try { + pstmt.setInt(i, n); + } catch (Exception e) { + System.out.println(e); + } // end try/catch + + } // end of SetIntParm + + public void SetShortParm(int i, short n) { + try { + pstmt.setShort(i, n); + } catch (Exception e) { + System.out.println(e); + } // end try/catch + + } // end of SetShortParm + + public void SetBigintParm(int i, long n) { + try { + pstmt.setLong(i, n); + } catch (Exception e) { + System.out.println(e); + } // end try/catch + + } // end of SetBigintParm + + public void SetFloatParm(int i, float f) { + try { + pstmt.setFloat(i, f); + } catch (Exception e) { + System.out.println(e); + } // end try/catch + + } // end of SetFloatParm + + public void SetDoubleParm(int i, double d) { + try { + pstmt.setDouble(i, d); + } catch (Exception e) { + System.out.println(e); + } // end try/catch + + } // end of SetDoubleParm + + public void SetTimestampParm(int i, Timestamp t) { + try { + pstmt.setTimestamp(i, t); + } catch (Exception e) { + System.out.println(e); + } // end try/catch + + } // end of SetTimestampParm + + public int ExecutePrep() { + int n = -3; + + if (pstmt != null) try { + n = pstmt.executeUpdate(); + } catch (SQLException se) { + System.out.println(se); + n = -1; + } catch (Exception e) { + System.out.println(e); + n = -2; + } //end try/catch + + return n; + } // end of ExecutePrep + + public boolean ClosePrepStmt() { + boolean b = false; + + if (pstmt != null) try { + pstmt.close(); + pstmt = null; + } catch (SQLException se) { + System.out.println(se); + b = true; + } catch (Exception e) { + System.out.println(e); + b = true; + } // end try/catch + + return b; + } // end of ClosePrepStmt + + public int JdbcDisconnect() { + int rc = 0; + + // Cancel pending statement + if (stmt != null) + try { + System.out.println("Cancelling statement"); + stmt.cancel(); + } catch(SQLException se) { + System.out.println(se); + rc += 1; + } // nothing more we can do + + // Close the statement and the connection + if (rs != null) + try { + System.out.println("Closing result set"); + rs.close(); + } catch(SQLException se) { + System.out.println(se); + rc = 2; + } // nothing more we can do + + if (stmt != null) + try { + System.out.println("Closing statement"); + stmt.close(); + } catch(SQLException se) { + System.out.println(se); + rc += 4; + } // nothing more we can do + + ClosePrepStmt(); + + if (conn != null) + try { + System.out.println("Closing connection"); + conn.close(); + } catch (SQLException se) { + System.out.println(se); + rc += 8; + } //end try/catch + + System.out.println("All closed"); + return rc; + } // end of JdbcDisconnect + + public int GetMaxValue(int n) { + int m = 0; + + try { + switch (n) { + case 1: // Max columns in table + m = dbmd.getMaxColumnsInTable(); + break; + case 2: // Max catalog name length + m = dbmd.getMaxCatalogNameLength(); + break; + case 3: // Max schema name length + m = dbmd.getMaxSchemaNameLength(); + break; + case 4: // Max table name length + m = dbmd.getMaxTableNameLength(); + break; + case 5: // Max column name length + m = dbmd.getMaxColumnNameLength(); + break; + } // endswitch n + + } catch(Exception e) { + System.out.println(e); + } // end try/catch + + return m; + } // end of GetMaxValue + + public int GetColumns(String[] parms) { + int ncol = 0; + + try { + if (rs != null) rs.close(); + rs = dbmd.getColumns(parms[0], parms[1], parms[2], parms[3]); + + if (rs != null) { + rsmd = rs.getMetaData(); + ncol = rsmd.getColumnCount(); + } // endif rs + + } catch(SQLException se) { + System.out.println(se); + } // end try/catch + + return ncol; + } // end of GetColumns + + public int GetTables(String[] parms) { + int ncol = 0; + String[] typ = null; + + if (parms[3] != null) { + typ = new String[1]; + typ[0] = parms[3]; + } // endif parms + + try { + if (rs != null) rs.close(); + rs = dbmd.getTables(parms[0], parms[1], parms[2], typ); + + if (rs != null) { + rsmd = rs.getMetaData(); + ncol = rsmd.getColumnCount(); + } // endif rs + + } catch(SQLException se) { + System.out.println(se); + } // end try/catch + + return ncol; + } // end of GetColumns + + public int Execute(String query) { + int n = 0; + + if (DEBUG) + System.out.println("Executing '" + query + "'"); + + try { + boolean b = stmt.execute(query); + + if (b == false) { + n = stmt.getUpdateCount(); + if (rs != null) rs.close(); + } // endif b + + if (DEBUG) + System.out.println("Query '" + query + "' executed: n = " + n); + + } catch (SQLException se) { + System.out.println(se); + n = -1; + } catch (Exception e) { + System.out.println(e); + n = -2; + } //end try/catch + + return n; + } // end of Execute + + public int GetResult() { + int ncol = 0; + + try { + rs = stmt.getResultSet(); + + if (rs != null) { + rsmd = rs.getMetaData(); + ncol = rsmd.getColumnCount(); + + if (DEBUG) + System.out.println("Result set has " + rsmd.getColumnCount() + " column(s)"); + + } // endif rs + + } catch (SQLException se) { + System.out.println(se); + ncol = -1; + } catch (Exception e) { + System.out.println(e); + ncol = -2; + } //end try/catch + + return ncol; + } // end of GetResult + + public int ExecuteQuery(String query) { + int ncol = 0; + + if (DEBUG) + System.out.println("Executing query '" + query + "'"); + + try { + rs = stmt.executeQuery(query); + rsmd = rs.getMetaData(); + ncol = rsmd.getColumnCount(); + + if (DEBUG) { + System.out.println("Query '" + query + "' executed successfully"); + System.out.println("Result set has " + rsmd.getColumnCount() + " column(s)"); + } // endif DEBUG + + } catch (SQLException se) { + System.out.println(se); + ncol = -1; + } catch (Exception e) { + System.out.println(e); + ncol = -2; + } //end try/catch + + return ncol; + } // end of ExecuteQuery + + public int ExecuteUpdate(String query) { + int n = 0; + + if (DEBUG) + System.out.println("Executing update query '" + query + "'"); + + try { + n = stmt.executeUpdate(query); + + if (DEBUG) + System.out.println("Update Query '" + query + "' executed: n = " + n); + + } catch (SQLException se) { + System.out.println(se); + n = -1; + } catch (Exception e) { + System.out.println(e); + n = -2; + } //end try/catch + + return n; + } // end of ExecuteQuery + + public int ReadNext() { + if (rs != null) { + try { + return rs.next() ? 1 : 0; + } catch (SQLException se) { + System.out.println(se); + return -1; + } //end try/catch + + } else + return 0; + + } // end of ReadNext + + public boolean Fetch(int row) { + if (rs != null) { + try { + return rs.absolute(row); + } catch (SQLException se) { + System.out.println(se); + return false; + } //end try/catch + + } else + return false; + + } // end of Fetch + + public String ColumnName(int n) { + if (rsmd == null) { + System.out.println("No result metadata"); + } else try { + return rsmd.getColumnLabel(n); + } catch (SQLException se) { + System.out.println(se); + } //end try/catch + + return null; + } // end of ColumnName + + public int ColumnType(int n, String name) { + if (rsmd == null) { + System.out.println("No result metadata"); + } else try { + if (n == 0) + n = rs.findColumn(name); + + return rsmd.getColumnType(n); + } catch (SQLException se) { + System.out.println("ColumnType: " + se); + } //end try/catch + + return 0; + } // end of ColumnType + + public String ColumnDesc(int n, int[] val) { + if (rsmd == null) { + System.out.println("No result metadata"); + return null; + } else try { + val[0] = rsmd.getColumnType(n); + val[1] = rsmd.getPrecision(n); + val[2] = rsmd.getScale(n); + val[3] = rsmd.isNullable(n); + return rsmd.getColumnLabel(n); + } catch (SQLException se) { + System.out.println(se); + } //end try/catch + + return null; + } // end of ColumnType + + public String StringField(int n, String name) { + if (rs == null) { + System.out.println("No result set"); + } else try { + return (n > 0) ? rs.getString(n) : rs.getString(name); + } catch (SQLException se) { + System.out.println(se); + } //end try/catch + + return null; + } // end of StringField + + public int IntField(int n, String name) { + if (rs == null) { + System.out.println("No result set"); + } else try { + return (n > 0) ? rs.getInt(n) : rs.getInt(name); + } catch (SQLException se) { + System.out.println(se); + } //end try/catch + + return 0; + } // end of IntField + + public long BigintField(int n, String name) { + if (rs == null) { + System.out.println("No result set"); + } else try { + BigDecimal bigDecimal = (n > 0) ? rs.getBigDecimal(n) : rs.getBigDecimal(name); + return bigDecimal != null ? bigDecimal.longValue() : null; + } catch (SQLException se) { + System.out.println(se); + } //end try/catch + + return 0; + } // end of BiginttField + + public double DoubleField(int n, String name) { + if (rs == null) { + System.out.println("No result set"); + } else try { + return (n > 0) ? rs.getDouble(n) : rs.getDouble(name); + } catch (SQLException se) { + System.out.println(se); + } //end try/catch + + return 0.; + } // end of DoubleField + + public float FloatField(int n, String name) { + if (rs == null) { + System.out.println("No result set"); + } else try { + return (n > 0) ? rs.getFloat(n) : rs.getFloat(name); + } catch (SQLException se) { + System.out.println(se); + } //end try/catch + + return 0; + } // end of FloatField + + public boolean BooleanField(int n, String name) { + if (rs == null) { + System.out.println("No result set"); + } else try { + return (n > 0) ? rs.getBoolean(n) : rs.getBoolean(name); + } catch (SQLException se) { + System.out.println(se); + } //end try/catch + + return false; + } // end of BooleanField + + public Date DateField(int n, String name) { + if (rs == null) { + System.out.println("No result set"); + } else try { + return (n > 0) ? rs.getDate(n) : rs.getDate(name); + } catch (SQLException se) { + System.out.println(se); + } //end try/catch + + return null; + } // end of DateField + + public Time TimeField(int n, String name) { + if (rs == null) { + System.out.println("No result set"); + } else try { + return (n > 0) ? rs.getTime(n) : rs.getTime(name); + } catch (SQLException se) { + System.out.println(se); + } //end try/catch + + return null; + } // end of TimeField + + public Timestamp TimestampField(int n, String name) { + if (rs == null) { + System.out.println("No result set"); + } else try { + return (n > 0) ? rs.getTimestamp(n) : rs.getTimestamp(name); + } catch (SQLException se) { + System.out.println(se); + } //end try/catch + + return null; + } // end of TimestampField + + public int GetDrivers(String[] s, int mxs) { + int n = 0; + List drivers = Collections.list(DriverManager.getDrivers()); + int size = Math.min(mxs, drivers.size()); + + for (int i = 0; i < size; i++) { + Driver driver = (Driver)drivers.get(i); + + // Get name of driver + s[n++] = driver.getClass().getName(); + + // Get version info + s[n++] = driver.getMajorVersion() + "." + driver.getMinorVersion(); + s[n++] = driver.jdbcCompliant() ? "Yes" : "No"; + s[n++] = driver.toString(); + } // endfor i + + return size; + } // end of GetDrivers + +} // end of class JdbcInterface From 80a204f27e91629a97a5d41e06bc8e4128a4ae86 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Thu, 5 May 2016 01:03:26 +0200 Subject: [PATCH 03/18] - Try to fix MDEV-9950 (not tested yet) modified: storage/connect/ha_connect.cc modified: storage/connect/plgdbutl.cpp - Fix Mdev-9997 (Sergey Vojtovitch) modified: storage/connect/inihandl.c - Try to have the JDBC type compiled by CMake modified: storage/connect/CMakeLists.txt - Fixing some bugs in the JDBC table type Use the CONNECTION option for the URL modified: storage/connect/ha_connect.cc modified: storage/connect/jdbconn.cpp modified: storage/connect/jdbconn.h modified: storage/connect/tabjdbc.cpp - Add the JdbcInterface.class to the project new file: storage/connect/JdbcInterface.class --- storage/connect/CMakeLists.txt | 12 ++-- storage/connect/JdbcInterface.class | Bin 0 -> 15117 bytes storage/connect/JdbcInterface.java | 2 +- storage/connect/ha_connect.cc | 19 +++++-- storage/connect/inihandl.c | 7 ++- storage/connect/jdbconn.cpp | 84 +++++++++++++--------------- storage/connect/jdbconn.h | 2 +- storage/connect/plgdbutl.cpp | 29 ++++------ storage/connect/tabjdbc.cpp | 16 ++++-- 9 files changed, 90 insertions(+), 81 deletions(-) create mode 100644 storage/connect/JdbcInterface.class diff --git a/storage/connect/CMakeLists.txt b/storage/connect/CMakeLists.txt index 80a5b3bdc60b8..f4bcbfa9ade3a 100644 --- a/storage/connect/CMakeLists.txt +++ b/storage/connect/CMakeLists.txt @@ -268,12 +268,14 @@ IF(CONNECT_WITH_JDBC) # TODO: Find how to compile and install the JdbcInterface.java class # Find required libraries and include directories - FIND_PACKAGE(JAVA) - FIND_PACKAGE(JNI) + FIND_PACKAGE(Java REQUIRED) + FIND_PACKAGE(JNI REQUIRED) IF (JAVA_FOUND AND JNI_FOUND) - INCLUDE_DIRECTORIES(${JNI_INCLUDE_DIR}) - SET(JNI_LIBRARY ${JNI_LIBRARIES}) - SET(CONNECT_SOURCES ${CONNECT_SOURCES} JdbcInterface.java + INCLUDE_DIRECTORIES(${JAVA_INCLUDE_PATH}) + INCLUDE_DIRECTORIES(${JAVA_INCLUDE_PATH2}) + SET(JDBC_LIBRARY ${JAVA_JVM_LIBRARY}) + SET(CONNECT_SOURCES ${CONNECT_SOURCES} + JdbcInterface.java JdbcInterface.class jdbconn.cpp tabjdbc.cpp jdbconn.h tabjdbc.h jdbccat.h) add_definitions(-DJDBC_SUPPORT) ELSE() diff --git a/storage/connect/JdbcInterface.class b/storage/connect/JdbcInterface.class new file mode 100644 index 0000000000000000000000000000000000000000..816f575212b2313bbde48e6b8831a0267f8ffef7 GIT binary patch literal 15117 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 0) ? rs.getBigDecimal(n) : rs.getBigDecimal(name); - return bigDecimal != null ? bigDecimal.longValue() : null; + return bigDecimal != null ? bigDecimal.longValue() : 0; } catch (SQLException se) { System.out.println(se); } //end try/catch diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 9f75d3bf54b71..caa07c8cf884a 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -190,6 +190,12 @@ extern "C" { } // extern "C" #endif // XMSG +#if defined(__WIN__) +CRITICAL_SECTION parsec; // Used calling the Flex parser +#else // !__WIN__ +pthread_mutex_t parmut; +#endif // !__WIN__ + /***********************************************************************/ /* Utility functions. */ /***********************************************************************/ @@ -634,6 +640,7 @@ static int connect_init_func(void *p) #if defined(__WIN__) sql_print_information("CONNECT: %s", compver); + InitializeCriticalSection((LPCRITICAL_SECTION)&parsec); #else // !__WIN__ sql_print_information("CONNECT: %s", version); #endif // !__WIN__ @@ -678,8 +685,10 @@ static int connect_done_func(void *) XmlCleanupParserLib(); #endif // LIBXML2_SUPPORT -#if !defined(__WIN__) -//PROFILE_End(); Causes signal 11 +#if defined(__WIN__) + DeleteCriticalSection((LPCRITICAL_SECTION)&parsec); +#else // !__WIN__ + PROFILE_End(); #endif // !__WIN__ for (pc= user_connect::to_users; pc; pc= pn) { @@ -5172,7 +5181,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd, spc= (!sep) ? ',' : *sep; qch= topt->qchar ? *topt->qchar : (signed)topt->quoted >= 0 ? '"' : 0; hdr= (int)topt->header; - tbl= topt->tablist; + tbl= topt->tablist; col= topt->colist; if (topt->oplist) { @@ -5305,8 +5314,8 @@ 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 && !(url= strz(g, create_info->connect_string))) { + strcpy(g->Message, "Missing URL"); } else { // Store ODBC additional parameters sjp= (PJPARM)PlugSubAlloc(g, NULL, sizeof(JDBCPARM)); diff --git a/storage/connect/inihandl.c b/storage/connect/inihandl.c index 542b807f8997a..46102557b2088 100644 --- a/storage/connect/inihandl.c +++ b/storage/connect/inihandl.c @@ -622,13 +622,16 @@ void PROFILE_End(void) if (trace) htrc("PROFILE_End: CurProfile=%p N=%d\n", CurProfile, N_CACHED_PROFILES); + if (!CurProfile) // Sergey Vojtovich + return; + /* Close all opened files and free the cache structure */ for (i = 0; i < N_CACHED_PROFILES; i++) { if (trace) htrc("MRU=%s i=%d\n", SVP(MRUProfile[i]->filename), i); - CurProfile = MRUProfile[i]; - PROFILE_ReleaseFile(); +// CurProfile = MRUProfile[i]; Sergey Vojtovich +// PROFILE_ReleaseFile(); see MDEV-9997 free(MRUProfile[i]); } // endfor i diff --git a/storage/connect/jdbconn.cpp b/storage/connect/jdbconn.cpp index cf744971c9e2f..4ad491951a709 100644 --- a/storage/connect/jdbconn.cpp +++ b/storage/connect/jdbconn.cpp @@ -741,32 +741,33 @@ JDBConn::JDBConn(PGLOBAL g, TDBJDBC *tdbp) // } // end of ~JDBConn -#if 0 /***********************************************************************/ /* Screen for errors. */ /***********************************************************************/ -bool JDBConn::Check(RETCODE rc) +char *JDBConn::Check(void) { - 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)); - - } // endif trace + if (env->ExceptionCheck()) { + char *msg; + 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(); + return msg; + } // endif Check - return false; + return NULL; } // end of Check +#if 0 /***********************************************************************/ /* Utility routine. */ /***********************************************************************/ @@ -911,14 +912,10 @@ int JDBConn::Open(PSZ jpath, PJPARM sop) rc = JNI_GetCreatedJavaVMs(jvms, 1, &jsz); if (rc == JNI_OK && jsz == 1) { - JavaVMAttachArgs args; - - args.version = JNI_VERSION_1_6; - args.name = NULL; - args.group = NULL; jvm = jvms[0]; - rc = jvm->AttachCurrentThread((void**)&env, &args); + rc = jvm->AttachCurrentThread((void**)&env, nullptr); } // endif rc + } // end of block if (rc == JNI_OK) @@ -1176,11 +1173,11 @@ void JDBConn::Close() void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val) { PGLOBAL& g = m_G; + char *msg; jint ctyp; jlong dtv; jstring cn, jn = nullptr; jobject dob; - jthrowable exc; jmethodID fldid = nullptr; if (rank == 0) @@ -1191,14 +1188,8 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val) 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 ((msg = Check())) { + sprintf(g->Message, "Getting ctyp: %s", msg); longjmp(g->jumper[g->jump_level], TYPE_AM_JDBC); } // endif Check @@ -1305,6 +1296,14 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val) val->Reset(); } // endswitch Type + if ((msg = 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); @@ -1467,6 +1466,7 @@ int JDBConn::ExecuteSQL(void) bool JDBConn::SetParam(JDBCCOL *colp) { PGLOBAL& g = m_G; + char *msg; int rc = false; PVAL val = colp->GetValue(); jint n, i = (jint)colp->GetRank(); @@ -1477,7 +1477,6 @@ bool JDBConn::SetParam(JDBCCOL *colp) jclass dat; jobject datobj; jstring jst = nullptr; - jthrowable exc; jmethodID dtc, setid = nullptr; switch (val->GetType()) { @@ -1531,7 +1530,7 @@ bool JDBConn::SetParam(JDBCCOL *colp) setid = env->GetMethodID(jdi, "SetDoubleParm", "(ID)V"); if (setid == nullptr) { - strcpy(g->Message, "Cannot fing method SetDoubleParm"); + strcpy(g->Message, "Cannot find method SetDoubleParm"); return true; } // endif setid @@ -1565,16 +1564,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 ((msg = Check())) { + sprintf(g->Message, "SetParam: col=%s msg=%s", colp->GetName(), msg); rc = true; - } // endif exc + } // endif msg if (jst) env->DeleteLocalRef(jst); @@ -1987,7 +1980,6 @@ bool JDBConn::SetParam(JDBCCOL *colp) } // 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; @@ -2001,7 +1993,7 @@ bool JDBConn::SetParam(JDBCCOL *colp) } // endfor i - if (rc == RC_OK) + if (rc > 0) qrp->Truncated = true; return i; diff --git a/storage/connect/jdbconn.h b/storage/connect/jdbconn.h index 0646fee845b8b..99720bf55d590 100644 --- a/storage/connect/jdbconn.h +++ b/storage/connect/jdbconn.h @@ -123,7 +123,7 @@ class JDBConn : public BLOCK { // JDBC operations protected: -//bool Check(RETCODE rc); + char *Check(void); //void ThrowDJX(int rc, PSZ msg/*, HSTMT hstmt = SQL_NULL_HSTMT*/); //void ThrowDJX(PSZ msg); //void AllocConnect(DWORD dwOptions); diff --git a/storage/connect/plgdbutl.cpp b/storage/connect/plgdbutl.cpp index d70eeb32a049e..799df7cfc5138 100644 --- a/storage/connect/plgdbutl.cpp +++ b/storage/connect/plgdbutl.cpp @@ -46,9 +46,9 @@ #else // !__WIN__ #include #include -#if defined(THREAD) +//#if defined(THREAD) #include -#endif // THREAD +//#endif // THREAD #include #define BIGMEM 2147483647 // Max int value #endif // !__WIN__ @@ -69,17 +69,6 @@ #include "valblk.h" #include "rcmsg.h" -/***********************************************************************/ -/* Macro or external routine definition */ -/***********************************************************************/ -#if defined(THREAD) -#if defined(__WIN__) -extern CRITICAL_SECTION parsec; // Used calling the Flex parser -#else // !__WIN__ -extern pthread_mutex_t parmut; -#endif // !__WIN__ -#endif // THREAD - /***********************************************************************/ /* DB static variables. */ /***********************************************************************/ @@ -90,6 +79,12 @@ extern "C" { extern char version[]; } // extern "C" +#if defined(__WIN__) +extern CRITICAL_SECTION parsec; // Used calling the Flex parser +#else // !__WIN__ +extern pthread_mutex_t parmut; +#endif // !__WIN__ + // The debug trace used by the main thread FILE *pfile = NULL; @@ -702,21 +697,21 @@ PDTP MakeDateFormat(PGLOBAL g, PSZ dfmt, bool in, bool out, int flag) /* Call the FLEX generated parser. In multi-threading mode the next */ /* instruction is included in an Enter/LeaveCriticalSection bracket. */ /*********************************************************************/ -#if defined(THREAD) + //#if defined(THREAD) #if defined(__WIN__) EnterCriticalSection((LPCRITICAL_SECTION)&parsec); #else // !__WIN__ pthread_mutex_lock(&parmut); #endif // !__WIN__ -#endif // THREAD +//#endif // THREAD rc = fmdflex(pdp); -#if defined(THREAD) +//#if defined(THREAD) #if defined(__WIN__) LeaveCriticalSection((LPCRITICAL_SECTION)&parsec); #else // !__WIN__ pthread_mutex_unlock(&parmut); #endif // !__WIN__ -#endif // THREAD +//#endif // THREAD if (trace) htrc("Done: in=%s out=%s rc=%d\n", SVP(pdp->InFmt), SVP(pdp->OutFmt), rc); diff --git a/storage/connect/tabjdbc.cpp b/storage/connect/tabjdbc.cpp index 97168646ba0e9..ce73349d9f75e 100644 --- a/storage/connect/tabjdbc.cpp +++ b/storage/connect/tabjdbc.cpp @@ -108,11 +108,17 @@ bool JDBCDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) { Jpath = GetStringCatInfo(g, "Jpath", ""); 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", @@ -198,7 +204,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; @@ -1669,6 +1675,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 /***********************************************************************/ From 025decfc38c00e8e04b433f13b22e2f32122abff Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Fri, 6 May 2016 01:07:14 +0200 Subject: [PATCH 04/18] - Remove gcc compiling errors and warnings modified: storage/connect/jdbconn.cpp modified: storage/connect/tabjdbc.h --- storage/connect/jdbconn.cpp | 36 ++++++++++++++++++++++-------------- storage/connect/tabjdbc.h | 2 +- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/storage/connect/jdbconn.cpp b/storage/connect/jdbconn.cpp index 4ad491951a709..093c746b59da9 100644 --- a/storage/connect/jdbconn.cpp +++ b/storage/connect/jdbconn.cpp @@ -47,7 +47,9 @@ #if defined(__WIN__) extern "C" HINSTANCE s_hModule; // Saved module handle -#endif // __WIN__ +#else // !__WIN__ +#define nullptr 0 +#endif // !__WIN__ int GetConvSize(); @@ -62,6 +64,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. */ /***********************************************************************/ @@ -155,7 +160,7 @@ 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; +//size_t m, n; JCATPARM *cap; #if defined(_DEBUG) @@ -174,8 +179,8 @@ static JCATPARM *AllocCatInfo(PGLOBAL g, JCATINFO fid, char *db, goto fin; } // endif rc - m = (size_t)qrp->Maxres; - n = (size_t)qrp->Nbcol; +//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; @@ -1157,10 +1162,12 @@ void JDBConn::Close() if (did == nullptr) printf("ERROR: method JdbcDisconnect() not found !"); - else - rc = env->CallIntMethod(job, did); + else if ((rc = env->CallIntMethod(job, did))) + printf("jdbcDisconnect: rc=%d", (int)rc); + + if ((rc = jvm->DetachCurrentThread())) + printf("DetachCurrentThread: rc = %d", (int)rc); - rc = jvm->DetachCurrentThread(); //rc = jvm->DestroyJavaVM(); m_Opened = false; } // endif m_Opened @@ -1687,8 +1694,8 @@ 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; int rc = ExecSQLcommand(src); @@ -1872,7 +1879,7 @@ bool JDBConn::SetParam(JDBCCOL *colp) int JDBConn::GetCatInfo(JCATPARM *cap) { PGLOBAL& g = m_G; - void *buffer; +// void *buffer; int i; PSZ fnc = "Unknown"; uint n, ncol; @@ -1946,7 +1953,7 @@ bool JDBConn::SetParam(JDBCCOL *colp) env->DeleteLocalRef(parms); // 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 @@ -1972,9 +1979,10 @@ 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 diff --git a/storage/connect/tabjdbc.h b/storage/connect/tabjdbc.h index b6cf91e28b80a..d3ac3784d2f61 100644 --- a/storage/connect/tabjdbc.h +++ b/storage/connect/tabjdbc.h @@ -73,7 +73,7 @@ class DllExport JDBCDEF : public TABDEF { /* Logical table description */ }; // end of JDBCDEF #if !defined(NJDBC) -#include "JDBConn.h" +#include "jdbconn.h" /***********************************************************************/ /* This is the JDBC Access Method class declaration for files from */ From 2323cf003387af35b126988eb6e57f1dff7dd996 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Mon, 9 May 2016 17:26:50 +0200 Subject: [PATCH 05/18] - Make the JVM lib dynamically loaded This makes the CONNECT storage engine usable when Java JDK is not installed. modified: storage/connect/ha_connect.cc modified: storage/connect/jdbconn.cpp modified: storage/connect/jdbconn.h - Typo modified: storage/connect/reldef.cpp --- storage/connect/ha_connect.cc | 34 +++++- storage/connect/jdbconn.cpp | 222 +++++++++++++++++++--------------- storage/connect/jdbconn.h | 22 ++-- storage/connect/reldef.cpp | 5 +- 4 files changed, 171 insertions(+), 112 deletions(-) diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index caa07c8cf884a..7571392ff3adb 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -129,6 +129,7 @@ #endif // ODBC_SUPPORT #if defined(JDBC_SUPPORT) #include "jdbccat.h" +#include "jdbconn.h" #endif // JDBC_SUPPORT #include "xtable.h" #include "tabmysql.h" @@ -169,7 +170,7 @@ #define JSONMAX 10 // JSON Default max grp size extern "C" { - char version[]= "Version 1.04.0006 March 12, 2016"; + char version[]= "Version 1.04.0006 May 08, 2016"; #if defined(__WIN__) char compver[]= "Version 1.04.0006 " __DATE__ " " __TIME__; char slash= '\\'; @@ -190,6 +191,10 @@ extern "C" { } // extern "C" #endif // XMSG +#if defined(JDBC_SUPPORT) + char *JvmPath; +#endif // JDBC_SUPPORT + #if defined(__WIN__) CRITICAL_SECTION parsec; // Used calling the Flex parser #else // !__WIN__ @@ -667,6 +672,9 @@ static int connect_init_func(void *p) DTVAL::SetTimeShift(); // Initialize time zone shift once for all BINCOL::SetEndian(); // Initialize host endian setting +#if defined(JDBC_SUPPORT) + JDBConn::SetJVM(); +#endif // JDBC_SUPPORT DBUG_RETURN(0); } // end of connect_init_func @@ -683,13 +691,17 @@ static int connect_done_func(void *) #ifdef LIBXML2_SUPPORT XmlCleanupParserLib(); -#endif // LIBXML2_SUPPORT +#endif // LIBXML2_SUPPORT -#if defined(__WIN__) +#ifdef JDBC_SUPPORT + JDBConn::ResetJVM(); +#endif // JDBC_SUPPORT + +#if defined(__WIN__) DeleteCriticalSection((LPCRITICAL_SECTION)&parsec); -#else // !__WIN__ +#else // !__WIN__ PROFILE_End(); -#endif // !__WIN__ +#endif // !__WIN__ for (pc= user_connect::to_users; pc; pc= pn) { if (pc->g) @@ -6835,6 +6847,15 @@ static MYSQL_SYSVAR_STR(errmsg_dir_path, msg_path, "../../../../storage/connect/"); // for testing #endif // XMSG +#if defined(JDBC_SUPPORT) +static MYSQL_SYSVAR_STR(jvm_path, JvmPath, + PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC, + "Path to the directory where is the JVM lib", + // check_jvm_path, update_jvm_path, + NULL, NULL, NULL); +#endif // JDBC_SUPPORT + + static struct st_mysql_sys_var* connect_system_variables[]= { MYSQL_SYSVAR(xtrace), MYSQL_SYSVAR(conv_size), @@ -6852,7 +6873,8 @@ static struct st_mysql_sys_var* connect_system_variables[]= { MYSQL_SYSVAR(errmsg_dir_path), #endif // XMSG MYSQL_SYSVAR(json_grp_size), - NULL + MYSQL_SYSVAR(jvm_path), + NULL }; maria_declare_plugin(connect) diff --git a/storage/connect/jdbconn.cpp b/storage/connect/jdbconn.cpp index 093c746b59da9..da1eb4eeb1dec 100644 --- a/storage/connect/jdbconn.cpp +++ b/storage/connect/jdbconn.cpp @@ -17,17 +17,19 @@ #include // for getcwd #if defined(__BORLANDC__) #define __MFC_COMPAT__ // To define min/max as macro -#endif +#endif // __BORLANDC__ //#include -#else +#else // !__WIN__ #if defined(UNIX) #include -#else +#else // !UNIX //nclude -#endif +#endif // !UNIX +#include +#include // for getenv //nclude #define NODW -#endif +#endif // !__WIN__ /***********************************************************************/ /* Required objects includes. */ @@ -52,6 +54,14 @@ extern "C" HINSTANCE s_hModule; // Saved module handle #endif // !__WIN__ int GetConvSize(); +extern char *JvmPath; // The connect_jvm_path global variable value + +/***********************************************************************/ +/* Static JDBConn objects. */ +/***********************************************************************/ +void *JDBConn::LibJvm = NULL; +CRTJVM JDBConn::CreateJavaVM = NULL; +GETJVM JDBConn::GetCreatedJavaVMs = NULL; /***********************************************************************/ /* Some macro's (should be defined elsewhere to be more accessible) */ @@ -618,90 +628,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 /***********************************************************************/ @@ -842,13 +768,98 @@ int JDBConn::GetMaxValue(int n) return (int)env->CallIntMethod(job, maxid, n); } // end of GetMaxValue +/***********************************************************************/ +/* Reset the JVM library. */ +/***********************************************************************/ +void JDBConn::ResetJVM(void) +{ + if (!LibJvm) { +#if defined(__WIN__) + FreeLibrary((HMODULE)LibJvm); +#else // !__WIN__ + dlclose(LibJvm); +#endif // !__WIN__ + LibJvm = NULL; + CreateJavaVM = NULL; + GetCreatedJavaVMs = NULL; + } // 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 (JvmPath) + strcat(strcpy(soname, JvmPath), "\\jvm.dll"); + else + strcpy(soname, "jvm.dll"); + +#if defined(__WIN__) + // 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; + } // endif LibJvm +#else // !__WIN__ + const char *error = NULL; + + // 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 = (CRTJVM)dlsym(LibJvm, "JNI_GetCreatedJavaVMs"))) { + error = dlerror(); + sprintf(g->Message, MSG(GET_FUNC_ERR), "JNI_GetCreatedJavaVMs", SVP(error)); + dlclose(LibJvm); + LibJvm = NULL; + } // endif LibJvm +#endif // !__WIN__ + + } // endif LibJvm + + return LibJvm == NULL; +} // end of GetJVM + /***********************************************************************/ /* Open: connect to a data source. */ /***********************************************************************/ int JDBConn::Open(PSZ jpath, PJPARM sop) { PGLOBAL& g = m_G; + + if (GetJVM(g)) + return true; + PSTRG jpop = new(g) STRING(g, 512, "-Djava.class.path="); + char *cp = NULL; char sep; #if defined(__WIN__) @@ -872,15 +883,26 @@ int JDBConn::Open(PSZ jpath, PJPARM 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 ((cp = PlugDup(m_G, getenv("CLASSPATH")))) + jpop->Append(cp); + + if (trace) { + htrc("CLASSPATH=%s\n", cp); + htrc("jpath=%s\n", jpath); + } // endif trace + + if (jpath && *jpath) { + if (cp) + jpop->Append(sep); - if (jpath) { - jpop->Append(sep); jpop->Append(jpath); } // endif jpath + if (trace) + htrc("%s\n", jpop->GetStr()); + options[0].optionString = jpop->GetStr(); //options[1].optionString = "-verbose:jni"; vm_args.version = JNI_VERSION_1_6; // minimum Java version @@ -889,7 +911,7 @@ int JDBConn::Open(PSZ jpath, PJPARM sop) vm_args.ignoreUnrecognized = false; // invalid options make the JVM init fail //=============== load and initialize Java VM and JNI interface ============= - jint rc = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args); // YES !! + jint rc = CreateJavaVM(&jvm, (void**)&env, &vm_args); // YES !! delete options; // we then no longer need the initialisation options. switch (rc) { @@ -914,7 +936,7 @@ int JDBConn::Open(PSZ jpath, PJPARM sop) JavaVM* jvms[1]; jsize jsz; - rc = JNI_GetCreatedJavaVMs(jvms, 1, &jsz); + rc = GetCreatedJavaVMs(jvms, 1, &jsz); if (rc == JNI_OK && jsz == 1) { jvm = jvms[0]; @@ -1952,6 +1974,9 @@ bool JDBConn::SetParam(JDBCCOL *colp) // 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) > (uint)ncol) { strcpy(g->Message, MSG(COL_NUM_MISM)); @@ -1989,9 +2014,12 @@ bool JDBConn::SetParam(JDBCCOL *colp) // Now fetch the result for (i = 0; i < qrp->Maxres; i++) { - if ((rc = Fetch(0)) == 0) + if ((rc = Fetch(0)) == 0) { + if (trace) + htrc("End of fetches i=%d\n", i); + break; - else if (rc < 0) + } else if (rc < 0) return -1; for (n = 0, crp = qrp->Colresp; crp; n++, crp = crp->Next) { diff --git a/storage/connect/jdbconn.h b/storage/connect/jdbconn.h index 99720bf55d590..b226d5d08d6d5 100644 --- a/storage/connect/jdbconn.h +++ b/storage/connect/jdbconn.h @@ -60,6 +60,9 @@ typedef struct tagJCATPARM { PUCHAR Pat; // Table type or column pattern } JCATPARM; +typedef jint(JNICALL *CRTJVM) (JavaVM **, void **, void *); +typedef jint(JNICALL *GETJVM) (JavaVM **, jsize, jsize *); + // JDBC connection to a data source class TDBJDBC; class JDBCCOL; @@ -114,8 +117,11 @@ class JDBConn : public BLOCK { 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; } + static void ResetJVM(void); + static bool GetJVM(PGLOBAL g); // Implementation public: @@ -126,15 +132,17 @@ class JDBConn : public BLOCK { char *Check(void); //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; PGLOBAL m_G; TDBJDBC *m_Tdb; JavaVM *jvm; // Pointer to the JVM (Java Virtual Machine) diff --git a/storage/connect/reldef.cpp b/storage/connect/reldef.cpp index 4b9d99bd8c91b..2c8ada52e6f5c 100644 --- a/storage/connect/reldef.cpp +++ b/storage/connect/reldef.cpp @@ -514,10 +514,11 @@ PTABDEF OEMDEF::GetXdef(PGLOBAL g) } // endif getdef #else // !__WIN__ const char *error = NULL; - Dl_info dl_info; #if 0 // Don't know what all this stuff does - // The OEM lib must retrieve exported CONNECT variables + Dl_info dl_info; + + // The OEM lib must retrieve exported CONNECT variables if (dladdr(&connect_hton, &dl_info)) { if (dlopen(dl_info.dli_fname, RTLD_NOLOAD | RTLD_NOW | RTLD_GLOBAL) == 0) { error = dlerror(); From 6aa163bce8279ed6e67cfa825004ba025ebe12d8 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Thu, 12 May 2016 12:20:52 +0200 Subject: [PATCH 06/18] - Continue working on the JDBC table type Suppress the jpath option add the connect_jvm_path and connect_class_path global variables modified: storage/connect/ha_connect.cc modified: storage/connect/jdbccat.h modified: storage/connect/jdbconn.cpp modified: storage/connect/jdbconn.h modified: storage/connect/tabjdbc.cpp modified: storage/connect/tabjdbc.h - Add the envar UDF modified: storage/connect/jsonudf.cpp modified: storage/connect/jsonudf.h - Fix MDEV-9950 modified: storage/connect/ha_connect.cc modified: storage/connect/plgdbutl.cpp --- storage/connect/ha_connect.cc | 23 ++-- storage/connect/jdbccat.h | 8 +- storage/connect/jdbconn.cpp | 247 ++++++++++++++++++++-------------- storage/connect/jdbconn.h | 11 +- storage/connect/jsonudf.cpp | 27 ++++ storage/connect/jsonudf.h | 4 + storage/connect/plgdbutl.cpp | 2 +- storage/connect/tabjdbc.cpp | 19 +-- storage/connect/tabjdbc.h | 7 +- 9 files changed, 207 insertions(+), 141 deletions(-) diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 7571392ff3adb..58a761f442d93 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -193,12 +193,13 @@ extern "C" { #if defined(JDBC_SUPPORT) char *JvmPath; + char *ClassPath; #endif // JDBC_SUPPORT #if defined(__WIN__) CRITICAL_SECTION parsec; // Used calling the Flex parser #else // !__WIN__ -pthread_mutex_t parmut; +pthread_mutex_t parmut = PTHREAD_MUTEX_INITIALIZER; #endif // !__WIN__ /***********************************************************************/ @@ -5156,7 +5157,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; @@ -5223,7 +5223,6 @@ 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); tabtyp = GetListOption(g, "Tabtype", topt->oplist, NULL); @@ -5510,15 +5509,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: @@ -5526,7 +5524,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); @@ -6853,6 +6851,12 @@ static MYSQL_SYSVAR_STR(jvm_path, JvmPath, "Path to the directory where is the JVM lib", // check_jvm_path, update_jvm_path, NULL, NULL, NULL); + +static MYSQL_SYSVAR_STR(class_path, ClassPath, + PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC, + "Java class path", + // check_class_path, update_class_path, + NULL, NULL, NULL); #endif // JDBC_SUPPORT @@ -6873,7 +6877,10 @@ static struct st_mysql_sys_var* connect_system_variables[]= { MYSQL_SYSVAR(errmsg_dir_path), #endif // XMSG MYSQL_SYSVAR(json_grp_size), +#if defined(JDBC_SUPPORT) MYSQL_SYSVAR(jvm_path), + MYSQL_SYSVAR(class_path), +#endif // JDBC_SUPPORT NULL }; diff --git a/storage/connect/jdbccat.h b/storage/connect/jdbccat.h index 150197804d5cb..37f33d7063d8b 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 da1eb4eeb1dec..fe93ba9a62f0a 100644 --- a/storage/connect/jdbconn.cpp +++ b/storage/connect/jdbconn.cpp @@ -54,7 +54,8 @@ extern "C" HINSTANCE s_hModule; // Saved module handle #endif // !__WIN__ int GetConvSize(); -extern char *JvmPath; // The connect_jvm_path global variable value +extern char *JvmPath; // The connect_jvm_path global variable value +extern char *ClassPath; // The connect_class_path global variable value /***********************************************************************/ /* Static JDBConn objects. */ @@ -213,8 +214,8 @@ static JCATPARM *AllocCatInfo(PGLOBAL g, JCATINFO fid, char *db, /* 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, @@ -236,7 +237,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, '%')) { @@ -315,11 +316,11 @@ 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) { JDBConn *jcp = new(g)JDBConn(g, NULL); - if (jcp->Open(jpath, sjp)) + if (jcp->Open(sjp)) return NULL; return jcp->GetMetaData(g, src); @@ -329,8 +330,8 @@ PQRYRES JDBCSrcCols(PGLOBAL g, char *jpath, char *src, PJPARM sjp) /* 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}; @@ -352,7 +353,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) @@ -429,7 +430,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 }; @@ -446,7 +447,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) @@ -796,12 +797,12 @@ bool JDBConn::GetJVM(PGLOBAL g) if (!LibJvm) { char soname[512]; +#if defined(__WIN__) if (JvmPath) strcat(strcpy(soname, JvmPath), "\\jvm.dll"); else strcpy(soname, "jvm.dll"); -#if defined(__WIN__) // Load the desired shared library if (!(LibJvm = LoadLibrary(soname))) { char buf[256]; @@ -826,6 +827,11 @@ bool JDBConn::GetJVM(PGLOBAL g) #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(); @@ -835,7 +841,7 @@ bool JDBConn::GetJVM(PGLOBAL g) sprintf(g->Message, MSG(GET_FUNC_ERR), "JNI_CreateJavaVM", SVP(error)); dlclose(LibJvm); LibJvm = NULL; - } else if (!(GetCreatedJavaVMs = (CRTJVM)dlsym(LibJvm, "JNI_GetCreatedJavaVMs"))) { + } else if (!(GetCreatedJavaVMs = (GETJVM)dlsym(LibJvm, "JNI_GetCreatedJavaVMs"))) { error = dlerror(); sprintf(g->Message, MSG(GET_FUNC_ERR), "JNI_GetCreatedJavaVMs", SVP(error)); dlclose(LibJvm); @@ -851,112 +857,103 @@ bool JDBConn::GetJVM(PGLOBAL g) /***********************************************************************/ /* Open: connect to a data source. */ /***********************************************************************/ -int JDBConn::Open(PSZ jpath, PJPARM sop) +int JDBConn::Open(PJPARM sop) { PGLOBAL& g = m_G; + // Link or check whether jvm library was linked if (GetJVM(g)) return true; - PSTRG jpop = new(g) STRING(g, 512, "-Djava.class.path="); - char *cp = NULL; - char sep; - -#if defined(__WIN__) - sep = ';'; -#else - sep = ':'; -#endif + // Firstly check whether the jvm was already created + JavaVM* jvms[1]; + jsize jsz; + jint rc = GetCreatedJavaVMs(jvms, 1, &jsz); - 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 + if (rc == JNI_OK && jsz == 1) { + // jvm already existing + jvm = jvms[0]; + rc = jvm->AttachCurrentThread((void**)&env, nullptr); - //================== prepare loading of Java VM ============================ - JavaVMInitArgs vm_args; // Initialization arguments - JavaVMOption* options = new JavaVMOption[1]; // JVM invocation options - - // where to find java .class - if ((cp = PlugDup(m_G, getenv("CLASSPATH")))) - jpop->Append(cp); - - if (trace) { - htrc("CLASSPATH=%s\n", cp); - htrc("jpath=%s\n", jpath); - } // endif trace - - if (jpath && *jpath) { - if (cp) - jpop->Append(sep); - - jpop->Append(jpath); - } // endif jpath + if (rc != JNI_OK) { + strcpy(g->Message, "Cannot attach jvm to the current thread"); + return RC_FX; + } // endif rc - if (trace) - htrc("%s\n", jpop->GetStr()); + } else { + // Create a new jvm + PSTRG jpop = new(g)STRING(g, 512, "-Djava.class.path="); + char *cp = NULL; + char sep; - 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 +#if defined(__WIN__) + sep = ';'; +#else + sep = ':'; +#endif - //=============== load and initialize Java VM and JNI interface ============= - jint rc = CreateJavaVM(&jvm, (void**)&env, &vm_args); // YES !! - delete options; // we then no longer need the initialisation options. + //================== prepare loading of Java VM ============================ + JavaVMInitArgs vm_args; // Initialization arguments + JavaVMOption* options = new JavaVMOption[1]; // JVM invocation options - 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"); - return RC_FX; - case JNI_EEXIST: - strcpy(g->Message, "VM already created"); - { - JavaVM* jvms[1]; - jsize jsz; + // where to find java .class + if ((cp = PlugDup(m_G, getenv("CLASSPATH")))) + jpop->Append(cp); - rc = GetCreatedJavaVMs(jvms, 1, &jsz); + if (trace) { + htrc("CLASSPATH=%s\n", getenv("CLASSPATH")); + htrc("ClassPath=%s\n", ClassPath); + } // endif trace - if (rc == JNI_OK && jsz == 1) { - jvm = jvms[0]; - rc = jvm->AttachCurrentThread((void**)&env, nullptr); - } // endif rc + if (ClassPath && *ClassPath) { + if (cp) + jpop->Append(sep); - } // end of block + jpop->Append(ClassPath); + } // endif ClassPath - if (rc == JNI_OK) + if (trace) + htrc("%s\n", jpop->GetStr()); + + 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 + + //=============== 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(); @@ -970,6 +967,44 @@ int JDBConn::Open(PSZ jpath, PJPARM sop) 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())) { + 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, "", "()V"); @@ -1003,6 +1038,18 @@ int JDBConn::Open(PSZ jpath, PJPARM sop) jobjectArray parms = env->NewObjectArray(4, // constructs java array of 4 env->FindClass("java/lang/String"), NULL); // Strings + if (sop) { + m_Driver = sop->Driver; + m_Url = sop->Url; + m_User = sop->User; + m_Pwd = sop->Pwd; + m_Scrollable = sop->Scrollable; + m_RowsetSize = sop->Fsize; + //m_LoginTimeout = sop->Cto; + //m_QueryTimeout = sop->Qto; + //m_UseCnc = sop->UseCnc; + } // endif sop + // change some elements if (m_Driver) env->SetObjectArrayElement(parms, 0, env->NewStringUTF(m_Driver)); diff --git a/storage/connect/jdbconn.h b/storage/connect/jdbconn.h index b226d5d08d6d5..4014a52cdcc2b 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 @@ -82,7 +73,7 @@ class JDBConn : public BLOCK { 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); diff --git a/storage/connect/jsonudf.cpp b/storage/connect/jsonudf.cpp index 0b5688c58ab20..d377b7d4b6324 100644 --- a/storage/connect/jsonudf.cpp +++ b/storage/connect/jsonudf.cpp @@ -5027,3 +5027,30 @@ void json_serialize_deinit(UDF_INIT* initid) { JsonFreeMem((PGLOBAL)initid->ptr); } // end of json_serialize_deinit + +/*********************************************************************************/ +/* Utility function returning an environment variable value. */ +/*********************************************************************************/ +my_bool envar_init(UDF_INIT *initid, UDF_ARGS *args, char *message) +{ + if (args->arg_count != 1) { + strcpy(message, "Unique argument must be an environment variable name"); + return true; + } else + return false; + +} // end of envar_init + +char *envar(UDF_INIT *initid, UDF_ARGS *args, char *result, + unsigned long *res_length, char *, char *) +{ + char *str, name[256]; + int n = MY_MIN(args->lengths[0], sizeof(name) - 1); + + memcpy(name, args->args[0], n); + name[n] = 0; + str = getenv(name); + *res_length = (str) ? strlen(str) : 0; + return str; +} // end of envar + diff --git a/storage/connect/jsonudf.h b/storage/connect/jsonudf.h index b7e9b8ecabb07..1406d9f2f2e94 100644 --- a/storage/connect/jsonudf.h +++ b/storage/connect/jsonudf.h @@ -218,8 +218,12 @@ extern "C" { DllExport my_bool json_serialize_init(UDF_INIT*, UDF_ARGS*, char*); DllExport char *json_serialize(UDF_EXEC_ARGS); DllExport void json_serialize_deinit(UDF_INIT*); + + DllExport my_bool envar_init(UDF_INIT*, UDF_ARGS*, char*); + DllExport char *envar(UDF_EXEC_ARGS); } // extern "C" + /*********************************************************************************/ /* Structure JPN. Used to make the locate path. */ /*********************************************************************************/ diff --git a/storage/connect/plgdbutl.cpp b/storage/connect/plgdbutl.cpp index 799df7cfc5138..13c0dfd1e1892 100644 --- a/storage/connect/plgdbutl.cpp +++ b/storage/connect/plgdbutl.cpp @@ -5,7 +5,7 @@ /* */ /* COPYRIGHT: */ /* ---------- */ -/* (C) Copyright to the author Olivier BERTRAND 1998-2015 */ +/* (C) Copyright to the author Olivier BERTRAND 1998-2016 */ /* */ /* WHAT THIS PROGRAM DOES: */ /* ----------------------- */ diff --git a/storage/connect/tabjdbc.cpp b/storage/connect/tabjdbc.cpp index ce73349d9f75e..37850ce6358cc 100644 --- a/storage/connect/tabjdbc.cpp +++ b/storage/connect/tabjdbc.cpp @@ -95,7 +95,7 @@ bool ExactInfo(void); /***********************************************************************/ JDBCDEF::JDBCDEF(void) { - Jpath = Driver = Url = Tabname = Tabschema = Username = NULL; + Driver = Url = Tabname = Tabschema = Username = NULL; Password = Tabcat = Tabtype = Srcdef = Qchar = Qrystr = Sep = NULL; Options = Quoted = Maxerr = Maxres = Memory = 0; Scrollable = Xsrc = false; @@ -106,7 +106,6 @@ JDBCDEF::JDBCDEF(void) /***********************************************************************/ bool JDBCDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) { - Jpath = GetStringCatInfo(g, "Jpath", ""); Driver = GetStringCatInfo(g, "Driver", NULL); Desc = Url = GetStringCatInfo(g, "Connect", NULL); @@ -222,7 +221,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; @@ -241,7 +239,6 @@ TDBJDBC::TDBJDBC(PJDBCDEF tdp) : TDBASE(tdp) Memory = tdp->Memory; Ops.Scrollable = tdp->Scrollable; } else { - Jpath = NULL; TableName = NULL; Schema = NULL; Ops.Driver = NULL; @@ -286,7 +283,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; @@ -684,7 +680,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 @@ -795,7 +791,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(); @@ -1545,7 +1541,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 @@ -1657,7 +1653,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 --------------------------- */ @@ -1667,7 +1663,6 @@ PQRYRES TDBJDRV::GetResult(PGLOBAL g) /***********************************************************************/ TDBJTB::TDBJTB(PJDBCDEF tdp) : TDBJDRV(tdp) { - Jpath = tdp->Jpath; Schema = tdp->Tabschema; Tab = tdp->Tabname; Tabtype = tdp->Tabtype; @@ -1684,7 +1679,7 @@ 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 -------------------------- */ @@ -1694,7 +1689,7 @@ PQRYRES TDBJTB::GetResult(PGLOBAL g) /***********************************************************************/ PQRYRES TDBJDBCL::GetResult(PGLOBAL g) { - return JDBCColumns(g, Jpath, Schema, Tab, NULL, Maxres, false, &Ops); + return JDBCColumns(g, Schema, Tab, NULL, Maxres, false, &Ops); } // end of GetResult #if 0 diff --git a/storage/connect/tabjdbc.h b/storage/connect/tabjdbc.h index d3ac3784d2f61..1624b9036104e 100644 --- a/storage/connect/tabjdbc.h +++ b/storage/connect/tabjdbc.h @@ -31,7 +31,6 @@ class DllExport JDBCDEF : public TABDEF { /* Logical table description */ // 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; } @@ -48,7 +47,6 @@ class DllExport JDBCDEF : public TABDEF { /* Logical table description */ protected: // Members - PSZ Jpath; /* Java class path */ PSZ Driver; /* JDBC driver */ PSZ Url; /* JDBC driver URL */ PSZ Tabname; /* External table name */ @@ -130,7 +128,6 @@ class TDBJDBC : public TDBASE { 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 +279,7 @@ class JSRCCOL : public JDBCCOL { 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 +287,6 @@ class TDBJDRV : public TDBCAT { // Members int Maxres; // Returned lines limit - char *Jpath; // Java class path }; // end of class TDBJDRV /***********************************************************************/ @@ -306,7 +302,6 @@ class TDBJTB : public TDBJDRV { 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 From 0f5ced1dd5f8b21b57effbcd2c4b699d214f7d79 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Thu, 12 May 2016 15:41:21 +0200 Subject: [PATCH 07/18] - Fix some typo ... causing crash! modified: storage/connect/jdbconn.cpp --- storage/connect/jdbconn.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/storage/connect/jdbconn.cpp b/storage/connect/jdbconn.cpp index fe93ba9a62f0a..88557fdd420d3 100644 --- a/storage/connect/jdbconn.cpp +++ b/storage/connect/jdbconn.cpp @@ -774,7 +774,7 @@ int JDBConn::GetMaxValue(int n) /***********************************************************************/ void JDBConn::ResetJVM(void) { - if (!LibJvm) { + if (LibJvm) { #if defined(__WIN__) FreeLibrary((HMODULE)LibJvm); #else // !__WIN__ @@ -863,7 +863,7 @@ int JDBConn::Open(PJPARM sop) // Link or check whether jvm library was linked if (GetJVM(g)) - return true; + return RC_FX; // Firstly check whether the jvm was already created JavaVM* jvms[1]; From 7972a45b4343cf620f4dc6d508ff9e0c1ca000e3 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Thu, 12 May 2016 17:22:45 +0200 Subject: [PATCH 08/18] - Remove REQUIRED option that caused compilation to fail Remove JVM_LIBRARY (is now dynamically loaded at run time) modified: storage/connect/CMakeLists.txt --- storage/connect/CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/storage/connect/CMakeLists.txt b/storage/connect/CMakeLists.txt index f4bcbfa9ade3a..fa2fb7b4ddd90 100644 --- a/storage/connect/CMakeLists.txt +++ b/storage/connect/CMakeLists.txt @@ -268,12 +268,12 @@ IF(CONNECT_WITH_JDBC) # TODO: Find how to compile and install the JdbcInterface.java class # Find required libraries and include directories - FIND_PACKAGE(Java REQUIRED) - FIND_PACKAGE(JNI REQUIRED) + FIND_PACKAGE(Java) + FIND_PACKAGE(JNI) IF (JAVA_FOUND AND JNI_FOUND) INCLUDE_DIRECTORIES(${JAVA_INCLUDE_PATH}) INCLUDE_DIRECTORIES(${JAVA_INCLUDE_PATH2}) - SET(JDBC_LIBRARY ${JAVA_JVM_LIBRARY}) + # SET(JDBC_LIBRARY ${JAVA_JVM_LIBRARY}) SET(CONNECT_SOURCES ${CONNECT_SOURCES} JdbcInterface.java JdbcInterface.class jdbconn.cpp tabjdbc.cpp jdbconn.h tabjdbc.h jdbccat.h) From 2f2797e52f235e6edae8627ac0700f8e43809859 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Fri, 20 May 2016 00:18:29 +0200 Subject: [PATCH 09/18] - JDBC tables can be connected via foreign server wrapper Redesign the handling of errors and exceptions modified: storage/connect/ha_connect.cc modified: storage/connect/jdbconn.cpp modified: storage/connect/jdbconn.h modified: storage/connect/tabjdbc.cpp modified: storage/connect/tabjdbc.h --- storage/connect/ha_connect.cc | 34 ++- storage/connect/jdbconn.cpp | 497 ++++++++++++++++------------------ storage/connect/jdbconn.h | 5 +- storage/connect/tabjdbc.cpp | 131 ++++++++- storage/connect/tabjdbc.h | 3 + 5 files changed, 373 insertions(+), 297 deletions(-) diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 58a761f442d93..0534884e68413 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -119,6 +119,7 @@ #undef OFFSET #define NOPARSE +#define NJDBC #if defined(UNIX) #include "osutil.h" #endif // UNIX @@ -128,7 +129,7 @@ #include "odbccat.h" #endif // ODBC_SUPPORT #if defined(JDBC_SUPPORT) -#include "jdbccat.h" +#include "tabjdbc.h" #include "jdbconn.h" #endif // JDBC_SUPPORT #include "xtable.h" @@ -5224,7 +5225,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd, #endif #if defined(JDBC_SUPPORT) driver= GetListOption(g, "Driver", topt->oplist, NULL); - url= GetListOption(g, "URL", topt->oplist, NULL); +// url= GetListOption(g, "URL", topt->oplist, NULL); tabtyp = GetListOption(g, "Tabtype", topt->oplist, NULL); #endif // JDBC_SUPPORT mxe= atoi(GetListOption(g,"maxerr", topt->oplist, "0")); @@ -5325,18 +5326,31 @@ static int connect_assisted_discovery(handlerton *, THD* thd, case TAB_JDBC: if (fnc & FNC_DRIVER) { ok= true; - } else if (!url && !(url= strz(g, create_info->connect_string))) { + } else if (!(url= strz(g, create_info->connect_string))) { strcpy(g->Message, "Missing URL"); } else { - // Store ODBC additional parameters + // Store JDBC additional parameters + int rc; + PJDBCDEF jdef= new(g) JDBCDEF(); + + jdef->SetName(create_info->alias); sjp= (PJPARM)PlugSubAlloc(g, NULL, sizeof(JDBCPARM)); sjp->Driver= driver; - sjp->Url= url; - sjp->User= (char*)user; - sjp->Pwd= (char*)pwd; sjp->Fsize= 0; sjp->Scrollable= false; - ok= true; + + if ((rc = jdef->ParseURL(g, url, false)) == RC_OK) { + sjp->Url= url; + sjp->User= (char*)user; + sjp->Pwd= (char*)pwd; + ok= true; + } else if (rc == RC_NF) { + if (jdef->GetTabname()) + tab= jdef->GetTabname(); + + ok= jdef->SetParms(sjp); + } // endif rc + } // endif's supfnc |= (FNC_DRIVER | FNC_TABLE); @@ -5775,12 +5789,10 @@ static int connect_assisted_discovery(handlerton *, THD* thd, switch (typ) { case TYPE_DOUBLE: + case TYPE_DECIM: // Some data sources do not count dec in length (prec) prec += (dec + 2); // To be safe break; - case TYPE_DECIM: - prec= len; - break; default: dec= 0; } // endswitch typ diff --git a/storage/connect/jdbconn.cpp b/storage/connect/jdbconn.cpp index 88557fdd420d3..1d2242060e133 100644 --- a/storage/connect/jdbconn.cpp +++ b/storage/connect/jdbconn.cpp @@ -38,7 +38,6 @@ #include "plgdbsem.h" #include "xobject.h" #include "xtable.h" -#include "jdbccat.h" #include "tabjdbc.h" //#include "jdbconn.h" //#include "plgcnx.h" // For DB types @@ -118,6 +117,7 @@ int TranslateJDBCType(int stp, int prec, int& len, char& v) break; case 2: // NUMERIC case 3: // DECIMAL + case -3: // VARBINARY type = TYPE_DECIM; break; case 4: // INTEGER @@ -155,7 +155,6 @@ int TranslateJDBCType(int stp, int prec, int& len, char& v) break; case 0: // NULL case -2: // BINARY - case -3: // VARBINARY case -4: // LONGVARBINARY default: type = TYPE_ERROR; @@ -318,12 +317,15 @@ PQRYRES JDBCColumns(PGLOBAL g, char *db, char *table, char *colpat, /**************************************************************************/ PQRYRES JDBCSrcCols(PGLOBAL g, char *src, PJPARM sjp) { + PQRYRES qrp; JDBConn *jcp = new(g)JDBConn(g, NULL); if (jcp->Open(sjp)) return NULL; - return jcp->GetMetaData(g, src); + qrp = jcp->GetMetaData(g, src); + jcp->Close(); + return qrp; } // end of JDBCSrcCols /**************************************************************************/ @@ -361,14 +363,14 @@ PQRYRES JDBCTables(PGLOBAL g, char *db, char *tabpat, char *tabtyp, n = jcp->GetMaxValue(2); // Max catalog name length - if (n < 0) - return NULL; +// if (n < 0) +// return NULL; - length[0] = (n) ? (n + 1) : 0; + length[0] = (n > 0) ? (n + 1) : 0; n = jcp->GetMaxValue(3); // Max schema name length - length[1] = (n) ? (n + 1) : 0; + length[1] = (n > 0) ? (n + 1) : 0; n = jcp->GetMaxValue(4); // Max table name length - length[2] = (n) ? (n + 1) : 128; + length[2] = (n > 0) ? (n + 1) : 128; } else { maxres = 0; length[0] = 128; @@ -642,11 +644,12 @@ JDBConn::JDBConn(PGLOBAL g, TDBJDBC *tdbp) env= nullptr; // Pointer to native interface jdi = nullptr; // Pointer to the JdbcInterface class job = nullptr; // The JdbcInterface class object - xqid = xuid = xid = grs = readid = fetchid = typid = nullptr; + xqid = xuid = xid = grs = readid = fetchid = typid = errid = nullptr; prepid = xpid = pcid = nullptr; //m_LoginTimeout = DEFAULT_LOGIN_TIMEOUT; //m_QueryTimeout = DEFAULT_QUERY_TIMEOUT; //m_UpdateOptions = 0; + Msg = NULL; m_Driver = NULL; m_Url = NULL; m_User = NULL; @@ -676,10 +679,11 @@ JDBConn::JDBConn(PGLOBAL g, TDBJDBC *tdbp) /***********************************************************************/ /* Screen for errors. */ /***********************************************************************/ -char *JDBConn::Check(void) +bool JDBConn::Check(jint rc) { + jstring s; + if (env->ExceptionCheck()) { - char *msg; jthrowable exc = env->ExceptionOccurred(); jmethodID tid = env->GetMethodID(env->FindClass("java/lang/Object"), "toString", "()Ljava/lang/String;"); @@ -688,17 +692,39 @@ char *JDBConn::Check(void) jstring s = (jstring)env->CallObjectMethod(exc, tid); const char *utf = env->GetStringUTFChars(s, (jboolean)false); env->DeleteLocalRef(s); - msg = PlugDup(m_G, utf); + Msg = PlugDup(m_G, utf); } else - msg = "Exception occured"; + Msg = "Exception occured"; env->ExceptionClear(); - return msg; - } // endif Check + } else if (rc < 0) { + s = (jstring)env->CallObjectMethod(job, errid); + Msg = (char*)env->GetStringUTFChars(s, (jboolean)false); + } else + Msg = NULL; - return NULL; + return (Msg != NULL); } // end of Check +/***********************************************************************/ +/* Get MethodID if not exists yet. */ +/***********************************************************************/ +bool JDBConn::gmID(PGLOBAL g, jmethodID& mid, const char *name, const char *sig) +{ + if (mid == nullptr) { + mid = env->GetMethodID(jdi, name, sig); + + if (Check()) { + strcpy(g->Message, Msg); + return true; + } else + return false; + + } else + return false; + +} // end of gmID + #if 0 /***********************************************************************/ /* Utility routine. */ @@ -758,15 +784,17 @@ void JDBConn::OnSetOptions(HSTMT hstmt) /***********************************************************************/ int JDBConn::GetMaxValue(int n) { - jmethodID maxid = env->GetMethodID(jdi, "GetMaxValue", "(I)I"); + jint m; + jmethodID maxid = nullptr; - if (maxid == nullptr) { - strcpy(m_G->Message, "ERROR: method GetMaxValue not found !"); + if (gmID(m_G, maxid, "GetMaxValue", "(I)I")) return -1; - } // endif maxid // call method - return (int)env->CallIntMethod(job, maxid, n); + if (Check(m = env->CallIntMethod(job, maxid, n))) + htrc("GetMaxValue: %s", Msg); + + return (int)m; } // end of GetMaxValue /***********************************************************************/ @@ -859,6 +887,7 @@ bool JDBConn::GetJVM(PGLOBAL g) /***********************************************************************/ int JDBConn::Open(PJPARM sop) { + bool err = false; PGLOBAL& g = m_G; // Link or check whether jvm library was linked @@ -881,8 +910,10 @@ int JDBConn::Open(PJPARM sop) } // endif rc } else { - // Create a new jvm - PSTRG jpop = new(g)STRING(g, 512, "-Djava.class.path="); + /*******************************************************************/ + /* Create a new jvm */ + /*******************************************************************/ + PSTRG jpop = new(g)STRING(g, 512, "-Djava.class.path=."); char *cp = NULL; char sep; @@ -897,23 +928,21 @@ int JDBConn::Open(PJPARM sop) JavaVMOption* options = new JavaVMOption[1]; // JVM invocation options // where to find java .class - if ((cp = PlugDup(m_G, getenv("CLASSPATH")))) - jpop->Append(cp); - - if (trace) { - htrc("CLASSPATH=%s\n", getenv("CLASSPATH")); - htrc("ClassPath=%s\n", ClassPath); - } // endif trace - if (ClassPath && *ClassPath) { - if (cp) - jpop->Append(sep); - + jpop->Append(sep); jpop->Append(ClassPath); } // endif ClassPath - if (trace) + if ((cp = getenv("CLASSPATH"))) { + jpop->Append(sep); + jpop->Append(cp); + } // endif cp + + if (trace) { + htrc("ClassPath=%s\n", ClassPath); + htrc("CLASSPATH=%s\n", cp); htrc("%s\n", jpop->GetStr()); + } // endif trace options[0].optionString = jpop->GetStr(); //options[1].optionString = "-verbose:jni"; @@ -981,7 +1010,7 @@ int JDBConn::Open(PJPARM sop) jstring path = env->NewStringUTF(jpath); rc = env->CallStaticIntMethod(jdi, alp, path); - if ((msg = Check())) { + if ((msg = Check(rc))) { strcpy(g->Message, msg); env->DeleteLocalRef(path); return RC_FX; @@ -1022,33 +1051,36 @@ int JDBConn::Open(PJPARM sop) return RC_FX; } // endif job - if (!sop) // DRIVER catalog table - return RC_OK; - - jmethodID cid = env->GetMethodID(jdi, "JdbcConnect", "([Ljava/lang/String;IZ)I"); + errid = env->GetMethodID(jdi, "GetErrmsg", "()Ljava/lang/String;"); if (env->ExceptionCheck()) { - strcpy(g->Message, "ERROR: method JdbcConnect() not found!"); + strcpy(g->Message, "ERROR: method GetErrmsg() not found!"); env->ExceptionDescribe(); env->ExceptionClear(); return RC_FX; } // endif Check + if (!sop) // DRIVER catalog table + return RC_OK; + + jmethodID cid = nullptr; + + if (gmID(g, cid, "JdbcConnect", "([Ljava/lang/String;IZ)I")) + return RC_FX; + // Build the java string array jobjectArray parms = env->NewObjectArray(4, // constructs java array of 4 env->FindClass("java/lang/String"), NULL); // Strings - if (sop) { - m_Driver = sop->Driver; - m_Url = sop->Url; - m_User = sop->User; - m_Pwd = sop->Pwd; - m_Scrollable = sop->Scrollable; - m_RowsetSize = sop->Fsize; - //m_LoginTimeout = sop->Cto; - //m_QueryTimeout = sop->Qto; - //m_UseCnc = sop->UseCnc; - } // endif sop + m_Driver = sop->Driver; + m_Url = sop->Url; + m_User = sop->User; + m_Pwd = sop->Pwd; + m_Scrollable = sop->Scrollable; + m_RowsetSize = sop->Fsize; + //m_LoginTimeout = sop->Cto; + //m_QueryTimeout = sop->Qto; + //m_UseCnc = sop->UseCnc; // change some elements if (m_Driver) @@ -1065,23 +1097,17 @@ int JDBConn::Open(PJPARM sop) // call method rc = env->CallIntMethod(job, cid, parms, m_RowsetSize, m_Scrollable); + err = Check(rc); + env->DeleteLocalRef(parms); // Not used anymore - // Not used anymore - env->DeleteLocalRef(parms); - - if (rc != (jint)0) { - strcpy(g->Message, "Connection failed"); + if (err) { + sprintf(g->Message, "Connecting: %s rc=%d", Msg, (int)rc); return RC_FX; - } // endif rc + } // endif Msg - typid = env->GetMethodID(jdi, "ColumnType", "(ILjava/lang/String;)I"); - - if (env->ExceptionCheck()) { - strcpy(g->Message, "ERROR: method ColumnType() not found!"); - env->ExceptionDescribe(); - env->ExceptionClear(); + if (gmID(g, typid, "ColumnType", "(ILjava/lang/String;)I")) return RC_FX; - } else + else m_Opened = true; return RC_OK; @@ -1092,43 +1118,37 @@ int JDBConn::Open(PJPARM sop) /***********************************************************************/ int JDBConn::ExecSQLcommand(char *sql) { - int rc = RC_NF; + int rc; jint n; jstring qry; PGLOBAL& g = m_G; - if (xid == nullptr) { - // Get the methods used to execute a query and get the result - xid = env->GetMethodID(jdi, "Execute", "(Ljava/lang/String;)I"); - - if (xid == nullptr) { - strcpy(g->Message, "Cannot find method Execute"); - return RC_FX; - } else - grs = env->GetMethodID(jdi, "GetResult", "()I"); - - if (grs == nullptr) { - strcpy(g->Message, "Cannot find method GetResult"); - return RC_FX; - } // endif grs - - } // endif xid + // Get the methods used to execute a query and get the result + if (gmID(g, xid, "Execute", "(Ljava/lang/String;)I") || + gmID(g, grs, "GetResult", "()I")) + return RC_FX; qry = env->NewStringUTF(sql); n = env->CallIntMethod(job, xid, qry); env->DeleteLocalRef(qry); - if (n < 0) { - sprintf(g->Message, "Error executing %s", sql); + if (Check(n)) { + sprintf(g->Message, "Execute: %s", Msg); return RC_FX; } // endif n - if ((m_Ncol = env->CallIntMethod(job, grs))) { + m_Ncol = env->CallIntMethod(job, grs); + + if (Check(m_Ncol)) { + sprintf(g->Message, "GetResult: %s", Msg); + rc = RC_FX; + } else if (m_Ncol) { strcpy(g->Message, "Result set column number"); rc = RC_OK; // A result set was returned } else { m_Aff = (int)n; // Affected rows strcpy(g->Message, "Affected rows"); + rc = RC_NF; } // endif ncol return rc; @@ -1139,44 +1159,29 @@ int JDBConn::ExecSQLcommand(char *sql) /***********************************************************************/ int JDBConn::Fetch(int pos) { - jint rc; + jint rc = JNI_ERR; + PGLOBAL& g = m_G; if (m_Full) // Result set has one row return 1; if (pos) { if (!m_Scrollable) { - strcpy(m_G->Message, "Cannot fetch(pos) if FORWARD ONLY"); - return -1; - } else if (fetchid == nullptr) { - fetchid = env->GetMethodID(jdi, "Fetch", "(I)Z"); - - if (fetchid == nullptr) { - strcpy(m_G->Message, "Cannot find method Fetch"); - return -1; - } // endif fetchid - - } // endif's + strcpy(g->Message, "Cannot fetch(pos) if FORWARD ONLY"); + return rc; + } else if (gmID(m_G, fetchid, "Fetch", "(I)Z")) + return rc; if (env->CallBooleanMethod(job, fetchid, pos)) rc = m_Rows; - else - rc = -1; } else { - if (readid == nullptr) { - readid = env->GetMethodID(jdi, "ReadNext", "()I"); - - if (readid == nullptr) { - strcpy(m_G->Message, "Cannot find method ReadNext"); - return -1; - } // endif readid - - } // endif readid + if (gmID(g, readid, "ReadNext", "()I")) + return rc; rc = env->CallBooleanMethod(job, readid); - if (rc >= 0) { + if (!Check(rc)) { if (rc == 0) m_Full = (m_Fetch == 1); else @@ -1184,7 +1189,7 @@ int JDBConn::Fetch(int pos) m_Rows += (int)rc; } else - strcpy(m_G->Message, "Error fetching next row"); + sprintf(g->Message, "Fetch: %s", Msg); } // endif pos @@ -1201,15 +1206,8 @@ int JDBConn::Rewind(char *sql) if (m_Full) rbuf = m_Rows; // No need to "rewind" else if (m_Scrollable) { - if (fetchid == nullptr) { - fetchid = env->GetMethodID(jdi, "Fetch", "(I)Z"); - - if (fetchid == nullptr) { - strcpy(m_G->Message, "Cannot find method Fetch"); - return -1; - } // endif readid - - } // endif readid + if (gmID(m_G, fetchid, "Fetch", "(I)Z")) + return -1; jboolean b = env->CallBooleanMethod(job, fetchid, 0); @@ -1227,15 +1225,15 @@ void JDBConn::Close() { if (m_Opened) { jint rc; - jmethodID did = env->GetMethodID(jdi, "JdbcDisconnect", "()I"); + jmethodID did = nullptr; - if (did == nullptr) - printf("ERROR: method JdbcDisconnect() not found !"); - else if ((rc = env->CallIntMethod(job, did))) - printf("jdbcDisconnect: rc=%d", (int)rc); + if (gmID(m_G, did, "JdbcDisconnect", "()I")) + printf("%s\n", Msg); + else if (Check(env->CallIntMethod(job, did))) + printf("jdbcDisconnect: %s\n", Msg); - if ((rc = jvm->DetachCurrentThread())) - printf("DetachCurrentThread: rc = %d", (int)rc); + if ((rc = jvm->DetachCurrentThread()) != JNI_OK) + printf("DetachCurrentThread: rc=%d\n", (int)rc); //rc = jvm->DestroyJavaVM(); m_Opened = false; @@ -1249,7 +1247,6 @@ void JDBConn::Close() void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val) { PGLOBAL& g = m_G; - char *msg; jint ctyp; jlong dtv; jstring cn, jn = nullptr; @@ -1262,10 +1259,11 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val) longjmp(g->jumper[g->jump_level], TYPE_AM_JDBC); } // endif name + // Returns 666 is case of error ctyp = env->CallIntMethod(job, typid, rank, jn); - if ((msg = Check())) { - sprintf(g->Message, "Getting ctyp: %s", msg); + if (Check((ctyp == 666) ? -1 : 1)) { + sprintf(g->Message, "Getting ctyp: %s", Msg); longjmp(g->jumper[g->jump_level], TYPE_AM_JDBC); } // endif Check @@ -1303,6 +1301,7 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val) break; case 8: // DOUBLE + case 2: // NUMERIC case 3: // DECIMAL fldid = env->GetMethodID(jdi, "DoubleField", "(ILjava/lang/String;)D"); @@ -1372,11 +1371,11 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val) val->Reset(); } // endswitch Type - if ((msg = Check())) { + if (Check()) { if (rank == 0) env->DeleteLocalRef(jn); - sprintf(g->Message, "SetColumnValue: %s rank=%d ctyp=%d", msg, rank, (int)ctyp); + sprintf(g->Message, "SetColumnValue: %s rank=%d ctyp=%d", Msg, rank, (int)ctyp); longjmp(g->jumper[g->jump_level], TYPE_AM_JDBC); } // endif Check @@ -1390,21 +1389,22 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val) /***********************************************************************/ bool JDBConn::PrepareSQL(char *sql) { - if (prepid == nullptr) { - prepid = env->GetMethodID(jdi, "CreatePrepStmt", "(Ljava/lang/String;)Z"); + bool b = true; + PGLOBAL& g = m_G; - if (prepid == nullptr) { - strcpy(m_G->Message, "Cannot find method CreatePrepStmt"); - return true; - } // endif prepid + if (!gmID(g, prepid, "CreatePrepStmt", "(Ljava/lang/String;)I")) { + // Create the prepared statement + jstring qry = env->NewStringUTF(sql); + if (Check(env->CallBooleanMethod(job, prepid, qry))) + sprintf(g->Message, "CreatePrepStmt: %s", Msg); + else + b = false; + + env->DeleteLocalRef(qry); } // endif prepid - - // Create the prepared statement - jstring qry = env->NewStringUTF(sql); - jboolean b = env->CallBooleanMethod(job, prepid, qry); - env->DeleteLocalRef(qry); - return (bool)b; + + return b; } // end of PrepareSQL /***********************************************************************/ @@ -1412,32 +1412,25 @@ bool JDBConn::PrepareSQL(char *sql) /***********************************************************************/ int JDBConn::ExecuteQuery(char *sql) { + int rc = RC_FX; jint ncol; jstring qry; PGLOBAL& g = m_G; - if (xqid == nullptr) { - // Get the methods used to execute a query and get the result - xqid = env->GetMethodID(jdi, "ExecuteQuery", "(Ljava/lang/String;)I"); + // Get the methods used to execute a query and get the result + if (!gmID(g, xqid, "ExecuteQuery", "(Ljava/lang/String;)I")) { + qry = env->NewStringUTF(sql); + ncol = env->CallIntMethod(job, xqid, qry); - if (xqid == nullptr) { - strcpy(g->Message, "Cannot find method ExecuteQuery"); - return RC_FX; - } // endif !xqid - - } // endif xqid - - qry = env->NewStringUTF(sql); - ncol = env->CallIntMethod(job, xqid, qry); - env->DeleteLocalRef(qry); + if (!Check(ncol)) { + m_Ncol = (int)ncol; + m_Aff = 0; // Affected rows + rc = RC_OK; + } else + sprintf(g->Message, "ExecuteQuery: %s", Msg); - if (ncol < 0) { - sprintf(g->Message, "Error executing %s: ncol = %d", sql, ncol); - return RC_FX; - } else { - m_Ncol = (int)ncol; - m_Aff = 0; // Affected rows - } // endif ncol + env->DeleteLocalRef(qry); + } // endif xqid return RC_OK; } // end of ExecuteQuery @@ -1447,34 +1440,27 @@ int JDBConn::ExecuteQuery(char *sql) /***********************************************************************/ int JDBConn::ExecuteUpdate(char *sql) { + int rc = RC_FX; jint n; jstring qry; PGLOBAL& g = m_G; - if (xuid == nullptr) { - // Get the methods used to execute a query and get the affected rows - xuid = env->GetMethodID(jdi, "ExecuteUpdate", "(Ljava/lang/String;)I"); + // Get the methods used to execute a query and get the affected rows + if (!gmID(g, xuid, "ExecuteUpdate", "(Ljava/lang/String;)I")) { + qry = env->NewStringUTF(sql); + n = env->CallIntMethod(job, xuid, qry); - if (xuid == nullptr) { - strcpy(g->Message, "Cannot find method ExecuteUpdate"); - return RC_FX; - } // endif !xuid - - } // endif xuid + if (!Check(n)) { + m_Ncol = 0; + m_Aff = (int)n; // Affected rows + rc = RC_OK; + } else + sprintf(g->Message, "ExecuteUpdate: %s n=%d", Msg, n); - qry = env->NewStringUTF(sql); - n = env->CallIntMethod(job, xuid, qry); - env->DeleteLocalRef(qry); + env->DeleteLocalRef(qry); + } // endif xuid - if (n < 0) { - sprintf(g->Message, "Error executing %s: n = %d", sql, n); - return RC_FX; - } else { - m_Ncol = 0; - m_Aff = (int)n; // Affected rows - } // endif n - - return RC_OK; + return rc; } // end of ExecuteUpdate /***********************************************************************/ @@ -1507,32 +1493,21 @@ int JDBConn::ExecuteSQL(void) int rc = RC_FX; PGLOBAL& g = m_G; - if (xpid == nullptr) { - // Get the methods used to execute a prepared statement - xpid = env->GetMethodID(jdi, "ExecutePrep", "()I"); + // Get the methods used to execute a prepared statement + if (!gmID(g, xpid, "ExecutePrep", "()I")) { + jint n = env->CallIntMethod(job, xpid); - if (xpid == nullptr) { - strcpy(g->Message, "Cannot find method ExecutePrep"); - return rc; - } // endif xpid + if (n == -3) + strcpy(g->Message, "SQL statement is not prepared"); + else if (Check(n)) + sprintf(g->Message, "ExecutePrep: %s", Msg); + else { + m_Aff = (int)n; + rc = RC_OK; + } // endswitch n } // endif xpid - jint n = env->CallIntMethod(job, xpid); - - switch ((int)n) { - case -1: - case -2: - strcpy(g->Message, "Exception error thrown while executing SQL"); - break; - case -3: - strcpy(g->Message, "SQL statement is not prepared"); - break; - default: - m_Aff = (int)n; - rc = RC_OK; - } // endswitch n - return rc; } // end of ExecuteSQL @@ -1542,8 +1517,7 @@ int JDBConn::ExecuteSQL(void) bool JDBConn::SetParam(JDBCCOL *colp) { PGLOBAL& g = m_G; - char *msg; - int rc = false; + bool rc = false; PVAL val = colp->GetValue(); jint n, i = (jint)colp->GetRank(); jshort s; @@ -1557,58 +1531,38 @@ bool JDBConn::SetParam(JDBCCOL *colp) switch (val->GetType()) { case TYPE_STRING: - setid = env->GetMethodID(jdi, "SetStringParm", "(ILjava/lang/String;)V"); - - if (setid == nullptr) { - strcpy(g->Message, "Cannot fing method SetStringParm"); + if (gmID(g, setid, "SetStringParm", "(ILjava/lang/String;)V")) return true; - } // endif setid jst = env->NewStringUTF(val->GetCharValue()); env->CallVoidMethod(job, setid, i, jst); break; case TYPE_INT: - setid = env->GetMethodID(jdi, "SetIntParm", "(II)V"); - - if (setid == nullptr) { - strcpy(g->Message, "Cannot fing method SetIntParm"); + if (gmID(g, setid, "SetIntParm", "(II)V")) return true; - } // endif setid n = (jint)val->GetIntValue(); env->CallVoidMethod(job, setid, i, n); break; case TYPE_TINY: case TYPE_SHORT: - setid = env->GetMethodID(jdi, "SetShortParm", "(IS)V"); - - if (setid == nullptr) { - strcpy(g->Message, "Cannot fing method SetShortParm"); + if (gmID(g, setid, "SetShortParm", "(IS)V")) return true; - } // endif setid s = (jshort)val->GetShortValue(); env->CallVoidMethod(job, setid, i, s); break; case TYPE_BIGINT: - setid = env->GetMethodID(jdi, "SetBigintParm", "(IJ)V"); - - if (setid == nullptr) { - strcpy(g->Message, "Cannot fing method SetBigintParm"); + if (gmID(g, setid, "SetBigintParm", "(IJ)V")) return true; - } // endif setid lg = (jlong)val->GetBigintValue(); env->CallVoidMethod(job, setid, i, lg); break; case TYPE_DOUBLE: case TYPE_DECIM: - setid = env->GetMethodID(jdi, "SetDoubleParm", "(ID)V"); - - if (setid == nullptr) { - strcpy(g->Message, "Cannot find method SetDoubleParm"); + if (gmID(g, setid, "SetDoubleParm", "(ID)V")) return true; - } // endif setid d = (jdouble)val->GetFloatValue(); env->CallVoidMethod(job, setid, i, d); @@ -1627,11 +1581,8 @@ bool JDBConn::SetParam(JDBCCOL *colp) if ((datobj = env->NewObject(dat, dtc, lg)) == nullptr) { strcpy(g->Message, "Cannot make Timestamp object"); return true; - } else if ((setid = env->GetMethodID(jdi, "SetTimestampParm", - "(ILjava/sql/Timestamp;)V")) == nullptr) { - strcpy(g->Message, "Cannot find method SetTimestampParm"); + } else if (gmID(g, setid, "SetTimestampParm", "(ILjava/sql/Timestamp;)V")) return true; - } // endif setid env->CallVoidMethod(job, setid, i, datobj); break; @@ -1640,8 +1591,8 @@ bool JDBConn::SetParam(JDBCCOL *colp) return true; } // endswitch Type - if ((msg = Check())) { - sprintf(g->Message, "SetParam: col=%s msg=%s", colp->GetName(), msg); + if (Check()) { + sprintf(g->Message, "SetParam: col=%s msg=%s", colp->GetName(), Msg); rc = true; } // endif msg @@ -1707,14 +1658,10 @@ bool JDBConn::SetParam(JDBCCOL *colp) int i, n, size; PCOLRES crp; jstring js; - jmethodID gdid = env->GetMethodID(jdi, "GetDrivers", "([Ljava/lang/String;I)I"); - - if (env->ExceptionCheck()) { - strcpy(m_G->Message, "ERROR: method GetDrivers() not found!"); - env->ExceptionDescribe(); - env->ExceptionClear(); + jmethodID gdid = nullptr; + + if (gmID(m_G, gdid, "GetDrivers", "([Ljava/lang/String;I)I")) return true; - } // endif Check // Build the java string array jobjectArray s = env->NewObjectArray(4 * qrp->Maxres, @@ -1766,7 +1713,7 @@ bool JDBConn::SetParam(JDBCCOL *colp) ushort i; jint *n = nullptr; jstring label; - jmethodID colid; + jmethodID colid = nullptr; int rc = ExecSQLcommand(src); if (rc == RC_NF) { @@ -1779,20 +1726,8 @@ bool JDBConn::SetParam(JDBCCOL *colp) return NULL; } // endif's - colid = env->GetMethodID(jdi, "ColumnDesc", "(I[I)Ljava/lang/String;"); - - if (colid == nullptr) { - strcpy(m_G->Message, "ERROR: method ColumnDesc() not found!"); + if (gmID(g, colid, "ColumnDesc", "(I[I)Ljava/lang/String;")) return NULL; - } // endif colid - - // Build the java string array - jintArray val = env->NewIntArray(4); - - if (val == nullptr) { - strcpy(m_G->Message, "Cannot allocate jint array"); - return NULL; - } // endif colid // Get max column name length len = GetMaxValue(5); @@ -1813,11 +1748,28 @@ bool JDBConn::SetParam(JDBCCOL *colp) case 5: crp->Name = "Nullable"; break; } // endswitch i + // Build the java string array + jintArray val = env->NewIntArray(4); + + if (val == nullptr) { + strcpy(m_G->Message, "Cannot allocate jint array"); + return NULL; + } // endif colid + /************************************************************************/ /* Now get the results into blocks. */ /************************************************************************/ for (i = 0; i < m_Ncol; i++) { - label = (jstring)env->CallObjectMethod(job, colid, i + 1, val); + if (!(label = (jstring)env->CallObjectMethod(job, colid, i + 1, val))) { + if (Check()) + sprintf(g->Message, "ColumnDesc: %s", Msg); + else + strcpy(g->Message, "No result metadata"); + + env->ReleaseIntArrayElements(val, n, 0); + return NULL; + } // endif label + name = env->GetStringUTFChars(label, (jboolean)false); crp = qrp->Colresp; // Column_Name crp->Kdata->SetValue((char*)name, i); @@ -1835,7 +1787,6 @@ bool JDBConn::SetParam(JDBCCOL *colp) /* Cleanup */ env->ReleaseIntArrayElements(val, n, 0); - Close(); /************************************************************************/ /* Return the result pointer for use by GetData routines. */ @@ -1962,7 +1913,7 @@ bool JDBConn::SetParam(JDBCCOL *colp) PVAL *pval = NULL; char* *pbuf = NULL; jobjectArray parms; - jmethodID catid; + jmethodID catid = nullptr; if (qrp->Maxres <= 0) return 0; // 0-sized result" @@ -2008,16 +1959,18 @@ bool JDBConn::SetParam(JDBCCOL *colp) return -1; } // endswitch infotype - catid = env->GetMethodID(jdi, fnc, "([Ljava/lang/String;)I"); - - if (catid == nullptr) { - sprintf(g->Message, "ERROR: method %s not found !", fnc); + if (gmID(g, catid, fnc, "([Ljava/lang/String;)I")) return -1; - } // endif maxid // call method ncol = env->CallIntMethod(job, catid, parms); + if (Check(ncol)) { + sprintf(g->Message, "%s: %s", fnc, Msg); + env->DeleteLocalRef(parms); + return -1; + } // endif Check + // Not used anymore env->DeleteLocalRef(parms); @@ -2061,13 +2014,15 @@ bool JDBConn::SetParam(JDBCCOL *colp) // Now fetch the result for (i = 0; i < qrp->Maxres; i++) { - if ((rc = Fetch(0)) == 0) { + if (Check(rc = Fetch(0))) { + sprintf(g->Message, "Fetch: %s", Msg); + return -1; + } if (rc == 0) { if (trace) htrc("End of fetches i=%d\n", i); break; - } else if (rc < 0) - return -1; + } // endif rc for (n = 0, crp = qrp->Colresp; crp; n++, crp = crp->Next) { SetColumnValue(n + 1, nullptr, pval[n]); diff --git a/storage/connect/jdbconn.h b/storage/connect/jdbconn.h index 4014a52cdcc2b..d8c36c6a63717 100644 --- a/storage/connect/jdbconn.h +++ b/storage/connect/jdbconn.h @@ -120,7 +120,8 @@ class JDBConn : public BLOCK { // JDBC operations protected: - char *Check(void); + bool gmID(PGLOBAL g, jmethodID& mid, const char *name, const char *sig); + bool Check(jint rc = 0); //void ThrowDJX(int rc, PSZ msg/*, HSTMT hstmt = SQL_NULL_HSTMT*/); //void ThrowDJX(PSZ msg); //void Free(void); @@ -150,9 +151,11 @@ class JDBConn : public BLOCK { jmethodID prepid; // The CreatePrepStmt method ID jmethodID xpid; // The ExecutePrep method ID jmethodID pcid; // The ClosePrepStmt method ID + jmethodID errid; // The GetErrmsg method ID //DWORD m_LoginTimeout; //DWORD m_QueryTimeout; //DWORD m_UpdateOptions; + char *Msg; char m_IDQuoteChar[2]; PSZ m_Driver; PSZ m_Url; diff --git a/storage/connect/tabjdbc.cpp b/storage/connect/tabjdbc.cpp index 37850ce6358cc..fa5f093bae65c 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 #include @@ -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" @@ -101,11 +102,107 @@ JDBCDEF::JDBCDEF(void) 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, "%d", server->port); + strcat(strcat(Url, ":"), buf); + } // endif port + + if (server->db) + strcat(strcat(Url, "/"), server->db); + + PlugSubAlloc(g, NULL, strlen(Url) + 1); + } else // host is a URL + Url = PlugDup(g, server->host); + + if (server->username) + Username = PlugDup(g, server->username); + + if (server->password) + Password = PlugDup(g, server->password); + + return RC_NF; + } // endif + + // Url was a JDBC URL, nothing to do + return RC_OK; +} // end of ParseURL + /***********************************************************************/ /* DefineAM: define specific AM block values from JDBC file. */ /***********************************************************************/ bool JDBCDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) { + int rc = RC_OK; + Driver = GetStringCatInfo(g, "Driver", NULL); Desc = Url = GetStringCatInfo(g, "Connect", NULL); @@ -120,28 +217,33 @@ bool JDBCDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) } // endif Connect - Tabname = GetStringCatInfo(g, "Name", - (Catfunc & (FNC_TABLE | FNC_COL)) ? NULL : Name); - Tabname = GetStringCatInfo(g, "Tabname", Tabname); - Tabschema = GetStringCatInfo(g, "Dbname", NULL); - Tabschema = GetStringCatInfo(g, "Schema", Tabschema); - Tabcat = GetStringCatInfo(g, "Qualifier", NULL); - Tabcat = GetStringCatInfo(g, "Catalog", Tabcat); - Tabtype = GetStringCatInfo(g, "Tabtype", NULL); - Username = GetStringCatInfo(g, "User", NULL); - Password = GetStringCatInfo(g, "Password", NULL); + if (Url) + rc = ParseURL(g, Url); + + if (rc == RC_FX) // Error + return true; + else if (rc == RC_OK) { // Url was not a server name + Tabname = GetStringCatInfo(g, "Name", + (Catfunc & (FNC_TABLE | FNC_COL)) ? NULL : Name); + Tabname = GetStringCatInfo(g, "Tabname", Tabname); + Username = GetStringCatInfo(g, "User", NULL); + Password = GetStringCatInfo(g, "Password", NULL); + } // endif rc if ((Srcdef = GetStringCatInfo(g, "Srcdef", NULL))) Read_Only = true; + Tabcat = GetStringCatInfo(g, "Qualifier", NULL); + Tabcat = GetStringCatInfo(g, "Catalog", Tabcat); + Tabschema = GetStringCatInfo(g, "Dbname", NULL); + Tabschema = GetStringCatInfo(g, "Schema", Tabschema); + Tabtype = GetStringCatInfo(g, "Tabtype", NULL); Qrystr = GetStringCatInfo(g, "Query_String", "?"); Sep = GetStringCatInfo(g, "Separator", NULL); Xsrc = GetBoolCatInfo("Execsrc", FALSE); Maxerr = GetIntCatInfo("Maxerr", 0); Maxres = GetIntCatInfo("Maxres", 0); Quoted = GetIntCatInfo("Quoted", 0); -//Options = JDBConn::noJDBCDialog; -//Options = JDBConn::noJDBCDialog | JDBConn::useCursorLib; //Cto= GetIntCatInfo("ConnectTimeout", DEFAULT_LOGIN_TIMEOUT); //Qto= GetIntCatInfo("QueryTimeout", DEFAULT_QUERY_TIMEOUT); Scrollable = GetBoolCatInfo("Scrollable", false); @@ -274,6 +376,7 @@ TDBJDBC::TDBJDBC(PJDBCDEF tdp) : TDBASE(tdp) Ncol = 0; Nparm = 0; Placed = false; + Prepared = false; Werr = false; Rerr = false; Ops.Fsize = Ops.CheckSize(Rows); diff --git a/storage/connect/tabjdbc.h b/storage/connect/tabjdbc.h index 1624b9036104e..537276a6a7f1b 100644 --- a/storage/connect/tabjdbc.h +++ b/storage/connect/tabjdbc.h @@ -7,6 +7,7 @@ /***********************************************************************/ #include "colblk.h" #include "resource.h" +#include "jdbccat.h" typedef class JDBCDEF *PJDBCDEF; typedef class TDBJDBC *PTDBJDBC; @@ -44,6 +45,8 @@ class DllExport JDBCDEF : public TABDEF { /* Logical table description */ 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 From a982f59b9b7ed988d908fa75425c826d7e85e406 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Sat, 21 May 2016 11:56:59 +0200 Subject: [PATCH 10/18] - JDBC using separate jmethodID for data types Some DEBUG tests modified: storage/connect/jdbconn.cpp modified: storage/connect/jdbconn.h --- storage/connect/jdbconn.cpp | 92 ++++++++++++++++++++++++------------- storage/connect/jdbconn.h | 23 +++++++++- 2 files changed, 80 insertions(+), 35 deletions(-) diff --git a/storage/connect/jdbconn.cpp b/storage/connect/jdbconn.cpp index 1d2242060e133..286d1141fe804 100644 --- a/storage/connect/jdbconn.cpp +++ b/storage/connect/jdbconn.cpp @@ -62,6 +62,9 @@ extern char *ClassPath; // The connect_class_path global variable value 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) */ @@ -646,6 +649,7 @@ JDBConn::JDBConn(PGLOBAL g, TDBJDBC *tdbp) job = nullptr; // The JdbcInterface 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; @@ -811,6 +815,9 @@ void JDBConn::ResetJVM(void) LibJvm = NULL; CreateJavaVM = NULL; GetCreatedJavaVMs = NULL; +#if defined(_DEBUG) + GetDefaultJavaVMInitArgs = NULL; +#endif // _DEBUG } // endif LibJvm } // end of ResetJVM @@ -851,6 +858,14 @@ bool JDBConn::GetJVM(PGLOBAL g) 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; @@ -874,7 +889,15 @@ bool JDBConn::GetJVM(PGLOBAL g) sprintf(g->Message, MSG(GET_FUNC_ERR), "JNI_GetCreatedJavaVMs", SVP(error)); dlclose(LibJvm); LibJvm = NULL; - } // endif LibJvm +#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__ } // endif LibJvm @@ -919,13 +942,17 @@ int JDBConn::Open(PJPARM sop) #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[1]; // JVM invocation options + JavaVMOption* options = new JavaVMOption[N]; // JVM invocation options // where to find java .class if (ClassPath && *ClassPath) { @@ -945,9 +972,20 @@ int JDBConn::Open(PJPARM sop) } // endif trace options[0].optionString = jpop->GetStr(); - //options[1].optionString = "-verbose:jni"; +#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 - vm_args.nOptions = 1; // number of options +#endif // _DEBUG + vm_args.nOptions = N; // number of options vm_args.options = options; vm_args.ignoreUnrecognized = false; // invalid options make the JVM init fail @@ -985,8 +1023,10 @@ int JDBConn::Open(PJPARM sop) } // 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"); @@ -1251,7 +1291,6 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val) jlong dtv; jstring cn, jn = nullptr; jobject dob; - jmethodID fldid = nullptr; if (rank == 0) if (!name || (jn = env->NewStringUTF(name)) == nullptr) { @@ -1271,11 +1310,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); @@ -1292,10 +1328,8 @@ 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)); + if (!gmID(g, intfldid, "IntField", "(ILjava/lang/String;)I")) + val->SetValue((int)env->CallIntMethod(job, intfldid, rank, jn)); else val->Reset(); @@ -1303,20 +1337,16 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val) 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(); @@ -1324,11 +1354,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"); @@ -1354,10 +1382,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(); diff --git a/storage/connect/jdbconn.h b/storage/connect/jdbconn.h index d8c36c6a63717..a7744ba6ba1ac 100644 --- a/storage/connect/jdbconn.h +++ b/storage/connect/jdbconn.h @@ -53,6 +53,9 @@ typedef struct tagJCATPARM { 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; @@ -109,8 +112,15 @@ class JDBConn : public BLOCK { public: // Set static variables - static void SetJVM(void) - { LibJvm = NULL; CreateJavaVM = NULL; GetCreatedJavaVMs = NULL; } + 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); @@ -135,6 +145,9 @@ class JDBConn : public BLOCK { #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) @@ -152,6 +165,12 @@ class JDBConn : public BLOCK { 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; From 77dd5ece06904aa10c3fe05b9493cf3231edcd85 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Sat, 21 May 2016 14:28:21 +0200 Subject: [PATCH 11/18] - Fix wrong return from ExecuteQuery modified: storage/connect/jdbconn.cpp - Suppress GCC warning modified: storage/connect/tabjdbc.cpp --- storage/connect/jdbconn.cpp | 2 +- storage/connect/tabjdbc.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/storage/connect/jdbconn.cpp b/storage/connect/jdbconn.cpp index 286d1141fe804..23bd64bfb88d7 100644 --- a/storage/connect/jdbconn.cpp +++ b/storage/connect/jdbconn.cpp @@ -1458,7 +1458,7 @@ int JDBConn::ExecuteQuery(char *sql) env->DeleteLocalRef(qry); } // endif xqid - return RC_OK; + return rc; } // end of ExecuteQuery /***********************************************************************/ diff --git a/storage/connect/tabjdbc.cpp b/storage/connect/tabjdbc.cpp index fa5f093bae65c..f507e3df3ea3a 100644 --- a/storage/connect/tabjdbc.cpp +++ b/storage/connect/tabjdbc.cpp @@ -172,7 +172,7 @@ int JDBCDEF::ParseURL(PGLOBAL g, char *url, bool b) if (server->port) { char buf[16]; - sprintf(buf, "%d", server->port); + sprintf(buf, "%ld", server->port); strcat(strcat(Url, ":"), buf); } // endif port From 0dae2932f42b10d86671d21de41cf0b444aedf5e Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Mon, 23 May 2016 15:08:51 +0200 Subject: [PATCH 12/18] - New version of the java JdbcInterface modified: storage/connect/JdbcInterface.class modified: storage/connect/JdbcInterface.java - Ignore *.tlog and .res files modified: .gitignore --- .gitignore | 2 + storage/connect/JdbcInterface.class | Bin 15117 -> 15215 bytes storage/connect/JdbcInterface.java | 229 ++++++++++++++++++---------- 3 files changed, 153 insertions(+), 78 deletions(-) diff --git a/.gitignore b/.gitignore index f2064537da467..279d3f59dc542 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 816f575212b2313bbde48e6b8831a0267f8ffef7..8c5ba6439f3fa073f8fa5f892e9ae84a581bc113 100644 GIT binary patch literal 15215 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 0) ? rs.getString(n) : rs.getString(name); } catch (SQLException se) { - System.out.println(se); + SetErrmsg(se); } //end try/catch return null; @@ -525,7 +544,7 @@ public int IntField(int n, String name) { } else try { return (n > 0) ? rs.getInt(n) : rs.getInt(name); } catch (SQLException se) { - System.out.println(se); + SetErrmsg(se); } //end try/catch return 0; @@ -538,7 +557,7 @@ public long BigintField(int n, String name) { BigDecimal bigDecimal = (n > 0) ? rs.getBigDecimal(n) : rs.getBigDecimal(name); return bigDecimal != null ? bigDecimal.longValue() : 0; } catch (SQLException se) { - System.out.println(se); + SetErrmsg(se); } //end try/catch return 0; @@ -550,7 +569,7 @@ public double DoubleField(int n, String name) { } else try { return (n > 0) ? rs.getDouble(n) : rs.getDouble(name); } catch (SQLException se) { - System.out.println(se); + SetErrmsg(se); } //end try/catch return 0.; @@ -562,7 +581,7 @@ public float FloatField(int n, String name) { } else try { return (n > 0) ? rs.getFloat(n) : rs.getFloat(name); } catch (SQLException se) { - System.out.println(se); + SetErrmsg(se); } //end try/catch return 0; @@ -574,7 +593,7 @@ public boolean BooleanField(int n, String name) { } else try { return (n > 0) ? rs.getBoolean(n) : rs.getBoolean(name); } catch (SQLException se) { - System.out.println(se); + SetErrmsg(se); } //end try/catch return false; @@ -586,7 +605,7 @@ public Date DateField(int n, String name) { } else try { return (n > 0) ? rs.getDate(n) : rs.getDate(name); } catch (SQLException se) { - System.out.println(se); + SetErrmsg(se); } //end try/catch return null; @@ -598,7 +617,7 @@ public Time TimeField(int n, String name) { } else try { return (n > 0) ? rs.getTime(n) : rs.getTime(name); } catch (SQLException se) { - System.out.println(se); + SetErrmsg(se); } //end try/catch return null; @@ -610,12 +629,24 @@ public Timestamp TimestampField(int n, String name) { } else try { return (n > 0) ? rs.getTimestamp(n) : rs.getTimestamp(name); } catch (SQLException se) { - System.out.println(se); + SetErrmsg(se); } //end try/catch return null; } // end of TimestampField + public String ObjectField(int n, String name) { + if (rs == null) { + System.out.println("No result set"); + } else try { + return (n > 0) ? rs.getObject(n).toString() : rs.getObject(name).toString(); + } catch (SQLException se) { + SetErrmsg(se); + } //end try/catch + + return null; + } // end of ObjectField + public int GetDrivers(String[] s, int mxs) { int n = 0; List drivers = Collections.list(DriverManager.getDrivers()); @@ -635,5 +666,47 @@ public int GetDrivers(String[] s, int mxs) { return size; } // end of GetDrivers + + /** + * Adds the specified path to the java library path + * from Fahd Shariff blog + * + * @param pathToAdd the path to add + static public int addLibraryPath(String pathToAdd) { + System.out.println("jpath = " + pathToAdd); + + try { + Field usrPathsField = ClassLoader.class.getDeclaredField("usr_paths"); + usrPathsField.setAccessible(true); + + //get array of paths + String[] paths = (String[])usrPathsField.get(null); + + //check if the path to add is already present + for (String path : paths) { + System.out.println("path = " + path); + + if (path.equals(pathToAdd)) + return -5; + + } // endfor path + + //add the new path + String[] newPaths = Arrays.copyOf(paths, paths.length + 1); + newPaths[paths.length] = pathToAdd; + usrPathsField.set(null, newPaths); + System.setProperty("java.library.path", + System.getProperty("java.library.path") + File.pathSeparator + pathToAdd); + Field fieldSysPath = ClassLoader.class.getDeclaredField("sys_paths"); + fieldSysPath.setAccessible(true); + fieldSysPath.set(null, null); + } catch (Exception e) { + SetErrmsg(e); + return -1; + } // end try/catch + + return 0; + } // end of addLibraryPath + */ } // end of class JdbcInterface From 809422838d7c90e658b889712f45f4b953a7bdd6 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Tue, 24 May 2016 11:29:12 +0200 Subject: [PATCH 13/18] - Alternative versions of the java JdbcInterface Some of them (ap/ds) enable connection to a DataSource added 'storage/connect/java/ap/JdbcInterface.class' added 'storage/connect/java/ap/JdbcInterface.java' added 'storage/connect/java/ds/JdbcInterface.class' added 'storage/connect/java/ds/JdbcInterface.java' added 'storage/connect/java/std/JdbcInterface.class' added 'storage/connect/java/std/JdbcInterface.java' --- storage/connect/java/ap/JdbcInterface.class | Bin 0 -> 15339 bytes storage/connect/java/ap/JdbcInterface.java | 709 ++++++++++++++++++ storage/connect/java/ds/JdbcInterface.class | Bin 0 -> 16169 bytes storage/connect/java/ds/JdbcInterface.java | 743 +++++++++++++++++++ storage/connect/java/std/JdbcInterface.class | Bin 0 -> 15215 bytes storage/connect/java/std/JdbcInterface.java | 712 ++++++++++++++++++ 6 files changed, 2164 insertions(+) create mode 100644 storage/connect/java/ap/JdbcInterface.class create mode 100644 storage/connect/java/ap/JdbcInterface.java create mode 100644 storage/connect/java/ds/JdbcInterface.class create mode 100644 storage/connect/java/ds/JdbcInterface.java create mode 100644 storage/connect/java/std/JdbcInterface.class create mode 100644 storage/connect/java/std/JdbcInterface.java diff --git a/storage/connect/java/ap/JdbcInterface.class b/storage/connect/java/ap/JdbcInterface.class new file mode 100644 index 0000000000000000000000000000000000000000..0b08b2e9217f2b281337ac952b32f20f1392fba0 GIT binary patch literal 15339 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 ZWG`%I|1OVoK}(-uchAVCNVUfJ{{cqi>xBRS literal 0 HcmV?d00001 diff --git a/storage/connect/java/ap/JdbcInterface.java b/storage/connect/java/ap/JdbcInterface.java new file mode 100644 index 0000000000000..10128cac682d2 --- /dev/null +++ b/storage/connect/java/ap/JdbcInterface.java @@ -0,0 +1,709 @@ +import java.math.*; +import java.sql.*; +import java.util.Collections; +import java.util.Hashtable; +import java.util.List; + +import org.apache.commons.dbcp2.BasicDataSource; + +public class JdbcInterface { + boolean DEBUG = false; + String Errmsg = "No error"; + Connection conn = null; + DatabaseMetaData dbmd = null; + Statement stmt = null; + PreparedStatement pstmt = null; + ResultSet rs = null; + ResultSetMetaData rsmd = null; + static Hashtable pool = new Hashtable(); + + // === Constructors/finalize ========================================= + public JdbcInterface() { + this(true); + } // end of default constructor + + public JdbcInterface(boolean b) { + DEBUG = b; + } // end of constructor + + private void SetErrmsg(Exception e) { + if (DEBUG) + System.out.println(e.getMessage()); + + Errmsg = e.toString(); + } // end of SetErrmsg + + private void SetErrmsg(String s) { + if (DEBUG) + System.out.println(s); + + Errmsg = s; + } // end of SetErrmsg + + public String GetErrmsg() { + String err = Errmsg; + + Errmsg = "No error"; + return err; + } // end of GetErrmsg + + public int JdbcConnect(String[] parms, int fsize, boolean scrollable) { + int rc = 0; + String url = parms[1]; + BasicDataSource ds = null; + + if (url == null) { + SetErrmsg("URL cannot be null"); + return -1; + } // endif url + + try { + if ((ds = pool.get(url)) == null) { + ds = new BasicDataSource(); + ds.setDriverClassName(parms[0]); + ds.setUrl(url); + ds.setUsername(parms[2]); + ds.setPassword(parms[3]); + pool.put(url, ds); + } // endif ds + + // Get a connection from the data source + conn = ds.getConnection(); + + // Get the data base meta data object + dbmd = conn.getMetaData(); + + // Get a statement from the connection + if (scrollable) + stmt = conn.createStatement(java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE, java.sql.ResultSet.CONCUR_READ_ONLY); + else + stmt = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY, java.sql.ResultSet.CONCUR_READ_ONLY); + + if (DEBUG) + System.out.println("Statement type = " + stmt.getResultSetType() + + " concurrency = " + stmt.getResultSetConcurrency()); + + if (DEBUG) // Get the fetch size of a statement + System.out.println("Default fetch size = " + stmt.getFetchSize()); + + if (fsize != 0) { + // Set the fetch size + stmt.setFetchSize(fsize); + + if (DEBUG) + System.out.println("New fetch size = " + stmt.getFetchSize()); + + } // endif fsize + + } catch (SQLException se) { + SetErrmsg(se); + rc = -2; + } catch( Exception e ) { + SetErrmsg(e); + rc = -3; + } // end try/catch + + return rc; + } // end of JdbcConnect + + public int CreatePrepStmt(String sql) { + int rc = 0; + + try { + pstmt = conn.prepareStatement(sql); + } catch (SQLException se) { + SetErrmsg(se); + rc = -1; + } catch (Exception e) { + SetErrmsg(e); + rc = -2; + } // end try/catch + + return rc; + } // end of CreatePrepStmt + + public void SetStringParm(int i, String s) { + try { + pstmt.setString(i, s); + } catch (Exception e) { + SetErrmsg(e); + } // end try/catch + + } // end of SetStringParm + + public void SetIntParm(int i, int n) { + try { + pstmt.setInt(i, n); + } catch (Exception e) { + SetErrmsg(e); + } // end try/catch + + } // end of SetIntParm + + public void SetShortParm(int i, short n) { + try { + pstmt.setShort(i, n); + } catch (Exception e) { + SetErrmsg(e); + } // end try/catch + + } // end of SetShortParm + + public void SetBigintParm(int i, long n) { + try { + pstmt.setLong(i, n); + } catch (Exception e) { + SetErrmsg(e); + } // end try/catch + + } // end of SetBigintParm + + public void SetFloatParm(int i, float f) { + try { + pstmt.setFloat(i, f); + } catch (Exception e) { + SetErrmsg(e); + } // end try/catch + + } // end of SetFloatParm + + public void SetDoubleParm(int i, double d) { + try { + pstmt.setDouble(i, d); + } catch (Exception e) { + SetErrmsg(e); + } // end try/catch + + } // end of SetDoubleParm + + public void SetTimestampParm(int i, Timestamp t) { + try { + pstmt.setTimestamp(i, t); + } catch (Exception e) { + SetErrmsg(e); + } // end try/catch + + } // end of SetTimestampParm + + public int ExecutePrep() { + int n = -3; + + if (pstmt != null) try { + n = pstmt.executeUpdate(); + } catch (SQLException se) { + SetErrmsg(se); + n = -1; + } catch (Exception e) { + SetErrmsg(e); + n = -2; + } //end try/catch + + return n; + } // end of ExecutePrep + + public boolean ClosePrepStmt() { + boolean b = false; + + if (pstmt != null) try { + pstmt.close(); + pstmt = null; + } catch (SQLException se) { + SetErrmsg(se); + b = true; + } catch (Exception e) { + SetErrmsg(e); + b = true; + } // end try/catch + + return b; + } // end of ClosePrepStmt + + public int JdbcDisconnect() { + int rc = 0; + + // Cancel pending statement + if (stmt != null) + try { + System.out.println("Cancelling statement"); + stmt.cancel(); + } catch(SQLException se) { + SetErrmsg(se); + rc += 1; + } // nothing more we can do + + // Close the statement and the connection + if (rs != null) + try { + if (DEBUG) + System.out.println("Closing result set"); + + rs.close(); + } catch(SQLException se) { + SetErrmsg(se); + rc = 2; + } // nothing more we can do + + if (stmt != null) + try { + if (DEBUG) + System.out.println("Closing statement"); + + stmt.close(); + } catch(SQLException se) { + SetErrmsg(se); + rc += 4; + } // nothing more we can do + + ClosePrepStmt(); + + if (conn != null) + try { + if (DEBUG) + System.out.println("Closing connection"); + + conn.close(); + } catch (SQLException se) { + SetErrmsg(se); + rc += 8; + } //end try/catch + + if (DEBUG) + System.out.println("All closed"); + + return rc; + } // end of JdbcDisconnect + + public int GetMaxValue(int n) { + int m = 0; + + try { + switch (n) { + case 1: // Max columns in table + m = dbmd.getMaxColumnsInTable(); + break; + case 2: // Max catalog name length + m = dbmd.getMaxCatalogNameLength(); + break; + case 3: // Max schema name length + m = dbmd.getMaxSchemaNameLength(); + break; + case 4: // Max table name length + m = dbmd.getMaxTableNameLength(); + break; + case 5: // Max column name length + m = dbmd.getMaxColumnNameLength(); + break; + } // endswitch n + + } catch(Exception e) { + SetErrmsg(e); + m = -1; + } // end try/catch + + return m; + } // end of GetMaxValue + + public int GetColumns(String[] parms) { + int ncol = 0; + + try { + if (rs != null) rs.close(); + rs = dbmd.getColumns(parms[0], parms[1], parms[2], parms[3]); + + if (rs != null) { + rsmd = rs.getMetaData(); + ncol = rsmd.getColumnCount(); + } // endif rs + + } catch(SQLException se) { + SetErrmsg(se); + } // end try/catch + + return ncol; + } // end of GetColumns + + public int GetTables(String[] parms) { + int ncol = 0; + String[] typ = null; + + if (parms[3] != null) { + typ = new String[1]; + typ[0] = parms[3]; + } // endif parms + + try { + if (rs != null) rs.close(); + rs = dbmd.getTables(parms[0], parms[1], parms[2], typ); + + if (rs != null) { + rsmd = rs.getMetaData(); + ncol = rsmd.getColumnCount(); + } // endif rs + + } catch(SQLException se) { + SetErrmsg(se); + } // end try/catch + + return ncol; + } // end of GetColumns + + public int Execute(String query) { + int n = 0; + + if (DEBUG) + System.out.println("Executing '" + query + "'"); + + try { + boolean b = stmt.execute(query); + + if (b == false) { + n = stmt.getUpdateCount(); + if (rs != null) rs.close(); + } // endif b + + if (DEBUG) + System.out.println("Query '" + query + "' executed: n = " + n); + + } catch (SQLException se) { + SetErrmsg(se); + n = -1; + } catch (Exception e) { + SetErrmsg(e); + n = -2; + } //end try/catch + + return n; + } // end of Execute + + public int GetResult() { + int ncol = 0; + + try { + rs = stmt.getResultSet(); + + if (rs != null) { + rsmd = rs.getMetaData(); + ncol = rsmd.getColumnCount(); + + if (DEBUG) + System.out.println("Result set has " + rsmd.getColumnCount() + " column(s)"); + + } // endif rs + + } catch (SQLException se) { + SetErrmsg(se); + ncol = -1; + } catch (Exception e) { + SetErrmsg(e); + ncol = -2; + } //end try/catch + + return ncol; + } // end of GetResult + + public int ExecuteQuery(String query) { + int ncol = 0; + + if (DEBUG) + System.out.println("Executing query '" + query + "'"); + + try { + rs = stmt.executeQuery(query); + rsmd = rs.getMetaData(); + ncol = rsmd.getColumnCount(); + + if (DEBUG) { + System.out.println("Query '" + query + "' executed successfully"); + System.out.println("Result set has " + rsmd.getColumnCount() + " column(s)"); + } // endif DEBUG + + } catch (SQLException se) { + SetErrmsg(se); + ncol = -1; + } catch (Exception e) { + SetErrmsg(e); + ncol = -2; + } //end try/catch + + return ncol; + } // end of ExecuteQuery + + public int ExecuteUpdate(String query) { + int n = 0; + + if (DEBUG) + System.out.println("Executing update query '" + query + "'"); + + try { + n = stmt.executeUpdate(query); + + if (DEBUG) + System.out.println("Update Query '" + query + "' executed: n = " + n); + + } catch (SQLException se) { + SetErrmsg(se); + n = -1; + } catch (Exception e) { + SetErrmsg(e); + n = -2; + } //end try/catch + + return n; + } // end of ExecuteUpdate + + public int ReadNext() { + if (rs != null) { + try { + return rs.next() ? 1 : 0; + } catch (SQLException se) { + SetErrmsg(se); + return -1; + } //end try/catch + + } else + return 0; + + } // end of ReadNext + + public boolean Fetch(int row) { + if (rs != null) { + try { + return rs.absolute(row); + } catch (SQLException se) { + SetErrmsg(se); + return false; + } //end try/catch + + } else + return false; + + } // end of Fetch + + public String ColumnName(int n) { + if (rsmd == null) { + System.out.println("No result metadata"); + } else try { + return rsmd.getColumnLabel(n); + } catch (SQLException se) { + SetErrmsg(se); + } //end try/catch + + return null; + } // end of ColumnName + + public int ColumnType(int n, String name) { + if (rsmd == null) { + System.out.println("No result metadata"); + } else try { + if (n == 0) + n = rs.findColumn(name); + + return rsmd.getColumnType(n); + } catch (SQLException se) { + SetErrmsg(se); + } //end try/catch + + return 666; // Not a type + } // end of ColumnType + + public String ColumnDesc(int n, int[] val) { + if (rsmd == null) { + System.out.println("No result metadata"); + return null; + } else try { + val[0] = rsmd.getColumnType(n); + val[1] = rsmd.getPrecision(n); + val[2] = rsmd.getScale(n); + val[3] = rsmd.isNullable(n); + return rsmd.getColumnLabel(n); + } catch (SQLException se) { + SetErrmsg(se); + } //end try/catch + + return null; + } // end of ColumnDesc + + public String StringField(int n, String name) { + if (rs == null) { + System.out.println("No result set"); + } else try { + return (n > 0) ? rs.getString(n) : rs.getString(name); + } catch (SQLException se) { + SetErrmsg(se); + } //end try/catch + + return null; + } // end of StringField + + public int IntField(int n, String name) { + if (rs == null) { + System.out.println("No result set"); + } else try { + return (n > 0) ? rs.getInt(n) : rs.getInt(name); + } catch (SQLException se) { + SetErrmsg(se); + } //end try/catch + + return 0; + } // end of IntField + + public long BigintField(int n, String name) { + if (rs == null) { + System.out.println("No result set"); + } else try { + BigDecimal bigDecimal = (n > 0) ? rs.getBigDecimal(n) : rs.getBigDecimal(name); + return bigDecimal != null ? bigDecimal.longValue() : 0; + } catch (SQLException se) { + SetErrmsg(se); + } //end try/catch + + return 0; + } // end of BiginttField + + public double DoubleField(int n, String name) { + if (rs == null) { + System.out.println("No result set"); + } else try { + return (n > 0) ? rs.getDouble(n) : rs.getDouble(name); + } catch (SQLException se) { + SetErrmsg(se); + } //end try/catch + + return 0.; + } // end of DoubleField + + public float FloatField(int n, String name) { + if (rs == null) { + System.out.println("No result set"); + } else try { + return (n > 0) ? rs.getFloat(n) : rs.getFloat(name); + } catch (SQLException se) { + SetErrmsg(se); + } //end try/catch + + return 0; + } // end of FloatField + + public boolean BooleanField(int n, String name) { + if (rs == null) { + System.out.println("No result set"); + } else try { + return (n > 0) ? rs.getBoolean(n) : rs.getBoolean(name); + } catch (SQLException se) { + SetErrmsg(se); + } //end try/catch + + return false; + } // end of BooleanField + + public Date DateField(int n, String name) { + if (rs == null) { + System.out.println("No result set"); + } else try { + return (n > 0) ? rs.getDate(n) : rs.getDate(name); + } catch (SQLException se) { + SetErrmsg(se); + } //end try/catch + + return null; + } // end of DateField + + public Time TimeField(int n, String name) { + if (rs == null) { + System.out.println("No result set"); + } else try { + return (n > 0) ? rs.getTime(n) : rs.getTime(name); + } catch (SQLException se) { + SetErrmsg(se); + } //end try/catch + + return null; + } // end of TimeField + + public Timestamp TimestampField(int n, String name) { + if (rs == null) { + System.out.println("No result set"); + } else try { + return (n > 0) ? rs.getTimestamp(n) : rs.getTimestamp(name); + } catch (SQLException se) { + SetErrmsg(se); + } //end try/catch + + return null; + } // end of TimestampField + + public String ObjectField(int n, String name) { + if (rs == null) { + System.out.println("No result set"); + } else try { + return (n > 0) ? rs.getObject(n).toString() : rs.getObject(name).toString(); + } catch (SQLException se) { + SetErrmsg(se); + } //end try/catch + + return null; + } // end of ObjectField + + public int GetDrivers(String[] s, int mxs) { + int n = 0; + List drivers = Collections.list(DriverManager.getDrivers()); + int size = Math.min(mxs, drivers.size()); + + for (int i = 0; i < size; i++) { + Driver driver = (Driver)drivers.get(i); + + // Get name of driver + s[n++] = driver.getClass().getName(); + + // Get version info + s[n++] = driver.getMajorVersion() + "." + driver.getMinorVersion(); + s[n++] = driver.jdbcCompliant() ? "Yes" : "No"; + s[n++] = driver.toString(); + } // endfor i + + return size; + } // end of GetDrivers + + /** + * Adds the specified path to the java library path + * from Fahd Shariff blog + * + * @param pathToAdd the path to add + static public int addLibraryPath(String pathToAdd) { + System.out.println("jpath = " + pathToAdd); + + try { + Field usrPathsField = ClassLoader.class.getDeclaredField("usr_paths"); + usrPathsField.setAccessible(true); + + //get array of paths + String[] paths = (String[])usrPathsField.get(null); + + //check if the path to add is already present + for (String path : paths) { + System.out.println("path = " + path); + + if (path.equals(pathToAdd)) + return -5; + + } // endfor path + + //add the new path + String[] newPaths = Arrays.copyOf(paths, paths.length + 1); + newPaths[paths.length] = pathToAdd; + usrPathsField.set(null, newPaths); + System.setProperty("java.library.path", + System.getProperty("java.library.path") + File.pathSeparator + pathToAdd); + Field fieldSysPath = ClassLoader.class.getDeclaredField("sys_paths"); + fieldSysPath.setAccessible(true); + fieldSysPath.set(null, null); + } catch (Exception e) { + SetErrmsg(e); + return -1; + } // end try/catch + + return 0; + } // end of addLibraryPath + */ + +} // end of class JdbcInterface diff --git a/storage/connect/java/ds/JdbcInterface.class b/storage/connect/java/ds/JdbcInterface.class new file mode 100644 index 0000000000000000000000000000000000000000..85a52b016cb27f170e0a93bf2668727f6d7aeb11 GIT binary patch literal 16169 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

g!6 zEkeRKWyaAJdNk-{yT*11Q|59Bi%~0223|HmT zVS+2EjL)D6I8U6#XHhLG;d&0i+?ri{E_3)?X4kU{J!Yr4fVgB!rce#-JbPAv`P9y~M}W{$=+Ea4m%&m)h@vr`*ruJf@TILqN$ z?=R5sH(Y?V!o^w&rW$Q=q|o9> zA#6**i|-qoQ0aSM*6CUvrj*Dg?`N0-6?paraSzC(Iayot*-*Nu{W`67gta1jiI&G< ztkJMR@pvA$;MZCCRUjUAxh%h`$(J7F|x`b*5MF~f!H9dEe*kAmGGmm z^tu4Tlj~)U>&!v*K>TG0@lr&vEi{U+fa`2U#JURRb2TmEYiI>uOB)zp_VEo^Fx`m7 z(l)xBZ=$QQsJe#1Bsew^=sHKB*FpGFpewpYJCdUDm{W3$hc2{Zk%ulvAIUMs)QTwW z0011oH^+yNXnQO8p-#In;2pVZ zJif?L&#|ftg^X|}q$$@HN1BzgpND0p;%~zg@1*`XnjFF3p>n>PCh-o$`PWd)Gc02aE+p*W3b^y55vC_Lzth6tA#Y#V-4!D0(-d8yC7PFKP5Ia)dSN0}vBkrrP z#c8D4aZO_Q~PbWPHG=~8$Owob6`tka{! zJ|w+s89N3(?+)^McGZ=ZNnyXsBl+Hkf;;F${((~N@ZZVDZ&Q%p!3SFZM9K9o4deGU zX0wkx!dC7;TajkdH9+2i+4xS%gzg&<&dfSP07*C*WB~P-OJO%}Q?$#J;GQHB*`!Zq zUW4Q#Ao&DI@>9yge$D_yuz}#M2-J!UO~=dz@h#e+^K4AUjj=pkY6H3z@zemi!3H!6 zNG3l^*>I>lz76&14w9|t$pH5aMfV$Uh#@%E!74^-R#Te}!4#y@$fwdN2UT4jwzY<+ z3>vBeRIK{A;Ei(Njk1fLp>_#i;Q7gu2My}{|1Cr|gRcwt#L%Z6iEl*VZImSf#M1E& zMG|xc?sp(d)dmhY2(x}b8<$eWWRN#6E6Kw>{5_k8*KKEAX?VzTWX$)E_4J@#G}dcB+^cBO z*fjfLw>+fV5BKB2z7@3?KDAnMvD>-C;ZiTwR1vrw1}=wFt}2E~M$%X{il(X2G*6Y# z5;caFs!}>lm1{K_ZdW?ou5`Fv$q(_v;C5*Wx3H(&OQ0~+CXaA(A^o6BUlWt|gt`It zG_vq^$^m#W_-YLH(i{F6z&{iCX953g;6DZU=K%lQ z{|SGl#;?PRp#KrFknxr`Z1goE*;MIIa7q7JH~JS8HI(nCKzSFxh>)1E+Za{GZtXf% zsHT#>J{%@bsurv)1S_Y4l{&CePt#Qc%}|SIj#{eOF=cO!V@NfQA=TJ!Q$cq~`(O1MRDbO^t{DvACrB*f2!{vU4i|2)2@M1VdD^c_II9_V909|!vLzW{p2 zQ{LnMv(cYmocfm={eO-hr!D~c3xWP3puZUCF9G_^K(DuO>}|f!9jEx?r1U>U;y2Pi zLHq|?_@xwbXN=zB)aAf`1@K=9{9A$lD&W5w_^{|4qPuGw|O6{I`7}{8_gARgRPA_SunEFQQW;Z5bkMp2>5nuc9uMzr*Cc zvE8b_eoocGBpk9QL#)Ymw}Xpsfs1d0i#ve+PMV_bqAKM+JeuKz*BMTDoneR9DJel! zw2)WVlkHSc*2tYFMRrP|(}0MlpuiERhf%PXY0Hzmz|iq$ dst = null; + + // === Constructors/finalize ========================================= + public JdbcInterface() { + this(true); + } // end of default constructor + + public JdbcInterface(boolean b) { + DEBUG = b; + dst = new Hashtable(); + } // end of constructor + + private void SetErrmsg(Exception e) { + if (DEBUG) + System.out.println(e.getMessage()); + + Errmsg = e.toString(); + } // end of SetErrmsg + + private void SetErrmsg(String s) { + if (DEBUG) + System.out.println(s); + + Errmsg = s; + } // end of SetErrmsg + + public String GetErrmsg() { + String err = Errmsg; + + Errmsg = "No error"; + return err; + } // end of GetErrmsg + + public int JdbcConnect(String[] parms, int fsize, boolean scrollable) { + int rc = 0; + String url = parms[1]; + DataSource ds = null; + MysqlDataSource mds = null; + MariaDbDataSource ads = null; + OracleDataSource ods = null; + PoolingDataSource pds = null; + + if (url == null) { + SetErrmsg("URL cannot be null"); + return -1; + } // endif driver + + try { + if ((ds = dst.get(url)) == null) { + if (url.toLowerCase().contains("mysql")) { + mds = new MysqlDataSource(); + mds.setURL(url); + mds.setUser(parms[2]); + mds.setPassword(parms[3]); + ds = mds; + } else if (url.toLowerCase().contains("mariadb")) { + ads = new MariaDbDataSource(); + ads.setUrl(url); + ads.setUser(parms[2]); + ads.setPassword(parms[3]); + ds = ads; + } else if (url.toLowerCase().contains("oracle")) { + ods = new OracleDataSource(); + ods.setURL(url); + ods.setUser(parms[2]); + ods.setPassword(parms[3]); + ds = ods; + } else if (url.toLowerCase().contains("postgresql")) { + pds = new PoolingDataSource(); + pds.setUrl(url); + pds.setUser(parms[2]); + pds.setPassword(parms[3]); + ds = pds; + } else { + SetErrmsg("Unsupported driver"); + return -4; + } // endif driver + + dst.put(url, ds); + } // endif ds + + // Get a connection from the data source + conn = ds.getConnection(); + + // Get the data base meta data object + dbmd = conn.getMetaData(); + + // Get a statement from the connection + if (scrollable) + stmt = conn.createStatement(java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE, java.sql.ResultSet.CONCUR_READ_ONLY); + else + stmt = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY, java.sql.ResultSet.CONCUR_READ_ONLY); + + if (DEBUG) + System.out.println("Statement type = " + stmt.getResultSetType() + + " concurrency = " + stmt.getResultSetConcurrency()); + + if (DEBUG) // Get the fetch size of a statement + System.out.println("Default fetch size = " + stmt.getFetchSize()); + + if (fsize != 0) { + // Set the fetch size + stmt.setFetchSize(fsize); + + if (DEBUG) + System.out.println("New fetch size = " + stmt.getFetchSize()); + + } // endif fsize + + } catch (SQLException se) { + SetErrmsg(se); + rc = -2; + } catch( Exception e ) { + SetErrmsg(e); + rc = -3; + } // end try/catch + + return rc; + } // end of JdbcConnect + + public int CreatePrepStmt(String sql) { + int rc = 0; + + try { + pstmt = conn.prepareStatement(sql); + } catch (SQLException se) { + SetErrmsg(se); + rc = -1; + } catch (Exception e) { + SetErrmsg(e); + rc = -2; + } // end try/catch + + return rc; + } // end of CreatePrepStmt + + public void SetStringParm(int i, String s) { + try { + pstmt.setString(i, s); + } catch (Exception e) { + SetErrmsg(e); + } // end try/catch + + } // end of SetStringParm + + public void SetIntParm(int i, int n) { + try { + pstmt.setInt(i, n); + } catch (Exception e) { + SetErrmsg(e); + } // end try/catch + + } // end of SetIntParm + + public void SetShortParm(int i, short n) { + try { + pstmt.setShort(i, n); + } catch (Exception e) { + SetErrmsg(e); + } // end try/catch + + } // end of SetShortParm + + public void SetBigintParm(int i, long n) { + try { + pstmt.setLong(i, n); + } catch (Exception e) { + SetErrmsg(e); + } // end try/catch + + } // end of SetBigintParm + + public void SetFloatParm(int i, float f) { + try { + pstmt.setFloat(i, f); + } catch (Exception e) { + SetErrmsg(e); + } // end try/catch + + } // end of SetFloatParm + + public void SetDoubleParm(int i, double d) { + try { + pstmt.setDouble(i, d); + } catch (Exception e) { + SetErrmsg(e); + } // end try/catch + + } // end of SetDoubleParm + + public void SetTimestampParm(int i, Timestamp t) { + try { + pstmt.setTimestamp(i, t); + } catch (Exception e) { + SetErrmsg(e); + } // end try/catch + + } // end of SetTimestampParm + + public int ExecutePrep() { + int n = -3; + + if (pstmt != null) try { + n = pstmt.executeUpdate(); + } catch (SQLException se) { + SetErrmsg(se); + n = -1; + } catch (Exception e) { + SetErrmsg(e); + n = -2; + } //end try/catch + + return n; + } // end of ExecutePrep + + public boolean ClosePrepStmt() { + boolean b = false; + + if (pstmt != null) try { + pstmt.close(); + pstmt = null; + } catch (SQLException se) { + SetErrmsg(se); + b = true; + } catch (Exception e) { + SetErrmsg(e); + b = true; + } // end try/catch + + return b; + } // end of ClosePrepStmt + + public int JdbcDisconnect() { + int rc = 0; + + // Cancel pending statement + if (stmt != null) + try { + System.out.println("Cancelling statement"); + stmt.cancel(); + } catch(SQLException se) { + SetErrmsg(se); + rc += 1; + } // nothing more we can do + + // Close the statement and the connection + if (rs != null) + try { + if (DEBUG) + System.out.println("Closing result set"); + + rs.close(); + } catch(SQLException se) { + SetErrmsg(se); + rc = 2; + } // nothing more we can do + + if (stmt != null) + try { + if (DEBUG) + System.out.println("Closing statement"); + + stmt.close(); + } catch(SQLException se) { + SetErrmsg(se); + rc += 4; + } // nothing more we can do + + ClosePrepStmt(); + + if (conn != null) + try { + if (DEBUG) + System.out.println("Closing connection"); + + conn.close(); + } catch (SQLException se) { + SetErrmsg(se); + rc += 8; + } //end try/catch + + if (DEBUG) + System.out.println("All closed"); + + return rc; + } // end of JdbcDisconnect + + public int GetMaxValue(int n) { + int m = 0; + + try { + switch (n) { + case 1: // Max columns in table + m = dbmd.getMaxColumnsInTable(); + break; + case 2: // Max catalog name length + m = dbmd.getMaxCatalogNameLength(); + break; + case 3: // Max schema name length + m = dbmd.getMaxSchemaNameLength(); + break; + case 4: // Max table name length + m = dbmd.getMaxTableNameLength(); + break; + case 5: // Max column name length + m = dbmd.getMaxColumnNameLength(); + break; + } // endswitch n + + } catch(Exception e) { + SetErrmsg(e); + m = -1; + } // end try/catch + + return m; + } // end of GetMaxValue + + public int GetColumns(String[] parms) { + int ncol = 0; + + try { + if (rs != null) rs.close(); + rs = dbmd.getColumns(parms[0], parms[1], parms[2], parms[3]); + + if (rs != null) { + rsmd = rs.getMetaData(); + ncol = rsmd.getColumnCount(); + } // endif rs + + } catch(SQLException se) { + SetErrmsg(se); + } // end try/catch + + return ncol; + } // end of GetColumns + + public int GetTables(String[] parms) { + int ncol = 0; + String[] typ = null; + + if (parms[3] != null) { + typ = new String[1]; + typ[0] = parms[3]; + } // endif parms + + try { + if (rs != null) rs.close(); + rs = dbmd.getTables(parms[0], parms[1], parms[2], typ); + + if (rs != null) { + rsmd = rs.getMetaData(); + ncol = rsmd.getColumnCount(); + } // endif rs + + } catch(SQLException se) { + SetErrmsg(se); + } // end try/catch + + return ncol; + } // end of GetColumns + + public int Execute(String query) { + int n = 0; + + if (DEBUG) + System.out.println("Executing '" + query + "'"); + + try { + boolean b = stmt.execute(query); + + if (b == false) { + n = stmt.getUpdateCount(); + if (rs != null) rs.close(); + } // endif b + + if (DEBUG) + System.out.println("Query '" + query + "' executed: n = " + n); + + } catch (SQLException se) { + SetErrmsg(se); + n = -1; + } catch (Exception e) { + SetErrmsg(e); + n = -2; + } //end try/catch + + return n; + } // end of Execute + + public int GetResult() { + int ncol = 0; + + try { + rs = stmt.getResultSet(); + + if (rs != null) { + rsmd = rs.getMetaData(); + ncol = rsmd.getColumnCount(); + + if (DEBUG) + System.out.println("Result set has " + rsmd.getColumnCount() + " column(s)"); + + } // endif rs + + } catch (SQLException se) { + SetErrmsg(se); + ncol = -1; + } catch (Exception e) { + SetErrmsg(e); + ncol = -2; + } //end try/catch + + return ncol; + } // end of GetResult + + public int ExecuteQuery(String query) { + int ncol = 0; + + if (DEBUG) + System.out.println("Executing query '" + query + "'"); + + try { + rs = stmt.executeQuery(query); + rsmd = rs.getMetaData(); + ncol = rsmd.getColumnCount(); + + if (DEBUG) { + System.out.println("Query '" + query + "' executed successfully"); + System.out.println("Result set has " + rsmd.getColumnCount() + " column(s)"); + } // endif DEBUG + + } catch (SQLException se) { + SetErrmsg(se); + ncol = -1; + } catch (Exception e) { + SetErrmsg(e); + ncol = -2; + } //end try/catch + + return ncol; + } // end of ExecuteQuery + + public int ExecuteUpdate(String query) { + int n = 0; + + if (DEBUG) + System.out.println("Executing update query '" + query + "'"); + + try { + n = stmt.executeUpdate(query); + + if (DEBUG) + System.out.println("Update Query '" + query + "' executed: n = " + n); + + } catch (SQLException se) { + SetErrmsg(se); + n = -1; + } catch (Exception e) { + SetErrmsg(e); + n = -2; + } //end try/catch + + return n; + } // end of ExecuteUpdate + + public int ReadNext() { + if (rs != null) { + try { + return rs.next() ? 1 : 0; + } catch (SQLException se) { + SetErrmsg(se); + return -1; + } //end try/catch + + } else + return 0; + + } // end of ReadNext + + public boolean Fetch(int row) { + if (rs != null) { + try { + return rs.absolute(row); + } catch (SQLException se) { + SetErrmsg(se); + return false; + } //end try/catch + + } else + return false; + + } // end of Fetch + + public String ColumnName(int n) { + if (rsmd == null) { + System.out.println("No result metadata"); + } else try { + return rsmd.getColumnLabel(n); + } catch (SQLException se) { + SetErrmsg(se); + } //end try/catch + + return null; + } // end of ColumnName + + public int ColumnType(int n, String name) { + if (rsmd == null) { + System.out.println("No result metadata"); + } else try { + if (n == 0) + n = rs.findColumn(name); + + return rsmd.getColumnType(n); + } catch (SQLException se) { + SetErrmsg(se); + } //end try/catch + + return 666; // Not a type + } // end of ColumnType + + public String ColumnDesc(int n, int[] val) { + if (rsmd == null) { + System.out.println("No result metadata"); + return null; + } else try { + val[0] = rsmd.getColumnType(n); + val[1] = rsmd.getPrecision(n); + val[2] = rsmd.getScale(n); + val[3] = rsmd.isNullable(n); + return rsmd.getColumnLabel(n); + } catch (SQLException se) { + SetErrmsg(se); + } //end try/catch + + return null; + } // end of ColumnDesc + + public String StringField(int n, String name) { + if (rs == null) { + System.out.println("No result set"); + } else try { + return (n > 0) ? rs.getString(n) : rs.getString(name); + } catch (SQLException se) { + SetErrmsg(se); + } //end try/catch + + return null; + } // end of StringField + + public int IntField(int n, String name) { + if (rs == null) { + System.out.println("No result set"); + } else try { + return (n > 0) ? rs.getInt(n) : rs.getInt(name); + } catch (SQLException se) { + SetErrmsg(se); + } //end try/catch + + return 0; + } // end of IntField + + public long BigintField(int n, String name) { + if (rs == null) { + System.out.println("No result set"); + } else try { + BigDecimal bigDecimal = (n > 0) ? rs.getBigDecimal(n) : rs.getBigDecimal(name); + return bigDecimal != null ? bigDecimal.longValue() : 0; + } catch (SQLException se) { + SetErrmsg(se); + } //end try/catch + + return 0; + } // end of BiginttField + + public double DoubleField(int n, String name) { + if (rs == null) { + System.out.println("No result set"); + } else try { + return (n > 0) ? rs.getDouble(n) : rs.getDouble(name); + } catch (SQLException se) { + SetErrmsg(se); + } //end try/catch + + return 0.; + } // end of DoubleField + + public float FloatField(int n, String name) { + if (rs == null) { + System.out.println("No result set"); + } else try { + return (n > 0) ? rs.getFloat(n) : rs.getFloat(name); + } catch (SQLException se) { + SetErrmsg(se); + } //end try/catch + + return 0; + } // end of FloatField + + public boolean BooleanField(int n, String name) { + if (rs == null) { + System.out.println("No result set"); + } else try { + return (n > 0) ? rs.getBoolean(n) : rs.getBoolean(name); + } catch (SQLException se) { + SetErrmsg(se); + } //end try/catch + + return false; + } // end of BooleanField + + public Date DateField(int n, String name) { + if (rs == null) { + System.out.println("No result set"); + } else try { + return (n > 0) ? rs.getDate(n) : rs.getDate(name); + } catch (SQLException se) { + SetErrmsg(se); + } //end try/catch + + return null; + } // end of DateField + + public Time TimeField(int n, String name) { + if (rs == null) { + System.out.println("No result set"); + } else try { + return (n > 0) ? rs.getTime(n) : rs.getTime(name); + } catch (SQLException se) { + SetErrmsg(se); + } //end try/catch + + return null; + } // end of TimeField + + public Timestamp TimestampField(int n, String name) { + if (rs == null) { + System.out.println("No result set"); + } else try { + return (n > 0) ? rs.getTimestamp(n) : rs.getTimestamp(name); + } catch (SQLException se) { + SetErrmsg(se); + } //end try/catch + + return null; + } // end of TimestampField + + public String ObjectField(int n, String name) { + if (rs == null) { + System.out.println("No result set"); + } else try { + return (n > 0) ? rs.getObject(n).toString() : rs.getObject(name).toString(); + } catch (SQLException se) { + SetErrmsg(se); + } //end try/catch + + return null; + } // end of ObjectField + + public int GetDrivers(String[] s, int mxs) { + int n = 0; + List drivers = Collections.list(DriverManager.getDrivers()); + int size = Math.min(mxs, drivers.size()); + + for (int i = 0; i < size; i++) { + Driver driver = (Driver)drivers.get(i); + + // Get name of driver + s[n++] = driver.getClass().getName(); + + // Get version info + s[n++] = driver.getMajorVersion() + "." + driver.getMinorVersion(); + s[n++] = driver.jdbcCompliant() ? "Yes" : "No"; + s[n++] = driver.toString(); + } // endfor i + + return size; + } // end of GetDrivers + + /** + * Adds the specified path to the java library path + * from Fahd Shariff blog + * + * @param pathToAdd the path to add + static public int addLibraryPath(String pathToAdd) { + System.out.println("jpath = " + pathToAdd); + + try { + Field usrPathsField = ClassLoader.class.getDeclaredField("usr_paths"); + usrPathsField.setAccessible(true); + + //get array of paths + String[] paths = (String[])usrPathsField.get(null); + + //check if the path to add is already present + for (String path : paths) { + System.out.println("path = " + path); + + if (path.equals(pathToAdd)) + return -5; + + } // endfor path + + //add the new path + String[] newPaths = Arrays.copyOf(paths, paths.length + 1); + newPaths[paths.length] = pathToAdd; + usrPathsField.set(null, newPaths); + System.setProperty("java.library.path", + System.getProperty("java.library.path") + File.pathSeparator + pathToAdd); + Field fieldSysPath = ClassLoader.class.getDeclaredField("sys_paths"); + fieldSysPath.setAccessible(true); + fieldSysPath.set(null, null); + } catch (Exception e) { + SetErrmsg(e); + return -1; + } // end try/catch + + return 0; + } // end of addLibraryPath + */ + +} // end of class JdbcInterface diff --git a/storage/connect/java/std/JdbcInterface.class b/storage/connect/java/std/JdbcInterface.class new file mode 100644 index 0000000000000000000000000000000000000000..8c5ba6439f3fa073f8fa5f892e9ae84a581bc113 GIT binary patch literal 15215 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 0) ? rs.getString(n) : rs.getString(name); + } catch (SQLException se) { + SetErrmsg(se); + } //end try/catch + + return null; + } // end of StringField + + public int IntField(int n, String name) { + if (rs == null) { + System.out.println("No result set"); + } else try { + return (n > 0) ? rs.getInt(n) : rs.getInt(name); + } catch (SQLException se) { + SetErrmsg(se); + } //end try/catch + + return 0; + } // end of IntField + + public long BigintField(int n, String name) { + if (rs == null) { + System.out.println("No result set"); + } else try { + BigDecimal bigDecimal = (n > 0) ? rs.getBigDecimal(n) : rs.getBigDecimal(name); + return bigDecimal != null ? bigDecimal.longValue() : 0; + } catch (SQLException se) { + SetErrmsg(se); + } //end try/catch + + return 0; + } // end of BiginttField + + public double DoubleField(int n, String name) { + if (rs == null) { + System.out.println("No result set"); + } else try { + return (n > 0) ? rs.getDouble(n) : rs.getDouble(name); + } catch (SQLException se) { + SetErrmsg(se); + } //end try/catch + + return 0.; + } // end of DoubleField + + public float FloatField(int n, String name) { + if (rs == null) { + System.out.println("No result set"); + } else try { + return (n > 0) ? rs.getFloat(n) : rs.getFloat(name); + } catch (SQLException se) { + SetErrmsg(se); + } //end try/catch + + return 0; + } // end of FloatField + + public boolean BooleanField(int n, String name) { + if (rs == null) { + System.out.println("No result set"); + } else try { + return (n > 0) ? rs.getBoolean(n) : rs.getBoolean(name); + } catch (SQLException se) { + SetErrmsg(se); + } //end try/catch + + return false; + } // end of BooleanField + + public Date DateField(int n, String name) { + if (rs == null) { + System.out.println("No result set"); + } else try { + return (n > 0) ? rs.getDate(n) : rs.getDate(name); + } catch (SQLException se) { + SetErrmsg(se); + } //end try/catch + + return null; + } // end of DateField + + public Time TimeField(int n, String name) { + if (rs == null) { + System.out.println("No result set"); + } else try { + return (n > 0) ? rs.getTime(n) : rs.getTime(name); + } catch (SQLException se) { + SetErrmsg(se); + } //end try/catch + + return null; + } // end of TimeField + + public Timestamp TimestampField(int n, String name) { + if (rs == null) { + System.out.println("No result set"); + } else try { + return (n > 0) ? rs.getTimestamp(n) : rs.getTimestamp(name); + } catch (SQLException se) { + SetErrmsg(se); + } //end try/catch + + return null; + } // end of TimestampField + + public String ObjectField(int n, String name) { + if (rs == null) { + System.out.println("No result set"); + } else try { + return (n > 0) ? rs.getObject(n).toString() : rs.getObject(name).toString(); + } catch (SQLException se) { + SetErrmsg(se); + } //end try/catch + + return null; + } // end of ObjectField + + public int GetDrivers(String[] s, int mxs) { + int n = 0; + List drivers = Collections.list(DriverManager.getDrivers()); + int size = Math.min(mxs, drivers.size()); + + for (int i = 0; i < size; i++) { + Driver driver = (Driver)drivers.get(i); + + // Get name of driver + s[n++] = driver.getClass().getName(); + + // Get version info + s[n++] = driver.getMajorVersion() + "." + driver.getMinorVersion(); + s[n++] = driver.jdbcCompliant() ? "Yes" : "No"; + s[n++] = driver.toString(); + } // endfor i + + return size; + } // end of GetDrivers + + /** + * Adds the specified path to the java library path + * from Fahd Shariff blog + * + * @param pathToAdd the path to add + static public int addLibraryPath(String pathToAdd) { + System.out.println("jpath = " + pathToAdd); + + try { + Field usrPathsField = ClassLoader.class.getDeclaredField("usr_paths"); + usrPathsField.setAccessible(true); + + //get array of paths + String[] paths = (String[])usrPathsField.get(null); + + //check if the path to add is already present + for (String path : paths) { + System.out.println("path = " + path); + + if (path.equals(pathToAdd)) + return -5; + + } // endfor path + + //add the new path + String[] newPaths = Arrays.copyOf(paths, paths.length + 1); + newPaths[paths.length] = pathToAdd; + usrPathsField.set(null, newPaths); + System.setProperty("java.library.path", + System.getProperty("java.library.path") + File.pathSeparator + pathToAdd); + Field fieldSysPath = ClassLoader.class.getDeclaredField("sys_paths"); + fieldSysPath.setAccessible(true); + fieldSysPath.set(null, null); + } catch (Exception e) { + SetErrmsg(e); + return -1; + } // end try/catch + + return 0; + } // end of addLibraryPath + */ + +} // end of class JdbcInterface From afa4657fd334056ea8de0c83e1ad655fd49566ae Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Tue, 24 May 2016 23:57:06 +0200 Subject: [PATCH 14/18] - Fix failing json_udf_bin test when --ps modified: storage/connect/jsonudf.cpp modified: storage/connect/mysql-test/connect/disabled.def --- storage/connect/jsonudf.cpp | 280 +++++++++++++++--- .../connect/mysql-test/connect/disabled.def | 2 +- 2 files changed, 240 insertions(+), 42 deletions(-) diff --git a/storage/connect/jsonudf.cpp b/storage/connect/jsonudf.cpp index 26965672ba4a2..4cead25989601 100644 --- a/storage/connect/jsonudf.cpp +++ b/storage/connect/jsonudf.cpp @@ -1805,7 +1805,20 @@ my_bool json_array_add_values_init(UDF_INIT *initid, UDF_ARGS *args, char *messa } else CalcLen(args, false, reslen, memlen); - return JsonInit(initid, args, message, true, reslen, memlen); + if (!JsonInit(initid, args, message, true, reslen, memlen)) { + PGLOBAL g = (PGLOBAL)initid->ptr; + + // This is a constant function + g->N = (initid->const_item) ? 1 : 0; + + // This is to avoid double execution when using prepared statements + if (IsJson(args, 0) > 1) + initid->const_item = 0; + + return false; + } else + return true; + } // end of json_array_add_values_init char *json_array_add_values(UDF_INIT *initid, UDF_ARGS *args, char *result, @@ -1850,7 +1863,7 @@ char *json_array_add_values(UDF_INIT *initid, UDF_ARGS *args, char *result, } // endif str // Keep result of constant function - g->Xchk = (initid->const_item) ? str : NULL; + g->Xchk = (g->N) ? str : NULL; } else str = (char*)g->Xchk; @@ -1873,7 +1886,7 @@ void json_array_add_values_deinit(UDF_INIT* initid) /*********************************************************************************/ my_bool json_array_add_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { - unsigned long reslen, memlen; + unsigned long reslen, memlen; if (args->arg_count < 2) { strcpy(message, "This function must have at least 2 arguments"); @@ -1884,7 +1897,20 @@ my_bool json_array_add_init(UDF_INIT *initid, UDF_ARGS *args, char *message) } else CalcLen(args, false, reslen, memlen, true); - return JsonInit(initid, args, message, true, reslen, memlen); + if (!JsonInit(initid, args, message, true, reslen, memlen)) { + PGLOBAL g = (PGLOBAL)initid->ptr; + + // This is a constant function + g->N = (initid->const_item) ? 1 : 0; + + // This is to avoid double execution when using prepared statements + if (IsJson(args, 0) > 1) + initid->const_item = 0; + + return false; + } else + return true; + } // end of json_array_add_init char *json_array_add(UDF_INIT *initid, UDF_ARGS *args, char *result, @@ -1930,7 +1956,7 @@ char *json_array_add(UDF_INIT *initid, UDF_ARGS *args, char *result, if (!str) str = MakePSZ(g, args, 0); - if (initid->const_item) + if (g->N) // Keep result of constant function g->Xchk = str; @@ -1966,7 +1992,20 @@ my_bool json_array_delete_init(UDF_INIT *initid, UDF_ARGS *args, char *message) } else CalcLen(args, false, reslen, memlen, true); - return JsonInit(initid, args, message, true, reslen, memlen); + if (!JsonInit(initid, args, message, true, reslen, memlen)) { + PGLOBAL g = (PGLOBAL)initid->ptr; + + // This is a constant function + g->N = (initid->const_item) ? 1 : 0; + + // This is to avoid double execution when using prepared statements + if (IsJson(args, 0) > 1) + initid->const_item = 0; + + return false; + } else + return true; + } // end of json_array_delete_init char *json_array_delete(UDF_INIT *initid, UDF_ARGS *args, char *result, @@ -2008,7 +2047,7 @@ char *json_array_delete(UDF_INIT *initid, UDF_ARGS *args, char *result, if (!str) str = MakePSZ(g, args, 0); - if (initid->const_item) + if (g->N) // Keep result of constant function g->Xchk = str; @@ -2184,7 +2223,20 @@ my_bool json_object_add_init(UDF_INIT *initid, UDF_ARGS *args, char *message) } else CalcLen(args, true, reslen, memlen, true); - return JsonInit(initid, args, message, true, reslen, memlen); + if (!JsonInit(initid, args, message, true, reslen, memlen)) { + PGLOBAL g = (PGLOBAL)initid->ptr; + + // This is a constant function + g->N = (initid->const_item) ? 1 : 0; + + // This is to avoid double execution when using prepared statements + if (IsJson(args, 0) > 1) + initid->const_item = 0; + + return false; + } else + return true; + } // end of json_object_add_init char *json_object_add(UDF_INIT *initid, UDF_ARGS *args, char *result, @@ -2227,7 +2279,7 @@ char *json_object_add(UDF_INIT *initid, UDF_ARGS *args, char *result, if (!str) str = MakePSZ(g, args, 0); - if (initid->const_item) + if (g->N) // Keep result of constant function g->Xchk = str; @@ -2266,7 +2318,20 @@ my_bool json_object_delete_init(UDF_INIT *initid, UDF_ARGS *args, char *message) } else CalcLen(args, true, reslen, memlen, true); - return JsonInit(initid, args, message, true, reslen, memlen); + if (!JsonInit(initid, args, message, true, reslen, memlen)) { + PGLOBAL g = (PGLOBAL)initid->ptr; + + // This is a constant function + g->N = (initid->const_item) ? 1 : 0; + + // This is to avoid double execution when using prepared statements + if (IsJson(args, 0) > 1) + initid->const_item = 0; + + return false; + } else + return true; + } // end of json_object_delete_init char *json_object_delete(UDF_INIT *initid, UDF_ARGS *args, char *result, @@ -2307,7 +2372,7 @@ char *json_object_delete(UDF_INIT *initid, UDF_ARGS *args, char *result, if (!str) str = MakePSZ(g, args, 0); - if (initid->const_item) + if (g->N) // Keep result of constant function g->Xchk = str; @@ -2605,7 +2670,20 @@ my_bool json_item_merge_init(UDF_INIT *initid, UDF_ARGS *args, char *message) } else CalcLen(args, false, reslen, memlen, true); - return JsonInit(initid, args, message, true, reslen, memlen); + if (!JsonInit(initid, args, message, true, reslen, memlen)) { + PGLOBAL g = (PGLOBAL)initid->ptr; + + // This is a constant function + g->N = (initid->const_item) ? 1 : 0; + + // This is to avoid double execution when using prepared statements + if (IsJson(args, 0) > 1) + initid->const_item = 0; + + return false; + } else + return true; + } // end of json_item_merge_init char *json_item_merge(UDF_INIT *initid, UDF_ARGS *args, char *result, @@ -2651,7 +2729,7 @@ char *json_item_merge(UDF_INIT *initid, UDF_ARGS *args, char *result, if (!str) str = MakePSZ(g, args, 0); - if (initid->const_item) + if (g->N) // Keep result of constant function g->Xchk = str; @@ -3552,11 +3630,11 @@ char *handle_item(UDF_INIT *initid, UDF_ARGS *args, char *result, PGLOBAL g = (PGLOBAL)initid->ptr; PGLOBAL gb = GetMemPtr(g, args, 0); - if (g->N) { + if (g->Alchecked) { str = (char*)g->Activityp; goto fin; - } else if (initid->const_item) - g->N = 1; + } else if (g->N) + g->Alchecked = 1; if (!strcmp(result, "$set")) w = 0; @@ -3632,7 +3710,7 @@ char *handle_item(UDF_INIT *initid, UDF_ARGS *args, char *result, if (!(str = MakeResult(g, args, jsp, INT_MAX32))) str = MakePSZ(g, args, 0); - if (initid->const_item) + if (g->N) // Keep result of constant function g->Activityp = (PACTIVITY)str; @@ -3677,7 +3755,21 @@ my_bool json_set_item_init(UDF_INIT *initid, UDF_ARGS *args, char *message) } else if (n != 3) memlen += args->lengths[0] * 3; - return JsonInit(initid, args, message, true, reslen, memlen); + if (!JsonInit(initid, args, message, true, reslen, memlen)) { + PGLOBAL g = (PGLOBAL)initid->ptr; + + // This is a constant function + g->N = (initid->const_item) ? 1 : 0; + + // This is to avoid double execution when using prepared statements + if (IsJson(args, 0) > 1) + initid->const_item = 0; + + g->Alchecked = 0; + return false; + } else + return true; + } // end of json_set_item_init char *json_set_item(UDF_INIT *initid, UDF_ARGS *args, char *result, @@ -3742,8 +3834,8 @@ my_bool json_file_init(UDF_INIT *initid, UDF_ARGS *args, char *message) if (args->arg_count < 1 || args->arg_count > 4) { strcpy(message, "This function only accepts 1 to 4 arguments"); return true; - } else if (!args->args[0] || args->arg_type[0] != STRING_RESULT) { - strcpy(message, "First argument must be a constant string (file name)"); + } else if (args->arg_type[0] != STRING_RESULT) { + strcpy(message, "First argument must be a string (file name)"); return true; } // endif's args[0] @@ -3761,7 +3853,12 @@ my_bool json_file_init(UDF_INIT *initid, UDF_ARGS *args, char *message) initid->maybe_null = 1; CalcLen(args, false, reslen, memlen); - fl = GetFileLength(args->args[0]); + + if (args->args[0]) + fl = GetFileLength(args->args[0]); + else + fl = 100; // What can be done here? + reslen += fl; if (initid->const_item) @@ -4020,7 +4117,18 @@ void jbin_array_deinit(UDF_INIT* initid) /*********************************************************************************/ my_bool jbin_array_add_values_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { - return json_array_add_values_init(initid, args, message); + unsigned long reslen, memlen; + + if (args->arg_count < 2) { + strcpy(message, "This function must have at least 2 arguments"); + return true; + } else if (!IsJson(args, 0) && args->arg_type[0] != STRING_RESULT) { + strcpy(message, "First argument must be a json string or item"); + return true; + } else + CalcLen(args, false, reslen, memlen); + + return JsonInit(initid, args, message, true, reslen, memlen); } // end of jbin_array_add_values_init char *jbin_array_add_values(UDF_INIT *initid, UDF_ARGS *args, char *result, @@ -4090,7 +4198,18 @@ void jbin_array_add_values_deinit(UDF_INIT* initid) /*********************************************************************************/ my_bool jbin_array_add_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { - return json_array_add_init(initid, args, message); + unsigned long reslen, memlen; + + if (args->arg_count < 2) { + strcpy(message, "This function must have at least 2 arguments"); + return true; + } else if (!IsJson(args, 0)) { + strcpy(message, "First argument must be a json item"); + return true; + } else + CalcLen(args, false, reslen, memlen, true); + + return JsonInit(initid, args, message, true, reslen, memlen); } // end of jbin_array_add_init char *jbin_array_add(UDF_INIT *initid, UDF_ARGS *args, char *result, @@ -4160,8 +4279,19 @@ void jbin_array_add_deinit(UDF_INIT* initid) /*********************************************************************************/ my_bool jbin_array_delete_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { - return json_array_delete_init(initid, args, message); -} // end of jbin_array_delete_init + unsigned long reslen, memlen; + + if (args->arg_count < 2) { + strcpy(message, "This function must have at least 2 arguments"); + return true; + } else if (!IsJson(args, 0)) { + strcpy(message, "First argument must be a json item"); + return true; + } else + CalcLen(args, false, reslen, memlen, true); + + return JsonInit(initid, args, message, true, reslen, memlen); + } // end of jbin_array_delete_init char *jbin_array_delete(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *res_length, char *is_null, char *error) @@ -4383,8 +4513,19 @@ void jbin_object_key_deinit(UDF_INIT* initid) /*********************************************************************************/ my_bool jbin_object_add_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { - return json_object_add_init(initid, args, message); -} // end of jbin_object_add_init + unsigned long reslen, memlen; + + if (args->arg_count < 2) { + strcpy(message, "This function must have at least 2 arguments"); + return true; + } else if (!IsJson(args, 0)) { + strcpy(message, "First argument must be a json item"); + return true; + } else + CalcLen(args, true, reslen, memlen, true); + + return JsonInit(initid, args, message, true, reslen, memlen); + } // end of jbin_object_add_init char *jbin_object_add(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *res_length, char *is_null, char *error) @@ -4449,8 +4590,22 @@ void jbin_object_add_deinit(UDF_INIT* initid) /*********************************************************************************/ my_bool jbin_object_delete_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { - return json_object_delete_init(initid, args, message); -} // end of jbin_object_delete_init + unsigned long reslen, memlen; + + if (args->arg_count < 2) { + strcpy(message, "This function must have 2 or 3 arguments"); + return true; + } else if (!IsJson(args, 0)) { + strcpy(message, "First argument must be a json item"); + return true; + } else if (args->arg_type[1] != STRING_RESULT) { + strcpy(message, "Second argument must be a key string"); + return true; + } else + CalcLen(args, true, reslen, memlen, true); + + return JsonInit(initid, args, message, true, reslen, memlen); + } // end of jbin_object_delete_init char *jbin_object_delete(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *res_length, char *is_null, char *error) @@ -4659,8 +4814,22 @@ void jbin_get_item_deinit(UDF_INIT* initid) /*********************************************************************************/ my_bool jbin_item_merge_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { - return json_item_merge_init(initid, args, message); -} // end of jbin_item_merge_init + unsigned long reslen, memlen; + + if (args->arg_count < 2) { + strcpy(message, "This function must have at least 2 arguments"); + return true; + } else if (!IsJson(args, 0)) { + strcpy(message, "First argument must be a json item"); + return true; + } else if (!IsJson(args, 1)) { + strcpy(message, "Second argument must be a json item"); + return true; + } else + CalcLen(args, false, reslen, memlen, true); + + return JsonInit(initid, args, message, true, reslen, memlen); + } // end of jbin_item_merge_init char *jbin_item_merge(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *res_length, char *is_null, char *error) @@ -4820,8 +4989,31 @@ char *bin_handle_item(UDF_INIT *initid, UDF_ARGS *args, char *result, /*********************************************************************************/ my_bool jbin_set_item_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { - return json_set_item_init(initid, args, message); -} // end of jbin_set_item_init + unsigned long reslen, memlen; + int n = IsJson(args, 0); + + if (!(args->arg_count % 2)) { + strcpy(message, "This function must have an odd number of arguments"); + return true; + } else if (!n && args->arg_type[0] != STRING_RESULT) { + strcpy(message, "First argument must be a json item"); + return true; + } else + CalcLen(args, false, reslen, memlen); + + if (n == 2 && args->args[0]) { + char fn[_MAX_PATH]; + long fl; + + memcpy(fn, args->args[0], args->lengths[0]); + fn[args->lengths[0]] = 0; + fl = GetFileLength(fn); + memlen += fl * 3; + } else if (n != 3) + memlen += args->lengths[0] * 3; + + return JsonInit(initid, args, message, true, reslen, memlen); + } // end of jbin_set_item_init char *jbin_set_item(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *res_length, char *is_null, char *p) @@ -4992,7 +5184,7 @@ my_bool json_serialize_init(UDF_INIT *initid, UDF_ARGS *args, char *message) if (args->arg_count != 1) { strcpy(message, "This function must have 1 argument"); return true; - } else if (IsJson(args, 0) != 3) { + } else if (args->args[0] && IsJson(args, 0) != 3) { strcpy(message, "Argument must be a Jbin tree"); return true; } else @@ -5002,21 +5194,27 @@ my_bool json_serialize_init(UDF_INIT *initid, UDF_ARGS *args, char *message) } // end of json_serialize_init char *json_serialize(UDF_INIT *initid, UDF_ARGS *args, char *result, - unsigned long *res_length, char *, char *) + unsigned long *res_length, char *, char *error) { char *str; PGLOBAL g = (PGLOBAL)initid->ptr; if (!g->Xchk) { - PBSON bsp = (PBSON)args->args[0]; + if (IsJson(args, 0) == 3) { + PBSON bsp = (PBSON)args->args[0]; - JsonSubSet(g); + JsonSubSet(g); - if (!(str = Serialize(g, bsp->Jsp, NULL, 0))) - str = strcpy(result, g->Message); + if (!(str = Serialize(g, bsp->Jsp, NULL, 0))) + str = strcpy(result, g->Message); + + // Keep result of constant function + g->Xchk = (initid->const_item) ? str : NULL; + } else { + *error = 1; + str = strcpy(result, "Argument is not a Jbin tree"); + } // endif - // Keep result of constant function - g->Xchk = (initid->const_item) ? str : NULL; } else str = (char*)g->Xchk; diff --git a/storage/connect/mysql-test/connect/disabled.def b/storage/connect/mysql-test/connect/disabled.def index 67acb5dff29f3..897c8fa741ed9 100644 --- a/storage/connect/mysql-test/connect/disabled.def +++ b/storage/connect/mysql-test/connect/disabled.def @@ -1 +1 @@ -json_udf_bin : broken upstream in --ps +#json_udf_bin : broken upstream in --ps From ead4147b13aa828f3b8393a2fc294479df9e4bb3 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Thu, 26 May 2016 18:48:47 +0200 Subject: [PATCH 15/18] - Reconize the JDBC type -7 (BIT) modified: storage/connect/jdbconn.cpp - Add the global variable connect_java_wrapper This enables to use different wrappers modified: storage/connect/CMakeLists.txt renamed: storage/connect/java/ap/JdbcInterface.class -> storage/connect/JdbcApacheInterface.class renamed: storage/connect/java/ap/JdbcInterface.java -> storage/connect/JdbcApacheInterface.java renamed: storage/connect/java/ds/JdbcInterface.class -> storage/connect/JdbcDSInterface.class renamed: storage/connect/java/ds/JdbcInterface.java -> storage/connect/JdbcDSInterface.java modified: storage/connect/ha_connect.cc deleted: storage/connect/java/std/JdbcInterface.class deleted: storage/connect/java/std/JdbcInterface.java modified: storage/connect/jdbconn.cpp modified: storage/connect/jdbconn.h - Add JDBC tests (disabled) modified: storage/connect/mysql-test/connect/disabled.def new file: storage/connect/mysql-test/connect/r/jdbc.result new file: storage/connect/mysql-test/connect/r/jdbc_new.result new file: storage/connect/mysql-test/connect/r/jdbc_oracle.result new file: storage/connect/mysql-test/connect/r/jdbc_postgresql.result new file: storage/connect/mysql-test/connect/std_data/girls.txt new file: storage/connect/mysql-test/connect/t/jdbc.test new file: storage/connect/mysql-test/connect/t/jdbc_new.test new file: storage/connect/mysql-test/connect/t/jdbc_oracle.test new file: storage/connect/mysql-test/connect/t/jdbc_postgresql.test new file: storage/connect/mysql-test/connect/t/jdbconn.inc new file: storage/connect/mysql-test/connect/t/jdbconn_cleanup.inc - Typo modified: storage/connect/jsonudf.cpp --- storage/connect/CMakeLists.txt | 4 +- ...erface.class => JdbcApacheInterface.class} | Bin 15339 -> 15357 bytes ...nterface.java => JdbcApacheInterface.java} | 8 +- ...cInterface.class => JdbcDSInterface.class} | Bin 16169 -> 16175 bytes ...dbcInterface.java => JdbcDSInterface.java} | 8 +- storage/connect/ha_connect.cc | 8 + storage/connect/java/std/JdbcInterface.class | Bin 15215 -> 0 bytes storage/connect/java/std/JdbcInterface.java | 712 ------------------ storage/connect/jdbconn.cpp | 23 +- storage/connect/jdbconn.h | 4 +- storage/connect/jsonudf.cpp | 15 +- .../connect/mysql-test/connect/disabled.def | 17 +- .../connect/mysql-test/connect/r/jdbc.result | 269 +++++++ .../mysql-test/connect/r/jdbc_new.result | 214 ++++++ .../mysql-test/connect/r/jdbc_oracle.result | 70 ++ .../connect/r/jdbc_postgresql.result | 65 ++ .../mysql-test/connect/std_data/girls.txt | 5 + .../connect/mysql-test/connect/t/jdbc.test | 143 ++++ .../mysql-test/connect/t/jdbc_new.test | 179 +++++ .../mysql-test/connect/t/jdbc_oracle.test | 56 ++ .../mysql-test/connect/t/jdbc_postgresql.test | 53 ++ .../connect/mysql-test/connect/t/jdbconn.inc | 31 + .../mysql-test/connect/t/jdbconn_cleanup.inc | 6 + 23 files changed, 1153 insertions(+), 737 deletions(-) rename storage/connect/{java/ap/JdbcInterface.class => JdbcApacheInterface.class} (96%) rename storage/connect/{java/ap/JdbcInterface.java => JdbcApacheInterface.java} (99%) rename storage/connect/{java/ds/JdbcInterface.class => JdbcDSInterface.class} (96%) rename storage/connect/{java/ds/JdbcInterface.java => JdbcDSInterface.java} (99%) delete mode 100644 storage/connect/java/std/JdbcInterface.class delete mode 100644 storage/connect/java/std/JdbcInterface.java create mode 100644 storage/connect/mysql-test/connect/r/jdbc.result create mode 100644 storage/connect/mysql-test/connect/r/jdbc_new.result create mode 100644 storage/connect/mysql-test/connect/r/jdbc_oracle.result create mode 100644 storage/connect/mysql-test/connect/r/jdbc_postgresql.result create mode 100644 storage/connect/mysql-test/connect/std_data/girls.txt create mode 100644 storage/connect/mysql-test/connect/t/jdbc.test create mode 100644 storage/connect/mysql-test/connect/t/jdbc_new.test create mode 100644 storage/connect/mysql-test/connect/t/jdbc_oracle.test create mode 100644 storage/connect/mysql-test/connect/t/jdbc_postgresql.test create mode 100644 storage/connect/mysql-test/connect/t/jdbconn.inc create mode 100644 storage/connect/mysql-test/connect/t/jdbconn_cleanup.inc diff --git a/storage/connect/CMakeLists.txt b/storage/connect/CMakeLists.txt index 41c1667afffc0..254d074612a1f 100644 --- a/storage/connect/CMakeLists.txt +++ b/storage/connect/CMakeLists.txt @@ -240,7 +240,7 @@ OPTION(CONNECT_WITH_JDBC "Compile CONNECT storage engine with JDBC support" ON) IF(CONNECT_WITH_JDBC) # TODO: detect Java SDK and the presence of JDBC connectors - # TODO: Find how to compile and install the JdbcInterface.java class + # TODO: Find how to compile and install the java wrapper class # Find required libraries and include directories FIND_PACKAGE(Java) @@ -251,6 +251,8 @@ IF(CONNECT_WITH_JDBC) # SET(JDBC_LIBRARY ${JAVA_JVM_LIBRARY}) SET(CONNECT_SOURCES ${CONNECT_SOURCES} JdbcInterface.java JdbcInterface.class + JdbcDSInterface.java JdbcDSInterface.class + JdbcApacheInterface.java JdbcApacheInterface.class jdbconn.cpp tabjdbc.cpp jdbconn.h tabjdbc.h jdbccat.h) add_definitions(-DJDBC_SUPPORT) ELSE() diff --git a/storage/connect/java/ap/JdbcInterface.class b/storage/connect/JdbcApacheInterface.class similarity index 96% rename from storage/connect/java/ap/JdbcInterface.class rename to storage/connect/JdbcApacheInterface.class index 0b08b2e9217f2b281337ac952b32f20f1392fba0..acd4258e3d3ace51a01fe79b5c0dfeb65d6ac87c 100644 GIT binary patch delta 70 zcmaD|{3y^y;72r9SahZGg3E-s4($}`XB^0+c61V`)W2Q(7#J8#nDp5hm>3y&y;72rH%h56vGMzWn47(r1jJc|z|2(18A<@e Cg%5fF diff --git a/storage/connect/java/ap/JdbcInterface.java b/storage/connect/JdbcApacheInterface.java similarity index 99% rename from storage/connect/java/ap/JdbcInterface.java rename to storage/connect/JdbcApacheInterface.java index 10128cac682d2..fdbc5bff2033b 100644 --- a/storage/connect/java/ap/JdbcInterface.java +++ b/storage/connect/JdbcApacheInterface.java @@ -6,7 +6,7 @@ import org.apache.commons.dbcp2.BasicDataSource; -public class JdbcInterface { +public class JdbcApacheInterface { boolean DEBUG = false; String Errmsg = "No error"; Connection conn = null; @@ -18,11 +18,11 @@ public class JdbcInterface { static Hashtable pool = new Hashtable(); // === Constructors/finalize ========================================= - public JdbcInterface() { + public JdbcApacheInterface() { this(true); } // end of default constructor - public JdbcInterface(boolean b) { + public JdbcApacheInterface(boolean b) { DEBUG = b; } // end of constructor @@ -706,4 +706,4 @@ static public int addLibraryPath(String pathToAdd) { } // end of addLibraryPath */ -} // end of class JdbcInterface +} // end of class JdbcApacheInterface diff --git a/storage/connect/java/ds/JdbcInterface.class b/storage/connect/JdbcDSInterface.class similarity index 96% rename from storage/connect/java/ds/JdbcInterface.class rename to storage/connect/JdbcDSInterface.class index 85a52b016cb27f170e0a93bf2668727f6d7aeb11..d56c04bd81f1253bc788d6c8556fa9a65c326d15 100644 GIT binary patch delta 58 zcmZ2kx4us7)W2Q(7#J8#n4;Jjm>3!Oy;72rU4l1?TxaAE^nq|Te`K_kWEX*QjHSOR F0{}GV5~KhC delta 52 zcmZ2qx3W&;)W2Q(7#J8#n4;Jjm>3y&y;72rH;P?nWaIY%F*ko@w3TEP0y8b8zbOL% D&P@>C diff --git a/storage/connect/java/ds/JdbcInterface.java b/storage/connect/JdbcDSInterface.java similarity index 99% rename from storage/connect/java/ds/JdbcInterface.java rename to storage/connect/JdbcDSInterface.java index fae688807f941..09f545bfb7401 100644 --- a/storage/connect/java/ds/JdbcInterface.java +++ b/storage/connect/JdbcDSInterface.java @@ -11,7 +11,7 @@ import com.mysql.cj.jdbc.MysqlDataSource; import oracle.jdbc.pool.OracleDataSource; -public class JdbcInterface { +public class JdbcDSInterface { boolean DEBUG = false; String Errmsg = "No error"; Connection conn = null; @@ -23,11 +23,11 @@ public class JdbcInterface { Hashtable dst = null; // === Constructors/finalize ========================================= - public JdbcInterface() { + public JdbcDSInterface() { this(true); } // end of default constructor - public JdbcInterface(boolean b) { + public JdbcDSInterface(boolean b) { DEBUG = b; dst = new Hashtable(); } // end of constructor @@ -740,4 +740,4 @@ static public int addLibraryPath(String pathToAdd) { } // end of addLibraryPath */ -} // end of class JdbcInterface +} // end of class JdbcDSInterface diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 6ef6fa4eab3bf..c08722f254758 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -195,6 +195,7 @@ extern "C" { #if defined(JDBC_SUPPORT) char *JvmPath; char *ClassPath; + char *Wrapper; #endif // JDBC_SUPPORT #if defined(__WIN__) @@ -6874,6 +6875,12 @@ static MYSQL_SYSVAR_STR(class_path, ClassPath, "Java class path", // check_class_path, update_class_path, NULL, NULL, NULL); + +static MYSQL_SYSVAR_STR(java_wrapper, Wrapper, + PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC, + "Java wrapper class", + // check_class_path, update_class_path, + NULL, NULL, "JdbcInterface"); #endif // JDBC_SUPPORT @@ -6897,6 +6904,7 @@ static struct st_mysql_sys_var* connect_system_variables[]= { #if defined(JDBC_SUPPORT) MYSQL_SYSVAR(jvm_path), MYSQL_SYSVAR(class_path), + MYSQL_SYSVAR(java_wrapper), #endif // JDBC_SUPPORT NULL }; diff --git a/storage/connect/java/std/JdbcInterface.class b/storage/connect/java/std/JdbcInterface.class deleted file mode 100644 index 8c5ba6439f3fa073f8fa5f892e9ae84a581bc113..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15215 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 0) ? rs.getString(n) : rs.getString(name); - } catch (SQLException se) { - SetErrmsg(se); - } //end try/catch - - return null; - } // end of StringField - - public int IntField(int n, String name) { - if (rs == null) { - System.out.println("No result set"); - } else try { - return (n > 0) ? rs.getInt(n) : rs.getInt(name); - } catch (SQLException se) { - SetErrmsg(se); - } //end try/catch - - return 0; - } // end of IntField - - public long BigintField(int n, String name) { - if (rs == null) { - System.out.println("No result set"); - } else try { - BigDecimal bigDecimal = (n > 0) ? rs.getBigDecimal(n) : rs.getBigDecimal(name); - return bigDecimal != null ? bigDecimal.longValue() : 0; - } catch (SQLException se) { - SetErrmsg(se); - } //end try/catch - - return 0; - } // end of BiginttField - - public double DoubleField(int n, String name) { - if (rs == null) { - System.out.println("No result set"); - } else try { - return (n > 0) ? rs.getDouble(n) : rs.getDouble(name); - } catch (SQLException se) { - SetErrmsg(se); - } //end try/catch - - return 0.; - } // end of DoubleField - - public float FloatField(int n, String name) { - if (rs == null) { - System.out.println("No result set"); - } else try { - return (n > 0) ? rs.getFloat(n) : rs.getFloat(name); - } catch (SQLException se) { - SetErrmsg(se); - } //end try/catch - - return 0; - } // end of FloatField - - public boolean BooleanField(int n, String name) { - if (rs == null) { - System.out.println("No result set"); - } else try { - return (n > 0) ? rs.getBoolean(n) : rs.getBoolean(name); - } catch (SQLException se) { - SetErrmsg(se); - } //end try/catch - - return false; - } // end of BooleanField - - public Date DateField(int n, String name) { - if (rs == null) { - System.out.println("No result set"); - } else try { - return (n > 0) ? rs.getDate(n) : rs.getDate(name); - } catch (SQLException se) { - SetErrmsg(se); - } //end try/catch - - return null; - } // end of DateField - - public Time TimeField(int n, String name) { - if (rs == null) { - System.out.println("No result set"); - } else try { - return (n > 0) ? rs.getTime(n) : rs.getTime(name); - } catch (SQLException se) { - SetErrmsg(se); - } //end try/catch - - return null; - } // end of TimeField - - public Timestamp TimestampField(int n, String name) { - if (rs == null) { - System.out.println("No result set"); - } else try { - return (n > 0) ? rs.getTimestamp(n) : rs.getTimestamp(name); - } catch (SQLException se) { - SetErrmsg(se); - } //end try/catch - - return null; - } // end of TimestampField - - public String ObjectField(int n, String name) { - if (rs == null) { - System.out.println("No result set"); - } else try { - return (n > 0) ? rs.getObject(n).toString() : rs.getObject(name).toString(); - } catch (SQLException se) { - SetErrmsg(se); - } //end try/catch - - return null; - } // end of ObjectField - - public int GetDrivers(String[] s, int mxs) { - int n = 0; - List drivers = Collections.list(DriverManager.getDrivers()); - int size = Math.min(mxs, drivers.size()); - - for (int i = 0; i < size; i++) { - Driver driver = (Driver)drivers.get(i); - - // Get name of driver - s[n++] = driver.getClass().getName(); - - // Get version info - s[n++] = driver.getMajorVersion() + "." + driver.getMinorVersion(); - s[n++] = driver.jdbcCompliant() ? "Yes" : "No"; - s[n++] = driver.toString(); - } // endfor i - - return size; - } // end of GetDrivers - - /** - * Adds the specified path to the java library path - * from Fahd Shariff blog - * - * @param pathToAdd the path to add - static public int addLibraryPath(String pathToAdd) { - System.out.println("jpath = " + pathToAdd); - - try { - Field usrPathsField = ClassLoader.class.getDeclaredField("usr_paths"); - usrPathsField.setAccessible(true); - - //get array of paths - String[] paths = (String[])usrPathsField.get(null); - - //check if the path to add is already present - for (String path : paths) { - System.out.println("path = " + path); - - if (path.equals(pathToAdd)) - return -5; - - } // endfor path - - //add the new path - String[] newPaths = Arrays.copyOf(paths, paths.length + 1); - newPaths[paths.length] = pathToAdd; - usrPathsField.set(null, newPaths); - System.setProperty("java.library.path", - System.getProperty("java.library.path") + File.pathSeparator + pathToAdd); - Field fieldSysPath = ClassLoader.class.getDeclaredField("sys_paths"); - fieldSysPath.setAccessible(true); - fieldSysPath.set(null, null); - } catch (Exception e) { - SetErrmsg(e); - return -1; - } // end try/catch - - return 0; - } // end of addLibraryPath - */ - -} // end of class JdbcInterface diff --git a/storage/connect/jdbconn.cpp b/storage/connect/jdbconn.cpp index 23bd64bfb88d7..7a508cd989b06 100644 --- a/storage/connect/jdbconn.cpp +++ b/storage/connect/jdbconn.cpp @@ -53,8 +53,9 @@ extern "C" HINSTANCE s_hModule; // Saved module handle #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 *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. */ @@ -645,8 +646,8 @@ 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 + 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; @@ -1028,11 +1029,11 @@ int JDBConn::Open(PJPARM sop) 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 @@ -1078,7 +1079,7 @@ int JDBConn::Open(PJPARM sop) jmethodID ctor = env->GetMethodID(jdi, "", "()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); @@ -1087,7 +1088,7 @@ int JDBConn::Open(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 @@ -1328,6 +1329,7 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val) case 4: // INTEGER case 5: // SMALLINT case -6: // TINYINT + case -7: // BIT if (!gmID(g, intfldid, "IntField", "(ILjava/lang/String;)I")) val->SetValue((int)env->CallIntMethod(job, intfldid, rank, jn)); else @@ -1393,6 +1395,9 @@ 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 diff --git a/storage/connect/jdbconn.h b/storage/connect/jdbconn.h index a7744ba6ba1ac..db8a11716e5d0 100644 --- a/storage/connect/jdbconn.h +++ b/storage/connect/jdbconn.h @@ -152,8 +152,8 @@ class JDBConn : public BLOCK { 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 diff --git a/storage/connect/jsonudf.cpp b/storage/connect/jsonudf.cpp index 4cead25989601..29af7b95f66e0 100644 --- a/storage/connect/jsonudf.cpp +++ b/storage/connect/jsonudf.cpp @@ -5235,21 +5235,28 @@ my_bool envar_init(UDF_INIT *initid, UDF_ARGS *args, char *message) if (args->arg_count != 1) { strcpy(message, "Unique argument must be an environment variable name"); return true; - } else + } else { + initid->maybe_null = true; return false; + } // endif count } // end of envar_init char *envar(UDF_INIT *initid, UDF_ARGS *args, char *result, - unsigned long *res_length, char *, char *) + unsigned long *res_length, char *is_null, char *) { char *str, name[256]; int n = MY_MIN(args->lengths[0], sizeof(name) - 1); memcpy(name, args->args[0], n); name[n] = 0; - str = getenv(name); - *res_length = (str) ? strlen(str) : 0; + + if (!(str = getenv(name))) { + *res_length = 0; + *is_null = 1; + } else + *res_length = strlen(str); + return str; } // end of envar diff --git a/storage/connect/mysql-test/connect/disabled.def b/storage/connect/mysql-test/connect/disabled.def index 897c8fa741ed9..9b4570915c7ec 100644 --- a/storage/connect/mysql-test/connect/disabled.def +++ b/storage/connect/mysql-test/connect/disabled.def @@ -1 +1,16 @@ -#json_udf_bin : broken upstream in --ps +############################################################################## +# +# List the test cases that are to be disabled temporarily. +# +# Separate the test case name and the comment with ':'. +# +# : BUG# +# +# Do not use any TAB characters for whitespace. +# +############################################################################## +#json_udf_bin : broken upstream in --ps (fixed) +jdbc : Variable settings depend on machine configuration +jdbc_new : Variable settings depend on machine configuration +jdbc_oracle : Variable settings depend on machine configuration +jdbc_postgresql : Variable settings depend on machine configuration diff --git a/storage/connect/mysql-test/connect/r/jdbc.result b/storage/connect/mysql-test/connect/r/jdbc.result new file mode 100644 index 0000000000000..5e844bc990078 --- /dev/null +++ b/storage/connect/mysql-test/connect/r/jdbc.result @@ -0,0 +1,269 @@ +CREATE DATABASE connect; +USE connect; +CREATE TABLE t2 ( +id bigint not null, +msg varchar(500), +tm time, +dt date, +dtm datetime, +ts timestamp); +INSERT INTO t2 VALUES(455000000000, 'A very big number', '18:10:25', '2016-03-16', '1999-12-11 23:01:52', '2015-07-24 09:32:45'); +SELECT * FROM t2; +id msg tm dt dtm ts +455000000000 A very big number 18:10:25 2016-03-16 1999-12-11 23:01:52 2015-07-24 09:32:45 +# +# Testing JDBC connection to MySQL driver +# +USE test; +CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC TABNAME=t2 CONNECTION='jdbc:mysql://localhost:PORT/connect?user=root'; +SELECT * FROM t1; +id msg tm dt dtm ts +455000000000 A very big number 18:10:25 2016-03-16 1999-12-11 23:01:52 2015-07-24 09:32:45 +INSERT INTO t1 VALUES(786325481247, 'Hello!', '19:45:03', '1933-08-10', '1985-11-12 09:02:44', '2014-06-17 10:32:01'); +Warnings: +Note 1105 t2: 1 affected rows +SELECT * FROM t1; +id msg tm dt dtm ts +455000000000 A very big number 18:10:25 2016-03-16 1999-12-11 23:01:52 2015-07-24 09:32:45 +786325481247 Hello! 19:45:03 1933-08-09 1985-11-12 09:02:44 2014-06-17 10:32:01 +DELETE FROM t1 WHERE msg = 'Hello!'; +Warnings: +Note 1105 t2: 1 affected rows +SELECT * FROM t1; +id msg tm dt dtm ts +455000000000 A very big number 18:10:25 2016-03-16 1999-12-11 23:01:52 2015-07-24 09:32:45 +DROP TABLE t1; +# +# Testing JDBC view +# +CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC SRCDEF='select id, msg, tm, dt from t2' CONNECTION='jdbc:mysql://localhost:PORT/connect?user=root'; +SELECT * FROM t1; +id msg tm dt +455000000000 A very big number 18:10:25 2016-03-16 +SELECT msg, dt FROM t1; +msg dt +A very big number 2016-03-16 +DROP TABLE t1, connect.t2; +# +# Testing JDBC write operations +# +USE connect; +CREATE TABLE boys ( +name CHAR(12) NOT NULL, +city CHAR(11), +birth DATE DATE_FORMAT='DD/MM/YYYY', +hired DATE DATE_FORMAT='DD/MM/YYYY' flag=36) +ENGINE=CONNECT TABLE_TYPE=FIX FILE_NAME='boys.txt' ENDING=1; +SELECT * FROM boys; +name city birth hired +John Boston 1986-01-25 2010-06-02 +Henry Boston 1987-06-07 2008-04-01 +George San Jose 1981-08-10 2010-06-02 +Sam Chicago 1979-11-22 2007-10-10 +James Dallas 1992-05-13 2009-12-14 +Bill Boston 1986-09-11 2008-02-10 +USE test; +CREATE TABLE t3 ( +name CHAR(12) NOT NULL, +city CHAR(12), +birth DATE, +hired DATE); +INSERT INTO t3 VALUES('Donald','Atlanta','1999-04-01','2016-03-31'),('Mick','New York','1980-01-20','2002-09-11'); +SELECT * FROM t3; +name city birth hired +Donald Atlanta 1999-04-01 2016-03-31 +Mick New York 1980-01-20 2002-09-11 +CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC TABNAME=boys CONNECTION='jdbc:mysql://localhost:PORT/connect?user=root' OPTION_LIST='scrollable=1'; +SELECT * FROM t1; +name city birth hired +John Boston 1986-01-25 2010-06-02 +Henry Boston 1987-06-07 2008-04-01 +George San Jose 1981-08-10 2010-06-02 +Sam Chicago 1979-11-22 2007-10-10 +James Dallas 1992-05-13 2009-12-14 +Bill Boston 1986-09-11 2008-02-10 +UPDATE t1 SET city = 'Phoenix' WHERE name = 'Henry'; +Warnings: +Note 1105 boys: 1 affected rows +INSERT INTO t1 SELECT * FROM t3; +Warnings: +Note 1105 boys: 2 affected rows +INSERT INTO t1 VALUES('Tom','Seatle','2002-03-15',NULL); +Warnings: +Note 1105 boys: 1 affected rows +SELECT * FROM t1; +name city birth hired +John Boston 1986-01-25 2010-06-02 +Henry Phoenix 1987-06-07 2008-04-01 +George San Jose 1981-08-10 2010-06-02 +Sam Chicago 1979-11-22 2007-10-10 +James Dallas 1992-05-13 2009-12-14 +Bill Boston 1986-09-11 2008-02-10 +Donald Atlanta 1999-04-01 2016-03-31 +Mick New York 1980-01-20 2002-09-11 +Tom Seatle 2002-03-15 1970-01-01 +DROP TABLE t3; +# +# Testing JDBC join operations +# +CREATE TABLE t3 ( +name CHAR(9) NOT NULL, +city CHAR(12) NOT NULL, +age INT(2)) +engine=CONNECT table_type=FIX file_name='girls.txt'; +SELECT g.name, b.name, g.city FROM t3 g STRAIGHT_JOIN connect.boys b where g.city = b.city; +name name city +Mary John Boston +Susan Sam Chicago +Betty Sam Chicago +Mary Bill Boston +SELECT g.name, b.name, g.city FROM t3 g STRAIGHT_JOIN t1 b where g.city = b.city; +name name city +Mary John Boston +Susan Sam Chicago +Betty Sam Chicago +Mary Bill Boston +DROP TABLE t1, t3, connect.boys; +# +# Testing MariaDB JDBC driver +# +USE connect; +CREATE TABLE emp ( +serialno CHAR(5) NOT NULL, +name VARCHAR(12) NOT NULL FLAG=6, +sex TINYINT(1) NOT NULL, +title VARCHAR(15) NOT NULL FLAG=20, +manager CHAR(5) NOT NULL, +department CHAR(4) NOT NULL FLAG=41, +secretary CHAR(5) NOT NULL FLAG=46, +salary DOUBLE(8,2) NOT NULL FLAG=52) +ENGINE=connect TABLE_TYPE=fix FILE_NAME='employee.dat' ENDING=1; +SELECT * FROM emp; +serialno name sex title manager department secretary salary +74200 BANCROFT 2 SALESMAN 70012 0318 24888 9600.00 +02345 SMITH 1 ENGINEER 31416 2452 11111 9000.00 +78943 MERCHANT 1 SALESMAN 70012 0318 24888 8700.00 +07654 FUNNIGUY 1 ADMINISTRATOR 40567 0319 33333 8500.00 +45678 BUGHAPPY 1 PROGRAMMER 40567 0319 12345 8500.00 +34567 BIGHEAD 1 SCIENTIST 31416 2452 11111 8000.00 +77777 SHRINKY 2 ADMINISTRATOR 70012 0318 27845 7500.00 +74234 WALTER 1 ENGINEER 70012 0318 24888 7400.00 +56789 FODDERMAN 1 SALESMAN 40567 0319 12345 7000.00 +73452 TONGHO 1 ENGINEER 70012 0318 24888 6800.00 +22222 SHORTSIGHT 2 SECRETARY 87777 0021 5500.00 +55555 MESSIFUL 2 SECRETARY 40567 0319 12345 5000.50 +27845 HONEY 2 SECRETARY 70012 0318 24888 4900.00 +98765 GOOSEPEN 1 ADMINISTRATOR 07654 0319 33333 4700.00 +11111 CHERRY 2 SECRETARY 31416 2452 4500.00 +33333 MONAPENNY 2 SECRETARY 07654 0319 3800.00 +12345 KITTY 2 TYPIST 40567 0319 3000.45 +24888 PLUMHEAD 2 TYPIST 27845 0318 2800.00 +87777 STRONG 1 DIRECTOR 0021 22222 23000.00 +76543 BULLOZER 1 SALESMAN 40567 0319 12345 14800.00 +70012 WERTHER 1 DIRECTOR 87777 0318 27845 14500.00 +40567 QUINN 1 DIRECTOR 87777 0319 55555 14000.00 +31416 ORELLY 1 ENGINEER 87777 2452 11111 13400.00 +36666 BIGHORN 1 SCIENTIST 31416 2452 11111 11000.00 +00137 BROWNY 1 ENGINEER 40567 0319 12345 10500.00 +73111 WHEELFOR 1 SALESMAN 70012 0318 24888 10030.00 +00023 MARTIN 1 ENGINEER 40567 0319 12345 10000.00 +USE test; +CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC TABNAME=emp CONNECTION='jdbc:mariadb://localhost:PORT/connect?user=root'; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `serialno` char(5) NOT NULL, + `name` varchar(12) NOT NULL, + `sex` tinyint(3) NOT NULL, + `title` varchar(15) NOT NULL, + `manager` char(5) NOT NULL, + `department` char(4) NOT NULL, + `secretary` char(5) NOT NULL, + `salary` double(12,2) NOT NULL +) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='jdbc:mariadb://localhost:PORT/connect?user=root' `TABLE_TYPE`='JDBC' `TABNAME`='emp' +SELECT * FROM t1; +serialno name sex title manager department secretary salary +74200 BANCROFT 2 SALESMAN 70012 0318 24888 9600.00 +02345 SMITH 1 ENGINEER 31416 2452 11111 9000.00 +78943 MERCHANT 1 SALESMAN 70012 0318 24888 8700.00 +07654 FUNNIGUY 1 ADMINISTRATOR 40567 0319 33333 8500.00 +45678 BUGHAPPY 1 PROGRAMMER 40567 0319 12345 8500.00 +34567 BIGHEAD 1 SCIENTIST 31416 2452 11111 8000.00 +77777 SHRINKY 2 ADMINISTRATOR 70012 0318 27845 7500.00 +74234 WALTER 1 ENGINEER 70012 0318 24888 7400.00 +56789 FODDERMAN 1 SALESMAN 40567 0319 12345 7000.00 +73452 TONGHO 1 ENGINEER 70012 0318 24888 6800.00 +22222 SHORTSIGHT 2 SECRETARY 87777 0021 5500.00 +55555 MESSIFUL 2 SECRETARY 40567 0319 12345 5000.50 +27845 HONEY 2 SECRETARY 70012 0318 24888 4900.00 +98765 GOOSEPEN 1 ADMINISTRATOR 07654 0319 33333 4700.00 +11111 CHERRY 2 SECRETARY 31416 2452 4500.00 +33333 MONAPENNY 2 SECRETARY 07654 0319 3800.00 +12345 KITTY 2 TYPIST 40567 0319 3000.45 +24888 PLUMHEAD 2 TYPIST 27845 0318 2800.00 +87777 STRONG 1 DIRECTOR 0021 22222 23000.00 +76543 BULLOZER 1 SALESMAN 40567 0319 12345 14800.00 +70012 WERTHER 1 DIRECTOR 87777 0318 27845 14500.00 +40567 QUINN 1 DIRECTOR 87777 0319 55555 14000.00 +31416 ORELLY 1 ENGINEER 87777 2452 11111 13400.00 +36666 BIGHORN 1 SCIENTIST 31416 2452 11111 11000.00 +00137 BROWNY 1 ENGINEER 40567 0319 12345 10500.00 +73111 WHEELFOR 1 SALESMAN 70012 0318 24888 10030.00 +00023 MARTIN 1 ENGINEER 40567 0319 12345 10000.00 +SELECT name, title, salary FROM t1 WHERE sex = 1; +name title salary +SMITH ENGINEER 9000.00 +MERCHANT SALESMAN 8700.00 +FUNNIGUY ADMINISTRATOR 8500.00 +BUGHAPPY PROGRAMMER 8500.00 +BIGHEAD SCIENTIST 8000.00 +WALTER ENGINEER 7400.00 +FODDERMAN SALESMAN 7000.00 +TONGHO ENGINEER 6800.00 +GOOSEPEN ADMINISTRATOR 4700.00 +STRONG DIRECTOR 23000.00 +BULLOZER SALESMAN 14800.00 +WERTHER DIRECTOR 14500.00 +QUINN DIRECTOR 14000.00 +ORELLY ENGINEER 13400.00 +BIGHORN SCIENTIST 11000.00 +BROWNY ENGINEER 10500.00 +WHEELFOR SALESMAN 10030.00 +MARTIN ENGINEER 10000.00 +DROP TABLE t1, connect.emp; +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:mariadb://localhost:PORT/connect' OPTION_LIST='User=root,Execsrc=1'; +SELECT * FROM t2 WHERE command='drop table tx1'; +command number message +drop table tx1 0 Execute: java.sql.SQLSyntaxErrorException: Unknown table 'connect.tx1' +Query is : drop table tx1 +SELECT * FROM t2 WHERE command = 'create table tx1 (a int not null, b char(32), c double(8,2))'; +command number message +create table tx1 (a int not null, b char(32), c double(8,2)) 0 Affected rows +SELECT * FROM t2 WHERE command in ('insert into tx1 values(1,''The number one'',456.12)',"insert into tx1(a,b) values(2,'The number two'),(3,'The number three')"); +command number message +insert into tx1 values(1,'The number one',456.12) 1 Affected rows +insert into tx1(a,b) values(2,'The number two'),(3,'The number three') 2 Affected rows +SELECT * FROM t2 WHERE command='update tx1 set c = 3.1416 where a = 2'; +command number message +update tx1 set c = 3.1416 where a = 2 1 Affected rows +SELECT * FROM t2 WHERE command='select * from tx1'; +command number message +select * from tx1 3 Result set column number +SELECT * FROM t2 WHERE command='delete from tx1 where a = 2'; +command number message +delete from tx1 where a = 2 1 Affected rows +SELECT * FROM connect.tx1; +a b c +1 The number one 456.12 +3 The number three NULL +DROP TABLE t2; +CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC CATFUNC=tables CONNECTION='jdbc:mariadb://localhost:PORT/connect' option_list='User=root,Maxres=50'; +SELECT * FROM t1; +Table_Cat Table_Schema Table_Name Table_Type Remark +connect NULL tx1 BASE TABLE +DROP TABLE t1; +DROP TABLE connect.tx1; +DROP DATABASE connect; +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/r/jdbc_new.result b/storage/connect/mysql-test/connect/r/jdbc_new.result new file mode 100644 index 0000000000000..794ab050f05ac --- /dev/null +++ b/storage/connect/mysql-test/connect/r/jdbc_new.result @@ -0,0 +1,214 @@ +CREATE TABLE t1 (a int, b char(10)); +INSERT INTO t1 VALUES (NULL,NULL),(0,'test00'),(1,'test01'),(2,'test02'),(3,'test03'); +SELECT * FROM t1; +a b +NULL NULL +0 test00 +1 test01 +2 test02 +3 test03 +# +# Testing errors +# +CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC +CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=unknown'; +SELECT * FROM t1; +ERROR HY000: Got error 174 'Connecting: java.sql.SQLException: Access denied for user 'unknown'@'localhost' (using password: NO) rc=-2' from CONNECT +DROP TABLE t1; +CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC +CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/unknown?user=root'; +ERROR HY000: Connecting: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown database 'unknown' rc=-2 +CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC TABNAME='unknown' + CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root'; +ERROR HY000: Cannot get columns from unknown +SHOW CREATE TABLE t1; +ERROR 42S02: Table 'test.t1' doesn't exist +CREATE TABLE t1 (x int, y char(10)) ENGINE=CONNECT TABLE_TYPE=JDBC +CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root'; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `x` int(11) DEFAULT NULL, + `y` char(10) DEFAULT NULL +) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root' `TABLE_TYPE`=JDBC +SELECT * FROM t1; +ERROR HY000: Got error 174 'ExecuteQuery: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'x' in 'field list'' from CONNECT +DROP TABLE t1; +CREATE TABLE t1 (a int, b char(10)) ENGINE=CONNECT TABLE_TYPE=JDBC +CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root'; +ALTER TABLE t1 RENAME t1backup; +SELECT * FROM t1; +ERROR HY000: Got error 174 'ExecuteQuery: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'test.t1' doesn't exist' from CONNECT +ALTER TABLE t1backup RENAME t1; +DROP TABLE t1; +# +# Testing SELECT, etc. +# +CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC +CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root'; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(10) DEFAULT NULL, + `b` char(10) DEFAULT NULL +) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root' `TABLE_TYPE`='JDBC' +SELECT * FROM t1; +a b +0 NULL +0 test00 +1 test01 +2 test02 +3 test03 +DROP TABLE t1; +CREATE TABLE t1 (a int, b char(10)) ENGINE=CONNECT TABLE_TYPE=JDBC TABNAME='t1' + CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root'; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL, + `b` char(10) DEFAULT NULL +) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root' `TABLE_TYPE`=JDBC `TABNAME`='t1' +SELECT * FROM t1; +a b +0 NULL +0 test00 +1 test01 +2 test02 +3 test03 +DROP TABLE t1; +CREATE TABLE t1 (a INT NOT NULL, b CHAR(10) NOT NULL) ENGINE=CONNECT TABLE_TYPE=JDBC +CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root'; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) NOT NULL, + `b` char(10) NOT NULL +) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root' `TABLE_TYPE`=JDBC +SELECT * FROM t1; +a b +0 +0 test00 +1 test01 +2 test02 +3 test03 +DROP TABLE t1; +CREATE TABLE t1 (a char(10), b int) ENGINE=CONNECT TABLE_TYPE=JDBC +CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root'; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` char(10) DEFAULT NULL, + `b` int(11) DEFAULT NULL +) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root' `TABLE_TYPE`=JDBC +SELECT * FROM t1; +a b +0 NULL +0 0 +1 0 +2 0 +3 0 +DROP TABLE t1; +DROP TABLE t1; +# +# Testing numeric data types +# +CREATE TABLE t1 (a tinyint, b smallint, c mediumint, d int, e bigint, f float, g double, h decimal(20,5)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` tinyint(4) DEFAULT NULL, + `b` smallint(6) DEFAULT NULL, + `c` mediumint(9) DEFAULT NULL, + `d` int(11) DEFAULT NULL, + `e` bigint(20) DEFAULT NULL, + `f` float DEFAULT NULL, + `g` double DEFAULT NULL, + `h` decimal(20,5) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +INSERT INTO t1 VALUES(100,3333,41235,1234567890,235000000000,3.14159265,3.14159265,3141.59265); +CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC +CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root'; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` tinyint(3) DEFAULT NULL, + `b` smallint(5) DEFAULT NULL, + `c` int(7) DEFAULT NULL, + `d` int(10) DEFAULT NULL, + `e` bigint(19) DEFAULT NULL, + `f` double(14,0) DEFAULT NULL, + `g` double(24,0) DEFAULT NULL, + `h` decimal(27,5) DEFAULT NULL +) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root' `TABLE_TYPE`='JDBC' +SELECT * FROM t1; +a b c d e f g h +100 3333 41235 1234567890 235000000000 3 3 3141.59265 +DROP TABLE t1; +DROP TABLE t1; +# +# Testing character data types +# +CREATE TABLE t1 (a char(12), b varchar(12)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` char(12) DEFAULT NULL, + `b` varchar(12) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +INSERT INTO t1 VALUES('Welcome','Hello, World'); +SELECT * FROM t1; +a b +Welcome Hello, World +CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC +CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root'; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` char(12) DEFAULT NULL, + `b` varchar(12) DEFAULT NULL +) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root' `TABLE_TYPE`='JDBC' +SELECT * FROM t1; +a b +Welcome Hello, World +DROP TABLE t1; +DROP TABLE t1; +# +# Testing temporal data types +# +CREATE TABLE t1 (a date, b datetime, c time, d timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, e year); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` date DEFAULT NULL, + `b` datetime DEFAULT NULL, + `c` time DEFAULT NULL, + `d` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `e` year(4) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +INSERT INTO t1 VALUES('2003-05-27 10:45:23','2003-05-27 10:45:23','2003-05-27 10:45:23','2003-05-27 10:45:23','2003-05-27 10:45:23'); +Warnings: +Note 1265 Data truncated for column 'a' at row 1 +Note 1265 Data truncated for column 'c' at row 1 +Warning 1265 Data truncated for column 'e' at row 1 +SELECT * FROM t1; +a b c d e +2003-05-27 2003-05-27 10:45:23 10:45:23 2003-05-27 10:45:23 2003 +CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC +CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root'; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` date DEFAULT NULL, + `b` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `c` time DEFAULT NULL, + `d` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + `e` date DEFAULT NULL +) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root' `TABLE_TYPE`='JDBC' +SELECT * FROM t1; +a b c d e +2003-05-27 2003-05-27 10:45:23 10:45:23 2003-05-27 10:45:23 2003-01-01 +DROP TABLE t1; +DROP TABLE t1; +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/r/jdbc_oracle.result b/storage/connect/mysql-test/connect/r/jdbc_oracle.result new file mode 100644 index 0000000000000..2e36891a037e6 --- /dev/null +++ b/storage/connect/mysql-test/connect/r/jdbc_oracle.result @@ -0,0 +1,70 @@ +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:oracle:thin:@localhost:1521:xe' +OPTION_LIST='User=system,Password=manager,Execsrc=1'; +SELECT * FROM t2 WHERE command = 'drop table employee'; +command number message +drop table employee 0 Execute: java.sql.SQLSyntaxErrorException: ORA-00942: table or view does not exist + +SELECT * FROM t2 WHERE command = 'create table employee (id int not null, name varchar(32), title char(16), salary number(8,2))'; +command number message +create table employee (id int not null, name varchar(32), title char(16), salary number(8,2)) 0 Affected rows +SELECT * FROM t2 WHERE command = "insert into employee values(4567,'Johnson', 'Engineer', 12560.50)"; +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:oracle:thin:@localhost:1521:xe' +OPTION_LIST='User=system,Password=manager'; +SELECT * FROM t1 WHERE table_name='employee'; +Table_Cat Table_Schema Table_Name Table_Type Remark +NULL SYSTEM EMPLOYEE TABLE NULL +DROP TABLE t1; +CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC TABNAME='EMPLOYEE' CATFUNC=columns +CONNECTION='jdbc:oracle:thin:@localhost:1521:xe' +OPTION_LIST='User=system,Password=manager'; +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 SYSTEM EMPLOYEE ID 3 NUMBER 38 0 0 10 0 NULL +NULL SYSTEM EMPLOYEE NAME 12 VARCHAR2 32 0 0 10 1 NULL +NULL SYSTEM EMPLOYEE TITLE 1 CHAR 16 0 0 10 1 NULL +NULL SYSTEM EMPLOYEE SALARY 3 NUMBER 8 0 2 10 1 NULL +DROP TABLE t1; +CREATE SERVER 'oracle' FOREIGN DATA WRAPPER 'oracle.jdbc.driver.OracleDriver' OPTIONS ( +HOST 'jdbc:oracle:thin:@localhost:1521:xe', +DATABASE 'SYSTEM', +USER 'system', +PASSWORD 'manager', +PORT 0, +SOCKET '', +OWNER 'SYSTEM'); +CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC CONNECTION='oracle' tabname='EMPLOYEE'; +SELECT * FROM t1; +ID NAME TITLE SALARY +4567 Johnson Engineer 12560.50 +INSERT INTO t1 VALUES(6214, 'Clinton', 'Retired', NULL); +Warnings: +Note 1105 EMPLOYEE: 1 affected rows +UPDATE t1 set name='Trump' WHERE id = 4567; +Warnings: +Note 1105 EMPLOYEE: 1 affected rows +SELECT * FROM t1; +ID NAME TITLE SALARY +4567 Trump Engineer 12560.50 +6214 Clinton Retired 0.00 +DELETE FROM t1 WHERE id = 6214; +Warnings: +Note 1105 EMPLOYEE: 1 affected rows +SELECT * FROM t1; +ID NAME TITLE SALARY +4567 Trump Engineer 12560.50 +DROP TABLE t1; +SELECT * FROM t2 WHERE command = 'drop table employee'; +command number message +drop table employee 0 Affected rows +DROP TABLE t2; +DROP SERVER 'oracle'; +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/r/jdbc_postgresql.result b/storage/connect/mysql-test/connect/r/jdbc_postgresql.result new file mode 100644 index 0000000000000..6d77d79d5d3ff --- /dev/null +++ b/storage/connect/mysql-test/connect/r/jdbc_postgresql.result @@ -0,0 +1,65 @@ +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'; +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 +SELECT * FROM t2 WHERE command = 'create table employee (id int not null, name varchar(32), title char(16), salary decimal(8,2))'; +command number message +create table employee (id int not null, name varchar(32), title char(16), salary decimal(8,2)) 0 Affected rows +SELECT * FROM t2 WHERE command = "insert into employee values(4567,'Johnson', 'Engineer', 12560.50)"; +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'; +SELECT * FROM t1; +Table_Cat Table_Schema Table_Name Table_Type Remark + public employee TABLE NULL + public t1 TABLE NULL + public t2 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'; +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 +NULL public employee name 12 varchar 32 0 0 10 1 NULL +NULL public employee title 1 bpchar 16 0 0 10 1 NULL +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', +PORT 0, +SOCKET '', +OWNER 'root'); +CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC CONNECTION='postgresql/public.employee'; +SELECT * FROM t1; +id name title salary +4567 Johnson Engineer 12560.50 +INSERT INTO t1 VALUES(3126,'Smith', 'Clerk', 5230.00); +Warnings: +Note 1105 public.employee: 1 affected rows +UPDATE t1 SET salary = salary + 100.00; +Warnings: +Note 1105 public.employee: 2 affected rows +SELECT * FROM t1; +id name title salary +4567 Johnson Engineer 12660.50 +3126 Smith Clerk 5330.00 +DROP TABLE t1; +DROP SERVER 'postgresql'; +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/girls.txt b/storage/connect/mysql-test/connect/std_data/girls.txt new file mode 100644 index 0000000000000..8c883d0d847c4 --- /dev/null +++ b/storage/connect/mysql-test/connect/std_data/girls.txt @@ -0,0 +1,5 @@ +Mary Boston 25 +Nancy Palo Alto 23 +Susan Chicago 18 +Betty Chicago 32 +Anne Denver 23 diff --git a/storage/connect/mysql-test/connect/t/jdbc.test b/storage/connect/mysql-test/connect/t/jdbc.test new file mode 100644 index 0000000000000..9389747ad9c75 --- /dev/null +++ b/storage/connect/mysql-test/connect/t/jdbc.test @@ -0,0 +1,143 @@ +-- source jdbconn.inc + +let $MYSQLD_DATADIR= `select @@datadir`; +--copy_file $MTR_SUITE_DIR/std_data/girls.txt $MYSQLD_DATADIR/test/girls.txt + +let $PORT= `select @@port`; + +# +# This test is run against a local MariaDB server +# +CREATE DATABASE connect; +USE connect; +CREATE TABLE t2 ( + id bigint not null, + msg varchar(500), + tm time, + dt date, + dtm datetime, + ts timestamp); +INSERT INTO t2 VALUES(455000000000, 'A very big number', '18:10:25', '2016-03-16', '1999-12-11 23:01:52', '2015-07-24 09:32:45'); +SELECT * FROM t2; + +--echo # +--echo # Testing JDBC connection to MySQL driver +--echo # +USE test; +--replace_result $PORT PORT +--eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC TABNAME=t2 CONNECTION='jdbc:mysql://localhost:$PORT/connect?user=root' +SELECT * FROM t1; +INSERT INTO t1 VALUES(786325481247, 'Hello!', '19:45:03', '1933-08-10', '1985-11-12 09:02:44', '2014-06-17 10:32:01'); +SELECT * FROM t1; +DELETE FROM t1 WHERE msg = 'Hello!'; +SELECT * FROM t1; +DROP TABLE t1; + +--echo # +--echo # Testing JDBC view +--echo # +--replace_result $PORT PORT +--eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC SRCDEF='select id, msg, tm, dt from t2' CONNECTION='jdbc:mysql://localhost:$PORT/connect?user=root' +SELECT * FROM t1; +SELECT msg, dt FROM t1; +DROP TABLE t1, connect.t2; + +--echo # +--echo # Testing JDBC write operations +--echo # +USE connect; +--copy_file $MTR_SUITE_DIR/std_data/boys.txt $MYSQLD_DATADIR/connect/boys.txt +CREATE TABLE boys ( + name CHAR(12) NOT NULL, + city CHAR(11), + birth DATE DATE_FORMAT='DD/MM/YYYY', + hired DATE DATE_FORMAT='DD/MM/YYYY' flag=36) +ENGINE=CONNECT TABLE_TYPE=FIX FILE_NAME='boys.txt' ENDING=1; +SELECT * FROM boys; + +USE test; +CREATE TABLE t3 ( + name CHAR(12) NOT NULL, + city CHAR(12), + birth DATE, + hired DATE); +INSERT INTO t3 VALUES('Donald','Atlanta','1999-04-01','2016-03-31'),('Mick','New York','1980-01-20','2002-09-11'); +SELECT * FROM t3; + +--replace_result $PORT PORT +--eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC TABNAME=boys CONNECTION='jdbc:mysql://localhost:$PORT/connect?user=root' OPTION_LIST='scrollable=1' +SELECT * FROM t1; +UPDATE t1 SET city = 'Phoenix' WHERE name = 'Henry'; +INSERT INTO t1 SELECT * FROM t3; +INSERT INTO t1 VALUES('Tom','Seatle','2002-03-15',NULL); +SELECT * FROM t1; +DROP TABLE t3; + +--echo # +--echo # Testing JDBC join operations +--echo # +CREATE TABLE t3 ( + name CHAR(9) NOT NULL, + city CHAR(12) NOT NULL, + age INT(2)) +engine=CONNECT table_type=FIX file_name='girls.txt'; +SELECT g.name, b.name, g.city FROM t3 g STRAIGHT_JOIN connect.boys b where g.city = b.city; +SELECT g.name, b.name, g.city FROM t3 g STRAIGHT_JOIN t1 b where g.city = b.city; +DROP TABLE t1, t3, connect.boys; + +--echo # +--echo # Testing MariaDB JDBC driver +--echo # +USE connect; +--copy_file $MTR_SUITE_DIR/std_data/employee.dat $MYSQLD_DATADIR/connect/employee.dat +CREATE TABLE emp ( + serialno CHAR(5) NOT NULL, + name VARCHAR(12) NOT NULL FLAG=6, + sex TINYINT(1) NOT NULL, + title VARCHAR(15) NOT NULL FLAG=20, + manager CHAR(5) NOT NULL, + department CHAR(4) NOT NULL FLAG=41, + secretary CHAR(5) NOT NULL FLAG=46, + salary DOUBLE(8,2) NOT NULL FLAG=52) +ENGINE=connect TABLE_TYPE=fix FILE_NAME='employee.dat' ENDING=1; +SELECT * FROM emp; + +USE test; +--replace_result $PORT PORT +--eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC TABNAME=emp CONNECTION='jdbc:mariadb://localhost:$PORT/connect?user=root' +--replace_result $PORT PORT +--eval SHOW CREATE TABLE t1 +SELECT * FROM t1; +SELECT name, title, salary FROM t1 WHERE sex = 1; + +DROP TABLE t1, connect.emp; + +# +# Testing remote command execution +# +--replace_result $PORT PORT +--eval 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:mariadb://localhost:$PORT/connect' OPTION_LIST='User=root,Execsrc=1' +SELECT * FROM t2 WHERE command='drop table tx1'; +SELECT * FROM t2 WHERE command = 'create table tx1 (a int not null, b char(32), c double(8,2))'; +SELECT * FROM t2 WHERE command in ('insert into tx1 values(1,''The number one'',456.12)',"insert into tx1(a,b) values(2,'The number two'),(3,'The number three')"); +SELECT * FROM t2 WHERE command='update tx1 set c = 3.1416 where a = 2'; +SELECT * FROM t2 WHERE command='select * from tx1'; +SELECT * FROM t2 WHERE command='delete from tx1 where a = 2'; +SELECT * FROM connect.tx1; +DROP TABLE t2; + +--replace_result $PORT PORT +--eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC CATFUNC=tables CONNECTION='jdbc:mariadb://localhost:$PORT/connect' option_list='User=root,Maxres=50' +SELECT * FROM t1; +DROP TABLE t1; +DROP TABLE connect.tx1; + +# +# Clean up +# +--remove_file $MYSQLD_DATADIR/connect/boys.txt +--remove_file $MYSQLD_DATADIR/connect/employee.dat +DROP DATABASE connect; +--remove_file $MYSQLD_DATADIR/test/girls.txt + +-- source jdbconn_cleanup.inc diff --git a/storage/connect/mysql-test/connect/t/jdbc_new.test b/storage/connect/mysql-test/connect/t/jdbc_new.test new file mode 100644 index 0000000000000..33ec1b343cc88 --- /dev/null +++ b/storage/connect/mysql-test/connect/t/jdbc_new.test @@ -0,0 +1,179 @@ +# +# This test is run against a remote MySQL server +# +connect (master,127.0.0.1,root,,test,$MASTER_MYPORT,); +connect (slave,127.0.0.1,root,,test,$SLAVE_MYPORT,); +connection master; + +-- source jdbconn.inc + +connection slave; +CREATE TABLE t1 (a int, b char(10)); +INSERT INTO t1 VALUES (NULL,NULL),(0,'test00'),(1,'test01'),(2,'test02'),(3,'test03'); +SELECT * FROM t1; + +--echo # +--echo # Testing errors +--echo # +connection master; + +# Bad user name +# Suppress "mysql_real_connect failed:" (printed in _DEBUG build) +--replace_result $SLAVE_MYPORT SLAVE_PORT "mysql_real_connect failed: " "" +eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC + CONNECTION='jdbc:mysql://127.0.0.1:$SLAVE_MYPORT/test?user=unknown'; +--error ER_GET_ERRMSG +SELECT * FROM t1; +DROP TABLE t1; + +# Bad database name +--replace_result $SLAVE_MYPORT SLAVE_PORT "mysql_real_connect failed: " "" +--error ER_UNKNOWN_ERROR +eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC + CONNECTION='jdbc:mysql://127.0.0.1:$SLAVE_MYPORT/unknown?user=root'; + +# Bad table name +--replace_result $SLAVE_MYPORT SLAVE_PORT +--error ER_UNKNOWN_ERROR +eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC TABNAME='unknown' + CONNECTION='jdbc:mysql://127.0.0.1:$SLAVE_MYPORT/test?user=root'; +--error ER_NO_SUCH_TABLE +SHOW CREATE TABLE t1; + +# Bad column name +--replace_result $SLAVE_MYPORT SLAVE_PORT +eval CREATE TABLE t1 (x int, y char(10)) ENGINE=CONNECT TABLE_TYPE=JDBC + CONNECTION='jdbc:mysql://127.0.0.1:$SLAVE_MYPORT/test?user=root'; +--replace_result $SLAVE_MYPORT SLAVE_PORT +SHOW CREATE TABLE t1; +--error ER_GET_ERRMSG +SELECT * FROM t1; +DROP TABLE t1; + +# The remote table disappeared +--replace_result $SLAVE_MYPORT SLAVE_PORT +eval CREATE TABLE t1 (a int, b char(10)) ENGINE=CONNECT TABLE_TYPE=JDBC + CONNECTION='jdbc:mysql://127.0.0.1:$SLAVE_MYPORT/test?user=root'; + +connection slave; +ALTER TABLE t1 RENAME t1backup; + +connection master; +--error ER_GET_ERRMSG +SELECT * FROM t1; + +connection slave; +ALTER TABLE t1backup RENAME t1; + +connection master; +DROP TABLE t1; + +--echo # +--echo # Testing SELECT, etc. +--echo # + +# Automatic table structure +--replace_result $SLAVE_MYPORT SLAVE_PORT +eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC + CONNECTION='jdbc:mysql://127.0.0.1:$SLAVE_MYPORT/test?user=root'; +--replace_result $SLAVE_MYPORT SLAVE_PORT +SHOW CREATE TABLE t1; +SELECT * FROM t1; +DROP TABLE t1; + +# Explicit table structure +--replace_result $SLAVE_MYPORT SLAVE_PORT +eval CREATE TABLE t1 (a int, b char(10)) ENGINE=CONNECT TABLE_TYPE=JDBC TABNAME='t1' + CONNECTION='jdbc:mysql://127.0.0.1:$SLAVE_MYPORT/test?user=root'; +--replace_result $SLAVE_MYPORT SLAVE_PORT +SHOW CREATE TABLE t1; +SELECT * FROM t1; +DROP TABLE t1; + +# Explicit table structure: remote NULL, local NOT NULL +--replace_result $SLAVE_MYPORT SLAVE_PORT +eval CREATE TABLE t1 (a INT NOT NULL, b CHAR(10) NOT NULL) ENGINE=CONNECT TABLE_TYPE=JDBC + CONNECTION='jdbc:mysql://127.0.0.1:$SLAVE_MYPORT/test?user=root'; +--replace_result $SLAVE_MYPORT SLAVE_PORT +SHOW CREATE TABLE t1; +SELECT * FROM t1; +DROP TABLE t1; + +# Explicit table structure with wrong column types +--replace_result $SLAVE_MYPORT SLAVE_PORT +eval CREATE TABLE t1 (a char(10), b int) ENGINE=CONNECT TABLE_TYPE=JDBC + CONNECTION='jdbc:mysql://127.0.0.1:$SLAVE_MYPORT/test?user=root'; +--replace_result $SLAVE_MYPORT SLAVE_PORT +SHOW CREATE TABLE t1; +SELECT * FROM t1; +DROP TABLE t1; + +connection slave; +DROP TABLE t1; + +--echo # +--echo # Testing numeric data types +--echo # + +# TODO: mediumint is converted to int, float is converted to double, decimal is converted to double +CREATE TABLE t1 (a tinyint, b smallint, c mediumint, d int, e bigint, f float, g double, h decimal(20,5)); +SHOW CREATE TABLE t1; +INSERT INTO t1 VALUES(100,3333,41235,1234567890,235000000000,3.14159265,3.14159265,3141.59265); + +connection master; +--replace_result $SLAVE_MYPORT SLAVE_PORT +eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC + CONNECTION='jdbc:mysql://127.0.0.1:$SLAVE_MYPORT/test?user=root'; +--replace_result $SLAVE_MYPORT SLAVE_PORT +SHOW CREATE TABLE t1; +SELECT * FROM t1; +DROP TABLE t1; + +connection slave; +DROP TABLE t1; + +--echo # +--echo # Testing character data types +--echo # + +CREATE TABLE t1 (a char(12), b varchar(12)); +SHOW CREATE TABLE t1; +INSERT INTO t1 VALUES('Welcome','Hello, World'); +SELECT * FROM t1; + +connection master; +--replace_result $SLAVE_MYPORT SLAVE_PORT +eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC + CONNECTION='jdbc:mysql://127.0.0.1:$SLAVE_MYPORT/test?user=root'; +--replace_result $SLAVE_MYPORT SLAVE_PORT +SHOW CREATE TABLE t1; +SELECT * FROM t1; +DROP TABLE t1; + +connection slave; +DROP TABLE t1; + +--echo # +--echo # Testing temporal data types +--echo # + +CREATE TABLE t1 (a date, b datetime, c time, d timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, e year); +SHOW CREATE TABLE t1; +INSERT INTO t1 VALUES('2003-05-27 10:45:23','2003-05-27 10:45:23','2003-05-27 10:45:23','2003-05-27 10:45:23','2003-05-27 10:45:23'); +SELECT * FROM t1; + +connection master; +--replace_result $SLAVE_MYPORT SLAVE_PORT +eval CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC + CONNECTION='jdbc:mysql://127.0.0.1:$SLAVE_MYPORT/test?user=root'; +--replace_result $SLAVE_MYPORT SLAVE_PORT +SHOW CREATE TABLE t1; +SELECT * FROM t1; +DROP TABLE t1; + +connection slave; +DROP TABLE t1; + +connection master; +-- source jdbconn_cleanup.inc + diff --git a/storage/connect/mysql-test/connect/t/jdbc_oracle.test b/storage/connect/mysql-test/connect/t/jdbc_oracle.test new file mode 100644 index 0000000000000..10cb7a7b77dba --- /dev/null +++ b/storage/connect/mysql-test/connect/t/jdbc_oracle.test @@ -0,0 +1,56 @@ +-- source jdbconn.inc + +# +# This test is run against Oracle driver +# +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:oracle:thin:@localhost:1521:xe' +OPTION_LIST='User=system,Password=manager,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 number(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:oracle:thin:@localhost:1521:xe' +OPTION_LIST='User=system,Password=manager'; +SELECT * FROM t1 WHERE table_name='employee'; +DROP TABLE t1; + +CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC TABNAME='EMPLOYEE' CATFUNC=columns +CONNECTION='jdbc:oracle:thin:@localhost:1521:xe' +OPTION_LIST='User=system,Password=manager'; +SELECT * FROM t1; +DROP TABLE t1; + +# +# Test connecting via a Federated server +# +CREATE SERVER 'oracle' FOREIGN DATA WRAPPER 'oracle.jdbc.driver.OracleDriver' OPTIONS ( +HOST 'jdbc:oracle:thin:@localhost:1521:xe', +DATABASE 'SYSTEM', +USER 'system', +PASSWORD 'manager', +PORT 0, +SOCKET '', +OWNER 'SYSTEM'); + +CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC CONNECTION='oracle' tabname='EMPLOYEE'; +SELECT * FROM t1; +INSERT INTO t1 VALUES(6214, 'Clinton', 'Retired', NULL); +UPDATE t1 set name='Trump' WHERE id = 4567; +SELECT * FROM t1; +DELETE FROM t1 WHERE id = 6214; +SELECT * FROM t1; +DROP TABLE t1; +SELECT * FROM t2 WHERE command = 'drop table employee'; +DROP TABLE t2; +DROP SERVER 'oracle'; + +# +# Clean up +# + +-- source jdbconn_cleanup.inc diff --git a/storage/connect/mysql-test/connect/t/jdbc_postgresql.test b/storage/connect/mysql-test/connect/t/jdbc_postgresql.test new file mode 100644 index 0000000000000..1041ef468d7b8 --- /dev/null +++ b/storage/connect/mysql-test/connect/t/jdbc_postgresql.test @@ -0,0 +1,53 @@ +-- source jdbconn.inc + +# +# This test is run against Postgresql driver +# +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'; +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'; +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'; +SELECT * FROM t1; +DROP TABLE t1; + +# +# Test connecting via a Federated server +# +CREATE SERVER 'postgresql' FOREIGN DATA WRAPPER 'postgresql' OPTIONS ( +HOST 'localhost', +DATABASE 'mtr', +USER 'mtr', +PASSWORD 'mtr', +PORT 0, +SOCKET '', +OWNER 'root'); + +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; +SELECT * FROM t1; +DROP TABLE t1; +DROP SERVER 'postgresql'; +SELECT * FROM t2 WHERE command='drop table employee'; +DROP TABLE t2; + +# +# Clean up +# +-- source jdbconn_cleanup.inc diff --git a/storage/connect/mysql-test/connect/t/jdbconn.inc b/storage/connect/mysql-test/connect/t/jdbconn.inc new file mode 100644 index 0000000000000..0bac0b35fc420 --- /dev/null +++ b/storage/connect/mysql-test/connect/t/jdbconn.inc @@ -0,0 +1,31 @@ +--source include/not_embedded.inc + +--disable_query_log +--error 0,ER_UNKNOWN_ERROR +CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC CATFUNC=drivers; +if (!`SELECT count(*) FROM INFORMATION_SCHEMA.TABLES + WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1' + AND ENGINE='CONNECT' + AND (CREATE_OPTIONS LIKE "%`table_type`='JDBC'%" OR CREATE_OPTIONS LIKE '%`table_type`=JDBC%')`) +{ + Skip Need Java support; +} +DROP TABLE t1; + +# This is specific and explains why this test is disabled. +# You should edit this file to reflect what is the required files location on your machine. +# This is the path to the JVM library (dll or so) +SET GLOBAL connect_jvm_path='C:\\Program Files\\Java\\jdk1.8.0_77\\jre\\bin\\client'; + +# The complete class path send when creating the Java Virtual Machine is, in that order: +# 1 - The current directory. +# 2 - The paths of the connect_class_path global variable. +# 3 - The paths of the CLASSPATH environment variable. +# These are the paths to the needed classes or jar files. The Apache ones are only for the JdbcApacheInterface wrapper. +SET GLOBAL connect_class_path='E:\\MariaDB-10.1\\Connect\\storage\\connect;E:\\MariaDB-10.1\\Connect\\sql\\data\\postgresql-9.4.1208.jar;E:\\Oracle\\ojdbc6.jar;E:\\Apache\\commons-dbcp2-2.1.1\\commons-dbcp2-2.1.1.jar;E:\\Apache\\commons-pool2-2.4.2\\commons-pool2-2.4.2.jar;E:\\Apache\\commons-logging-1.2\\commons-logging-1.2.jar'; + +# On my machine, paths to the JDK classes and to the MySQL and MariaDB drivers are defined in the CLASSPATH environment variable +#CREATE FUNCTION envar RETURNS STRING SONAME 'ha_connect.dll'; +#SELECT envar('CLASSPATH'); + +--enable_query_log diff --git a/storage/connect/mysql-test/connect/t/jdbconn_cleanup.inc b/storage/connect/mysql-test/connect/t/jdbconn_cleanup.inc new file mode 100644 index 0000000000000..48e321495aded --- /dev/null +++ b/storage/connect/mysql-test/connect/t/jdbconn_cleanup.inc @@ -0,0 +1,6 @@ +--disable_warnings +#DROP FUNCTION envar; +SET GLOBAL connect_jvm_path=NULL; +SET GLOBAL connect_class_path=NULL; +SET GLOBAL time_zone = SYSTEM; +--enable_warnings From 613680a04179f0f5832832e82c429832aab322f5 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Thu, 2 Jun 2016 22:11:08 +0200 Subject: [PATCH 16/18] - Fix MDEV-10111 Reconize unsigned integers when creating tables via srcdef modified: storage/connect/ha_connect.cc modified: storage/connect/myconn.cpp - Fix MDEV-10136 crash on SELECT jsonget_string(NULL, 'a') modified: storage/connect/jsonudf.cpp - Assert longjmp initialized when suballocating modified: storage/connect/plugutil.c - Avoid crash in MakeRecord when table->vcol_set isnull (trace > 1) modified: storage/connect/ha_connect.cc --- storage/connect/ha_connect.cc | 4 ++-- storage/connect/jsonudf.cpp | 2 +- storage/connect/myconn.cpp | 8 ++++++-- storage/connect/plugutil.c | 4 +++- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index c08722f254758..45ad4a484e15d 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -1961,7 +1961,7 @@ int ha_connect::MakeRecord(char *buf) if (trace > 1) htrc("Maps: read=%08X write=%08X vcol=%08X defr=%08X defw=%08X\n", *table->read_set->bitmap, *table->write_set->bitmap, - *table->vcol_set->bitmap, + (table->vcol_set) ? *table->vcol_set->bitmap : 0, *table->def_read_set.bitmap, *table->def_write_set.bitmap); // Avoid asserts in field::store() for columns that are not updated @@ -5619,7 +5619,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd, len= crp->Length; dec= crp->Prec; flg= crp->Flag; - v= crp->Var; + v= (crp->Kdata->IsUnsigned()) ? 'U' : crp->Var; tm= (crp->Kdata->IsNullable()) ? 0 : NOT_NULL_FLAG; if (!len && typ == TYPE_STRING) diff --git a/storage/connect/jsonudf.cpp b/storage/connect/jsonudf.cpp index 29af7b95f66e0..0bc964d73510e 100644 --- a/storage/connect/jsonudf.cpp +++ b/storage/connect/jsonudf.cpp @@ -1433,7 +1433,7 @@ static my_bool CheckMemory(PGLOBAL g, UDF_INIT *initid, UDF_ARGS *args, uint n, char *p = args->args[0]; // Is this a file name? - if (!strchr("[{ \t\r\n", *p) && (len = GetFileLength(p))) + if (p && !strchr("[{ \t\r\n", *p) && (len = GetFileLength(p))) ml += len * (M + 1); else ml += args->lengths[0] * M; diff --git a/storage/connect/myconn.cpp b/storage/connect/myconn.cpp index e9bd64cf8e677..b844d68e1cd66 100644 --- a/storage/connect/myconn.cpp +++ b/storage/connect/myconn.cpp @@ -901,8 +901,12 @@ PQRYRES MYSQLC::GetResult(PGLOBAL g, bool pdb) if (fld->flags & NOT_NULL_FLAG) crp->Nulls = NULL; else { - crp->Nulls = (char*)PlugSubAlloc(g, NULL, m_Rows); - memset(crp->Nulls, ' ', m_Rows); + if (m_Rows) { + crp->Nulls = (char*)PlugSubAlloc(g, NULL, m_Rows); + memset(crp->Nulls, ' ', m_Rows); + } // endif m_Rows + + crp->Kdata->SetNullable(true); } // endelse fld->flags } // endfor fld diff --git a/storage/connect/plugutil.c b/storage/connect/plugutil.c index 38e28a171b22a..2551b60334979 100644 --- a/storage/connect/plugutil.c +++ b/storage/connect/plugutil.c @@ -516,7 +516,9 @@ void *PlugSubAlloc(PGLOBAL g, void *memp, size_t size) if (trace) htrc("PlugSubAlloc: %s\n", g->Message); - longjmp(g->jumper[g->jump_level], 1); + /* Nothing we can do if longjmp is not initialized. */ + assert(g->jump_level >= 0); + longjmp(g->jumper[g->jump_level], 1); } /* endif size OS32 code */ /*********************************************************************/ From 74009534a10c1d30a85309cfca13a4cea37f0667 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Mon, 13 Jun 2016 12:58:24 +0200 Subject: [PATCH 17/18] - Possibly fix MDEV-10179 Reset remote tables when re-opening modified: storage/connect/tabtbl.cpp - Add trace and make m_Stmt conditional modified: storage/connect/myconn.cpp modified: storage/connect/myconn.h - Protect trace from null string (for Linux) modified: storage/connect/tabcol.cpp - Record error changes modified: storage/connect/mysql-test/connect/r/jdbc_new.result - Typo modified: storage/connect/jdbconn.cpp modified: storage/connect/jsonudf.cpp --- storage/connect/jdbconn.cpp | 2 +- storage/connect/jsonudf.cpp | 4 ++-- storage/connect/myconn.cpp | 24 +++++++++++++++---- storage/connect/myconn.h | 6 +++-- .../mysql-test/connect/r/jdbc_new.result | 10 ++++---- storage/connect/tabcol.cpp | 2 +- storage/connect/tabtbl.cpp | 8 +++++++ 7 files changed, 41 insertions(+), 15 deletions(-) diff --git a/storage/connect/jdbconn.cpp b/storage/connect/jdbconn.cpp index 7a508cd989b06..a8c0b193dcd32 100644 --- a/storage/connect/jdbconn.cpp +++ b/storage/connect/jdbconn.cpp @@ -2081,7 +2081,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/jsonudf.cpp b/storage/connect/jsonudf.cpp index 0bc964d73510e..e94d38179264b 100644 --- a/storage/connect/jsonudf.cpp +++ b/storage/connect/jsonudf.cpp @@ -1,6 +1,6 @@ /****************** jsonudf C++ Program Source Code File (.CPP) ******************/ -/* PROGRAM NAME: jsonudf Version 1.3 */ -/* (C) Copyright to the author Olivier BERTRAND 2015 */ +/* PROGRAM NAME: jsonudf Version 1.4 */ +/* (C) Copyright to the author Olivier BERTRAND 2015-2016 */ /* This program are the JSON User Defined Functions . */ /*********************************************************************************/ diff --git a/storage/connect/myconn.cpp b/storage/connect/myconn.cpp index b844d68e1cd66..644ca019e4ac0 100644 --- a/storage/connect/myconn.cpp +++ b/storage/connect/myconn.cpp @@ -5,7 +5,7 @@ /* */ /* COPYRIGHT: */ /* ---------- */ -/* (C) Copyright to the author Olivier BERTRAND 2007-2015 */ +/* (C) Copyright to the author Olivier BERTRAND 2007-2016 */ /* */ /* WHAT THIS PROGRAM DOES: */ /* ----------------------- */ @@ -401,8 +401,10 @@ PQRYRES SrcColumns(PGLOBAL g, const char *host, const char *db, MYSQLC::MYSQLC(void) { m_DB = NULL; - m_Stmt = NULL; - m_Res = NULL; +#if defined (MYSQL_PREPARED_STATEMENTS) + m_Stmt = NULL; +#endif // MYSQL_PREPARED_STATEMENTS + m_Res = NULL; m_Rows = -1; m_Row = NULL; m_Fields = -1; @@ -444,7 +446,10 @@ int MYSQLC::Open(PGLOBAL g, const char *host, const char *db, return RC_FX; } // endif m_DB - // Removed to do like FEDERATED do + if (trace) + htrc("MYSQLC Open: m_DB=%.4X size=%d\n", m_DB, (int)sizeof(*m_DB)); + + // Removed to do like FEDERATED do //mysql_options(m_DB, MYSQL_READ_DEFAULT_GROUP, "client-mariadb"); mysql_options(m_DB, MYSQL_OPT_USE_REMOTE_CONNECTION, NULL); mysql_options(m_DB, MYSQL_OPT_CONNECT_TIMEOUT, &cto); @@ -701,6 +706,11 @@ int MYSQLC::ExecSQL(PGLOBAL g, const char *query, int *w) } else { m_Fields = mysql_num_fields(m_Res); m_Rows = (!m_Use) ? (int)mysql_num_rows(m_Res) : 0; + + if (trace) + htrc("ExecSQL: m_Res=%.4X size=%d m_Fields=%d m_Rows=%d\n", + m_Res, sizeof(*m_Res), m_Fields, m_Rows); + } // endif m_Res } else { @@ -1017,7 +1027,11 @@ int MYSQLC::ExecSQLcmd(PGLOBAL g, const char *query, int *w) void MYSQLC::Close(void) { FreeResult(); - mysql_close(m_DB); + + if (trace) + htrc("MYSQLC Close: m_DB=%.4X\n", m_DB); + + mysql_close(m_DB); m_DB = NULL; } // end of Close diff --git a/storage/connect/myconn.h b/storage/connect/myconn.h index 79f095f5c939c..9ebd37527a6d9 100644 --- a/storage/connect/myconn.h +++ b/storage/connect/myconn.h @@ -90,8 +90,10 @@ class DllItem MYSQLC { // Members MYSQL *m_DB; // The return from MySQL connection - MYSQL_STMT *m_Stmt; // Prepared statement handle - MYSQL_RES *m_Res; // Points to MySQL Result +#if defined (MYSQL_PREPARED_STATEMENTS) + MYSQL_STMT *m_Stmt; // Prepared statement handle +#endif // MYSQL_PREPARED_STATEMENTS + MYSQL_RES *m_Res; // Points to MySQL Result MYSQL_ROW m_Row; // Point to current row int m_Rows; // The number of rows of the result int N; diff --git a/storage/connect/mysql-test/connect/r/jdbc_new.result b/storage/connect/mysql-test/connect/r/jdbc_new.result index 794ab050f05ac..e5356edd5d812 100644 --- a/storage/connect/mysql-test/connect/r/jdbc_new.result +++ b/storage/connect/mysql-test/connect/r/jdbc_new.result @@ -17,7 +17,7 @@ ERROR HY000: Got error 174 'Connecting: java.sql.SQLException: Access denied for DROP TABLE t1; CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/unknown?user=root'; -ERROR HY000: Connecting: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown database 'unknown' rc=-2 +ERROR HY000: Connecting: java.sql.SQLSyntaxErrorException: Unknown database 'unknown' rc=-2 CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC TABNAME='unknown' CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root'; ERROR HY000: Cannot get columns from unknown @@ -32,13 +32,15 @@ t1 CREATE TABLE `t1` ( `y` char(10) DEFAULT NULL ) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root' `TABLE_TYPE`=JDBC SELECT * FROM t1; -ERROR HY000: Got error 174 'ExecuteQuery: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'x' in 'field list'' from CONNECT +ERROR HY000: Got error 174 'ExecuteQuery: java.sql.SQLSyntaxErrorException: Unknown column 'x' in 'field list' +Query is : SELECT x, y FROM t1' from CONNECT DROP TABLE t1; CREATE TABLE t1 (a int, b char(10)) ENGINE=CONNECT TABLE_TYPE=JDBC CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root'; ALTER TABLE t1 RENAME t1backup; SELECT * FROM t1; -ERROR HY000: Got error 174 'ExecuteQuery: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'test.t1' doesn't exist' from CONNECT +ERROR HY000: Got error 174 'ExecuteQuery: java.sql.SQLSyntaxErrorException: Table 'test.t1' doesn't exist +Query is : SELECT a, b FROM t1' from CONNECT ALTER TABLE t1backup RENAME t1; DROP TABLE t1; # @@ -206,7 +208,7 @@ t1 CREATE TABLE `t1` ( ) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='jdbc:mysql://127.0.0.1:SLAVE_PORT/test?user=root' `TABLE_TYPE`='JDBC' SELECT * FROM t1; a b c d e -2003-05-27 2003-05-27 10:45:23 10:45:23 2003-05-27 10:45:23 2003-01-01 +2003-05-27 2003-05-27 10:45:23 10:45:23 2003-05-27 10:45:23 1970-01-01 DROP TABLE t1; DROP TABLE t1; SET GLOBAL connect_jvm_path=NULL; diff --git a/storage/connect/tabcol.cpp b/storage/connect/tabcol.cpp index 662c0b514cf73..fde1baa631724 100644 --- a/storage/connect/tabcol.cpp +++ b/storage/connect/tabcol.cpp @@ -50,7 +50,7 @@ XTAB::XTAB(PTABLE tp) : Name(tp->Name) Qualifier = tp->Qualifier; if (trace) - htrc(" making copy TABLE %s %s\n", Name, Srcdef); + htrc(" making copy TABLE %s %s\n", Name, SVP(Srcdef)); } // end of XTAB constructor diff --git a/storage/connect/tabtbl.cpp b/storage/connect/tabtbl.cpp index 36849146746d0..e3baf7c3da5b0 100644 --- a/storage/connect/tabtbl.cpp +++ b/storage/connect/tabtbl.cpp @@ -569,6 +569,9 @@ pthread_handler_t ThreadOpen(void *p) if (!my_thread_init()) { set_current_thd(cmp->Thd); + if (trace) + htrc("ThreadOpen: Thd=%d\n", cmp->Thd); + // Try to open the connection if (!cmp->Tap->GetTo_Tdb()->OpenDB(cmp->G)) { cmp->Ready = true; @@ -604,9 +607,14 @@ void TDBTBM::ResetDB(void) if (colp->GetAmType() == TYPE_AM_TABID) colp->COLBLK::Reset(); + // Local tables for (PTABLE tabp = Tablist; tabp; tabp = tabp->GetNext()) ((PTDBASE)tabp->GetTo_Tdb())->ResetDB(); + // Remote tables + for (PTBMT tp = Tmp; tp; tp = tp->Next) + ((PTDBASE)tp->Tap->GetTo_Tdb())->ResetDB(); + Tdbp = (Tablist) ? (PTDBASE)Tablist->GetTo_Tdb() : NULL; Crp = 0; } // end of ResetDB From 7e64b079680b5f0f1e1cb735e3c83e45e96ec0e3 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Mon, 20 Jun 2016 16:37:57 +0200 Subject: [PATCH 18/18] - Add column pattern and table type argument to catalog tables modified: storage/connect/ha_connect.cc modified: storage/connect/jdbconn.cpp modified: storage/connect/jdbconn.h modified: storage/connect/odbccat.h modified: storage/connect/odbconn.cpp modified: storage/connect/tabjdbc.cpp modified: storage/connect/tabjdbc.h modified: storage/connect/tabodbc.cpp modified: storage/connect/tabodbc.h - Avoid longjump in AllocCatInfo functions modified: storage/connect/jdbconn.cpp modified: storage/connect/jdbconn.h modified: storage/connect/odbconn.cpp - Change GetColumns error return value from 0 to -1 modified: storage/connect/JdbcInterface.class modified: storage/connect/JdbcInterface.java --- storage/connect/JdbcInterface.class | Bin 15215 -> 15215 bytes storage/connect/JdbcInterface.java | 2 +- storage/connect/ha_connect.cc | 2 +- storage/connect/jdbconn.cpp | 49 ++++++++-------------------- storage/connect/jdbconn.h | 6 ++-- storage/connect/odbccat.h | 2 +- storage/connect/odbconn.cpp | 4 +-- storage/connect/tabjdbc.cpp | 20 ++++++++++-- storage/connect/tabjdbc.h | 9 +++-- storage/connect/tabodbc.cpp | 27 +++++++++++---- storage/connect/tabodbc.h | 15 ++++++--- 11 files changed, 75 insertions(+), 61 deletions(-) diff --git a/storage/connect/JdbcInterface.class b/storage/connect/JdbcInterface.class index 8c5ba6439f3fa073f8fa5f892e9ae84a581bc113..51a0e69bad5dd6bf018c28a4ff0d618f68f3d65b 100644 GIT binary patch delta 19 bcmaD~_P%VxG<7B>+sSjump_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 - -//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 *)); + 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 -//for (i = 0; i < n; i++) -// cap->Vlen[i] = (SQLLEN *)PlugSubAlloc(g, NULL, m * sizeof(SQLLEN)); - -//cap->Status = (UWORD *)PlugSubAlloc(g, NULL, m * sizeof(UWORD)); - -fin: - g->jump_level--; return cap; } // end of AllocCatInfo @@ -291,7 +269,8 @@ PQRYRES JDBCColumns(PGLOBAL g, char *db, char *table, char *colpat, if (!(cap = AllocCatInfo(g, CAT_COL, db, table, qrp))) return NULL; - cap->Pat = (PUCHAR)colpat; + // Colpat cannot be null or empty for some drivers + cap->Pat = (colpat && *colpat) ? colpat : "%"; /************************************************************************/ /* Now get the results into blocks. */ @@ -402,7 +381,7 @@ PQRYRES JDBCTables(PGLOBAL g, char *db, char *tabpat, char *tabtyp, 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); @@ -1931,9 +1910,9 @@ bool JDBConn::SetParam(JDBCCOL *colp) { PGLOBAL& g = m_G; // void *buffer; - int i; + int i, ncol; PSZ fnc = "Unknown"; - uint n, ncol; + uint n; short len, tp; int crow = 0; PQRYRES qrp = cap->Qrp; @@ -1956,9 +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) { diff --git a/storage/connect/jdbconn.h b/storage/connect/jdbconn.h index db8a11716e5d0..abec3919e524a 100644 --- a/storage/connect/jdbconn.h +++ b/storage/connect/jdbconn.h @@ -46,9 +46,9 @@ 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 *); diff --git a/storage/connect/odbccat.h b/storage/connect/odbccat.h index 1b5febadd3aeb..3b729bcb4bb26 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 8b2626fe96249..f1f8327f91aa4 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 f507e3df3ea3a..e6782e71753a7 100644 --- a/storage/connect/tabjdbc.cpp +++ b/storage/connect/tabjdbc.cpp @@ -96,7 +96,7 @@ bool ExactInfo(void); /***********************************************************************/ JDBCDEF::JDBCDEF(void) { - 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; @@ -237,7 +237,13 @@ bool JDBCDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) Tabcat = GetStringCatInfo(g, "Catalog", Tabcat); Tabschema = GetStringCatInfo(g, "Dbname", NULL); Tabschema = GetStringCatInfo(g, "Schema", Tabschema); - Tabtype = GetStringCatInfo(g, "Tabtype", NULL); + + 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); @@ -1787,12 +1793,20 @@ PQRYRES TDBJTB::GetResult(PGLOBAL g) /* --------------------------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, 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 537276a6a7f1b..cf5e662c9d114 100644 --- a/storage/connect/tabjdbc.h +++ b/storage/connect/tabjdbc.h @@ -26,6 +26,7 @@ class DllExport JDBCDEF : public TABDEF { /* Logical table description */ friend class TDBXJDC; friend class TDBJDRV; friend class TDBJTB; + friend class TDBJDBCL; public: // Constructor JDBCDEF(void); @@ -58,6 +59,7 @@ class DllExport JDBCDEF : public TABDEF { /* Logical table description */ 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 */ @@ -317,14 +319,15 @@ class TDBJTB : public TDBJDRV { 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 5fd0534210dac..8a43ca9e591e1 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 6440dee830d3c..aa6592d8abfbd 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