mirror of
https://github.com/MariaDB/server.git
synced 2025-03-22 23:18:38 +01:00
- Fix MDEV-15429 CONNECT engine JDBC handling Postgresql UUID type
Also handle Postgresql sending type VARCHAR for TEXT column and setting length to b x7FFFFFF when the length is unknown. modified: storage/connect/Client.java modified: storage/connect/JavaWrappers.jar modified: storage/connect/JdbcInterface.java modified: storage/connect/PostgresqlInterface.java modified: storage/connect/global.h modified: storage/connect/ha_connect.cc modified: storage/connect/jdbconn.cpp modified: storage/connect/jdbconn.h modified: storage/connect/mysql-test/connect/r/jdbc_postgresql.result modified: storage/connect/mysql-test/connect/t/jdbc_postgresql.test modified: storage/connect/mysql-test/connect/t/jdbconn.inc modified: storage/connect/plgdbsem.h modified: storage/connect/tabjdbc.cpp modified: storage/connect/tabjdbc.h
This commit is contained in:
parent
175ce0e7f5
commit
f9cf2df077
15 changed files with 383 additions and 171 deletions
|
@ -1,9 +1,13 @@
|
|||
|
||||
package wrappers;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.Console;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.sql.Date;
|
||||
import java.sql.Time;
|
||||
import java.sql.Timestamp;
|
||||
|
||||
public class Client {
|
||||
static boolean DEBUG = true;
|
||||
|
@ -58,6 +62,9 @@ public class Client {
|
|||
String query;
|
||||
System.out.println("Successfully connected to " + parms[1]);
|
||||
|
||||
s = jdi.GetQuoteString();
|
||||
System.out.println("Qstr = '" + s + "'");
|
||||
|
||||
while ((query = getLine("Query: ", false)) != null) {
|
||||
n = jdi.Execute(query);
|
||||
System.out.println("Returned n = " + n);
|
||||
|
@ -79,7 +86,11 @@ public class Client {
|
|||
private static void PrintResult(int ncol) {
|
||||
// Get result set meta data
|
||||
int i;
|
||||
Date date = new Date(0);
|
||||
Time time = new Time(0);
|
||||
Timestamp tsp = new Timestamp(0);
|
||||
String columnName;
|
||||
Object job;
|
||||
|
||||
// Get the column names; column indices start from 1
|
||||
for (i = 1; i <= ncol; i++) {
|
||||
|
@ -112,6 +123,7 @@ public class Client {
|
|||
case java.sql.Types.VARCHAR:
|
||||
case java.sql.Types.LONGVARCHAR:
|
||||
case java.sql.Types.CHAR:
|
||||
case 1111:
|
||||
System.out.print(jdi.StringField(i, null));
|
||||
break;
|
||||
case java.sql.Types.INTEGER:
|
||||
|
@ -120,14 +132,17 @@ public class Client {
|
|||
case java.sql.Types.BIGINT:
|
||||
System.out.print(jdi.BigintField(i, null));
|
||||
break;
|
||||
case java.sql.Types.TIMESTAMP:
|
||||
System.out.print(jdi.TimestampField(i, null));
|
||||
break;
|
||||
case java.sql.Types.TIME:
|
||||
System.out.print(jdi.TimeField(i, null));
|
||||
time.setTime((long)jdi.TimeField(i, null) * 1000);
|
||||
System.out.print(time);
|
||||
break;
|
||||
case java.sql.Types.DATE:
|
||||
System.out.print(jdi.DateField(i, null));
|
||||
date.setTime((long)jdi.DateField(i, null) * 1000);
|
||||
System.out.print(date);
|
||||
break;
|
||||
case java.sql.Types.TIMESTAMP:
|
||||
tsp.setTime((long)jdi.TimestampField(i, null) * 1000);
|
||||
System.out.print(tsp);
|
||||
break;
|
||||
case java.sql.Types.SMALLINT:
|
||||
System.out.print(jdi.IntField(i, null));
|
||||
|
@ -141,6 +156,8 @@ public class Client {
|
|||
case java.sql.Types.BOOLEAN:
|
||||
System.out.print(jdi.BooleanField(i, null));
|
||||
default:
|
||||
job = jdi.ObjectField(i, null);
|
||||
System.out.print(job.toString());
|
||||
break;
|
||||
} // endswitch Type
|
||||
|
||||
|
|
Binary file not shown.
|
@ -1,10 +1,22 @@
|
|||
package wrappers;
|
||||
|
||||
import java.math.*;
|
||||
import java.sql.*;
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.Date;
|
||||
import java.sql.Driver;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.ResultSetMetaData;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.sql.Time;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.Collections;
|
||||
import java.util.Hashtable;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
|
@ -223,6 +235,24 @@ public class JdbcInterface {
|
|||
|
||||
} // end of SetTimestampParm
|
||||
|
||||
public void SetUuidParm(int i, String s) {
|
||||
try {
|
||||
UUID uuid;
|
||||
|
||||
if (s == null)
|
||||
uuid = null;
|
||||
else if (s.isEmpty())
|
||||
uuid = UUID.randomUUID();
|
||||
else
|
||||
uuid = UUID.fromString(s);
|
||||
|
||||
pstmt.setObject(i, uuid);
|
||||
} catch (Exception e) {
|
||||
SetErrmsg(e);
|
||||
} // end try/catch
|
||||
|
||||
} // end of SetUuidParm
|
||||
|
||||
public int SetNullParm(int i, int typ) {
|
||||
int rc = 0;
|
||||
|
||||
|
@ -481,6 +511,8 @@ public class JdbcInterface {
|
|||
System.out.println("Executing query '" + query + "'");
|
||||
|
||||
try {
|
||||
if (rs != null)
|
||||
rs.close();
|
||||
rs = stmt.executeQuery(query);
|
||||
rsmd = rs.getMetaData();
|
||||
ncol = rsmd.getColumnCount();
|
||||
|
@ -708,7 +740,7 @@ public class JdbcInterface {
|
|||
return 0;
|
||||
} // end of TimestampField
|
||||
|
||||
public Object ObjectField(int n, String name) {
|
||||
public Object ObjectField(int n, String name) {
|
||||
if (rs == null) {
|
||||
System.out.println("No result set");
|
||||
} else try {
|
||||
|
@ -720,6 +752,22 @@ public class JdbcInterface {
|
|||
return null;
|
||||
} // end of ObjectField
|
||||
|
||||
public String UuidField(int n, String name) {
|
||||
Object job;
|
||||
|
||||
if (rs == null) {
|
||||
System.out.println("No result set");
|
||||
} else
|
||||
try {
|
||||
job = (n > 0) ? rs.getObject(n) : rs.getObject(name);
|
||||
return job.toString();
|
||||
} catch (SQLException se) {
|
||||
SetErrmsg(se);
|
||||
} // end try/catch
|
||||
|
||||
return null;
|
||||
} // end of UuidField
|
||||
|
||||
public int GetDrivers(String[] s, int mxs) {
|
||||
int n = 0;
|
||||
List<Driver> drivers = Collections.list(DriverManager.getDrivers());
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
package wrappers;
|
||||
|
||||
import java.sql.*;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Hashtable;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.postgresql.jdbc2.optional.PoolingDataSource;
|
||||
|
||||
public class PostgresqlInterface extends JdbcInterface {
|
||||
|
@ -19,7 +20,7 @@ public class PostgresqlInterface extends JdbcInterface {
|
|||
|
||||
} // end of constructor
|
||||
|
||||
@Override
|
||||
@Override
|
||||
public int JdbcConnect(String[] parms, int fsize, boolean scrollable) {
|
||||
int rc = 0;
|
||||
String url = parms[1];
|
||||
|
|
|
@ -220,7 +220,6 @@ DllExport BOOL PlugIsAbsolutePath(LPCSTR path);
|
|||
DllExport bool AllocSarea(PGLOBAL, uint);
|
||||
DllExport void FreeSarea(PGLOBAL);
|
||||
DllExport BOOL PlugSubSet(PGLOBAL, void *, uint);
|
||||
void *PlugSubAlloc(PGLOBAL, void *, size_t); // Does throw
|
||||
DllExport char *PlugDup(PGLOBAL g, const char *str);
|
||||
DllExport void *MakePtr(void *, OFFSET);
|
||||
DllExport void htrc(char const *fmt, ...);
|
||||
|
@ -231,4 +230,9 @@ DllExport uint GetTraceValue(void);
|
|||
} // extern "C"
|
||||
#endif
|
||||
|
||||
/***********************************************************************/
|
||||
/* Non exported routine declarations. */
|
||||
/***********************************************************************/
|
||||
void *PlugSubAlloc(PGLOBAL, void *, size_t); // Does throw
|
||||
|
||||
/*-------------------------- End of Global.H --------------------------*/
|
||||
|
|
|
@ -174,9 +174,9 @@
|
|||
#define JSONMAX 10 // JSON Default max grp size
|
||||
|
||||
extern "C" {
|
||||
char version[]= "Version 1.06.0006 February 02, 2018";
|
||||
char version[]= "Version 1.06.0007 March 11, 2018";
|
||||
#if defined(__WIN__)
|
||||
char compver[]= "Version 1.06.0006 " __DATE__ " " __TIME__;
|
||||
char compver[]= "Version 1.06.0007 " __DATE__ " " __TIME__;
|
||||
char slash= '\\';
|
||||
#else // !__WIN__
|
||||
char slash= '/';
|
||||
|
@ -288,11 +288,16 @@ static MYSQL_THDVAR_SET(
|
|||
0, // def (NO)
|
||||
&xtrace_typelib); // typelib
|
||||
|
||||
// Getting exact info values
|
||||
// Getting exact info values
|
||||
static MYSQL_THDVAR_BOOL(exact_info, PLUGIN_VAR_RQCMDARG,
|
||||
"Getting exact info values",
|
||||
NULL, NULL, 0);
|
||||
|
||||
// Enabling cond_push
|
||||
static MYSQL_THDVAR_BOOL(cond_push, PLUGIN_VAR_RQCMDARG,
|
||||
"Enabling cond_push",
|
||||
NULL, NULL, 1); // YES by default
|
||||
|
||||
/**
|
||||
Temporary file usage:
|
||||
no: Not using temporary file
|
||||
|
@ -427,6 +432,7 @@ handlerton *connect_hton= NULL;
|
|||
uint GetTraceValue(void)
|
||||
{return (uint)(connect_hton ? THDVAR(current_thd, xtrace) : 0);}
|
||||
bool ExactInfo(void) {return THDVAR(current_thd, exact_info);}
|
||||
bool CondPushEnabled(void) {return THDVAR(current_thd, cond_push);}
|
||||
USETEMP UseTemp(void) {return (USETEMP)THDVAR(current_thd, use_tempfile);}
|
||||
int GetConvSize(void) {return THDVAR(current_thd, conv_size);}
|
||||
TYPCONV GetTypeConv(void) {return (TYPCONV)THDVAR(current_thd, type_conv);}
|
||||
|
@ -3196,7 +3202,7 @@ const COND *ha_connect::cond_push(const COND *cond)
|
|||
{
|
||||
DBUG_ENTER("ha_connect::cond_push");
|
||||
|
||||
if (tdbp) {
|
||||
if (tdbp && CondPushEnabled()) {
|
||||
PGLOBAL& g= xp->g;
|
||||
AMT tty= tdbp->GetAmType();
|
||||
bool x= (tty == TYPE_AM_MYX || tty == TYPE_AM_XDBC);
|
||||
|
@ -7243,7 +7249,8 @@ static struct st_mysql_sys_var* connect_system_variables[]= {
|
|||
#if defined(JAVA_SUPPORT) || defined(CMGO_SUPPORT)
|
||||
MYSQL_SYSVAR(enable_mongo),
|
||||
#endif // JAVA_SUPPORT || CMGO_SUPPORT
|
||||
NULL
|
||||
MYSQL_SYSVAR(cond_push),
|
||||
NULL
|
||||
};
|
||||
|
||||
maria_declare_plugin(connect)
|
||||
|
@ -7256,10 +7263,10 @@ maria_declare_plugin(connect)
|
|||
PLUGIN_LICENSE_GPL,
|
||||
connect_init_func, /* Plugin Init */
|
||||
connect_done_func, /* Plugin Deinit */
|
||||
0x0106, /* version number (1.05) */
|
||||
0x0107, /* version number (1.05) */
|
||||
NULL, /* status variables */
|
||||
connect_system_variables, /* system variables */
|
||||
"1.06.0006", /* string version */
|
||||
"1.06.0007", /* string version */
|
||||
MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
|
||||
}
|
||||
maria_declare_plugin_end;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/************ Jdbconn C++ Functions Source Code File (.CPP) ************/
|
||||
/* Name: JDBCONN.CPP Version 1.1 */
|
||||
/* Name: JDBCONN.CPP Version 1.2 */
|
||||
/* */
|
||||
/* (C) Copyright to the author Olivier BERTRAND 2016-2017 */
|
||||
/* (C) Copyright to the author Olivier BERTRAND 2016-2018 */
|
||||
/* */
|
||||
/* This file contains the JDBC connection classes functions. */
|
||||
/***********************************************************************/
|
||||
|
@ -116,10 +116,26 @@ int TranslateJDBCType(int stp, char *tn, int prec, int& len, char& v)
|
|||
return TYPE_ERROR;
|
||||
else
|
||||
len = MY_MIN(abs(len), GetConvSize());
|
||||
|
||||
// Pass through
|
||||
case 12: // VARCHAR
|
||||
if (tn && !stricmp(tn, "TEXT"))
|
||||
// Postgresql returns 12 for TEXT
|
||||
if (GetTypeConv() == TPC_NO)
|
||||
return TYPE_ERROR;
|
||||
|
||||
// Postgresql can return this
|
||||
if (len == 0x7FFFFFFF)
|
||||
len = GetConvSize();
|
||||
|
||||
// Pass through
|
||||
case -9: // NVARCHAR (unicode)
|
||||
// Postgresql can return this when size is unknown
|
||||
if (len == 0x7FFFFFFF)
|
||||
len = GetConvSize();
|
||||
|
||||
v = 'V';
|
||||
// Pass through
|
||||
case 1: // CHAR
|
||||
case -15: // NCHAR (unicode)
|
||||
case -8: // ROWID
|
||||
|
@ -171,6 +187,14 @@ int TranslateJDBCType(int stp, char *tn, int prec, int& len, char& v)
|
|||
case -5: // BIGINT
|
||||
type = TYPE_BIGINT;
|
||||
break;
|
||||
case 1111: // UNKNOWN or UUID
|
||||
if (!tn || !stricmp(tn, "UUID")) {
|
||||
type = TYPE_STRING;
|
||||
len = 36;
|
||||
break;
|
||||
} // endif tn
|
||||
|
||||
// Pass through
|
||||
case 0: // NULL
|
||||
case -2: // BINARY
|
||||
case -4: // LONGVARBINARY
|
||||
|
@ -192,6 +216,104 @@ int TranslateJDBCType(int stp, char *tn, int prec, int& len, char& v)
|
|||
return type;
|
||||
} // end of TranslateJDBCType
|
||||
|
||||
/***********************************************************************/
|
||||
/* A helper class to split an optionally qualified table name into */
|
||||
/* components. */
|
||||
/* These formats are understood: */
|
||||
/* "CatalogName.SchemaName.TableName" */
|
||||
/* "SchemaName.TableName" */
|
||||
/* "TableName" */
|
||||
/***********************************************************************/
|
||||
class SQLQualifiedName {
|
||||
static const uint max_parts = 3; // Catalog.Schema.Table
|
||||
MYSQL_LEX_STRING m_part[max_parts];
|
||||
char m_buf[512];
|
||||
|
||||
void lex_string_set(MYSQL_LEX_STRING *S, char *str, size_t length)
|
||||
{
|
||||
S->str = str;
|
||||
S->length = length;
|
||||
} // end of lex_string_set
|
||||
|
||||
void lex_string_shorten_down(MYSQL_LEX_STRING *S, size_t offs)
|
||||
{
|
||||
DBUG_ASSERT(offs <= S->length);
|
||||
S->str += offs;
|
||||
S->length -= offs;
|
||||
} // end of lex_string_shorten_down
|
||||
|
||||
/*********************************************************************/
|
||||
/* Find the rightmost '.' delimiter and return the length */
|
||||
/* of the qualifier, including the rightmost '.' delimier. */
|
||||
/* For example, for the string {"a.b.c",5} it will return 4, */
|
||||
/* which is the length of the qualifier "a.b." */
|
||||
/*********************************************************************/
|
||||
size_t lex_string_find_qualifier(MYSQL_LEX_STRING *S)
|
||||
{
|
||||
size_t i;
|
||||
for (i = S->length; i > 0; i--)
|
||||
{
|
||||
if (S->str[i - 1] == '.')
|
||||
{
|
||||
S->str[i - 1] = '\0';
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
} // end of lex_string_find_qualifier
|
||||
|
||||
public:
|
||||
/*********************************************************************/
|
||||
/* Initialize to the given optionally qualified name. */
|
||||
/* NULL pointer in "name" is supported. */
|
||||
/* name qualifier has precedence over schema. */
|
||||
/*********************************************************************/
|
||||
SQLQualifiedName(JCATPARM *cap)
|
||||
{
|
||||
const char *name = (const char *)cap->Tab;
|
||||
char *db = (char *)cap->DB;
|
||||
size_t len, i;
|
||||
|
||||
// Initialize the parts
|
||||
for (i = 0; i < max_parts; i++)
|
||||
lex_string_set(&m_part[i], NULL, 0);
|
||||
|
||||
if (name) {
|
||||
// Initialize the first (rightmost) part
|
||||
lex_string_set(&m_part[0], m_buf,
|
||||
strmake(m_buf, name, sizeof(m_buf) - 1) - m_buf);
|
||||
|
||||
// Initialize the other parts, if exist.
|
||||
for (i = 1; i < max_parts; i++) {
|
||||
if (!(len = lex_string_find_qualifier(&m_part[i - 1])))
|
||||
break;
|
||||
|
||||
lex_string_set(&m_part[i], m_part[i - 1].str, len - 1);
|
||||
lex_string_shorten_down(&m_part[i - 1], len);
|
||||
} // endfor i
|
||||
|
||||
} // endif name
|
||||
|
||||
// If it was not specified, set schema as the passed db name
|
||||
if (db && !m_part[1].length)
|
||||
lex_string_set(&m_part[1], db, strlen(db));
|
||||
|
||||
} // end of SQLQualifiedName
|
||||
|
||||
char *ptr(uint i)
|
||||
{
|
||||
DBUG_ASSERT(i < max_parts);
|
||||
return (char *)(m_part[i].length ? m_part[i].str : NULL);
|
||||
} // end of ptr
|
||||
|
||||
size_t length(uint i)
|
||||
{
|
||||
DBUG_ASSERT(i < max_parts);
|
||||
return m_part[i].length;
|
||||
} // end of length
|
||||
|
||||
}; // end of class SQLQualifiedName
|
||||
|
||||
/***********************************************************************/
|
||||
/* Allocate the structure used to refer to the result set. */
|
||||
/***********************************************************************/
|
||||
|
@ -519,7 +641,7 @@ JDBConn::JDBConn(PGLOBAL g, PCSZ wrapper) : JAVAConn(g, wrapper)
|
|||
xqid = xuid = xid = grs = readid = fetchid = typid = errid = nullptr;
|
||||
prepid = xpid = pcid = nullptr;
|
||||
chrfldid = intfldid = dblfldid = fltfldid = bigfldid = nullptr;
|
||||
objfldid = datfldid = timfldid = tspfldid = nullptr;
|
||||
objfldid = datfldid = timfldid = tspfldid = uidfldid = nullptr;
|
||||
DiscFunc = "JdbcDisconnect";
|
||||
m_Ncol = 0;
|
||||
m_Aff = 0;
|
||||
|
@ -535,12 +657,84 @@ JDBConn::JDBConn(PGLOBAL g, PCSZ wrapper) : JAVAConn(g, wrapper)
|
|||
m_IDQuoteChar[1] = 0;
|
||||
} // end of JDBConn
|
||||
|
||||
//JDBConn::~JDBConn()
|
||||
// {
|
||||
//if (Connected())
|
||||
// EndCom();
|
||||
/***********************************************************************/
|
||||
/* Search for UUID columns. */
|
||||
/***********************************************************************/
|
||||
bool JDBConn::SetUUID(PGLOBAL g, PTDBJDBC tjp)
|
||||
{
|
||||
int ncol, ctyp;
|
||||
bool brc = true;
|
||||
PCSZ fnc = "GetColumns";
|
||||
PCOL colp;
|
||||
JCATPARM *cap;
|
||||
//jint jtyp;
|
||||
jboolean rc = false;
|
||||
jobjectArray parms;
|
||||
jmethodID catid = nullptr;
|
||||
|
||||
// } // end of ~JDBConn
|
||||
if (gmID(g, catid, fnc, "([Ljava/lang/String;)I"))
|
||||
return true;
|
||||
else if (gmID(g, intfldid, "IntField", "(ILjava/lang/String;)I"))
|
||||
return true;
|
||||
else if (gmID(g, readid, "ReadNext", "()I"))
|
||||
return true;
|
||||
|
||||
cap = AllocCatInfo(g, JCAT_COL, tjp->Schema, tjp->TableName, NULL);
|
||||
SQLQualifiedName name(cap);
|
||||
|
||||
// Build the java string array
|
||||
parms = env->NewObjectArray(4, env->FindClass("java/lang/String"), NULL);
|
||||
env->SetObjectArrayElement(parms, 0, env->NewStringUTF(name.ptr(2)));
|
||||
env->SetObjectArrayElement(parms, 1, env->NewStringUTF(name.ptr(1)));
|
||||
env->SetObjectArrayElement(parms, 2, env->NewStringUTF(name.ptr(0)));
|
||||
|
||||
for (colp = tjp->GetColumns(); colp; colp = colp->GetNext()) {
|
||||
env->SetObjectArrayElement(parms, 3, env->NewStringUTF(colp->GetName()));
|
||||
ncol = env->CallIntMethod(job, catid, parms);
|
||||
|
||||
if (Check(ncol)) {
|
||||
sprintf(g->Message, "%s: %s", fnc, Msg);
|
||||
goto err;
|
||||
} // endif Check
|
||||
|
||||
rc = env->CallBooleanMethod(job, readid);
|
||||
|
||||
if (Check(rc)) {
|
||||
sprintf(g->Message, "ReadNext: %s", Msg);
|
||||
goto err;
|
||||
} else if (rc == 0) {
|
||||
sprintf(g->Message, "table %s does not exist", tjp->TableName);
|
||||
goto err;
|
||||
} // endif rc
|
||||
|
||||
// Returns 666 is case of error
|
||||
//jtyp = env->CallIntMethod(job, typid, 5, nullptr);
|
||||
|
||||
//if (Check((jtyp == 666) ? -1 : 1)) {
|
||||
// sprintf(g->Message, "Getting jtyp: %s", Msg);
|
||||
// goto err;
|
||||
//} // endif ctyp
|
||||
|
||||
ctyp = (int)env->CallIntMethod(job, intfldid, 5, nullptr);
|
||||
|
||||
if (Check(ctyp)) {
|
||||
sprintf(g->Message, "Getting ctyp: %s", Msg);
|
||||
goto err;
|
||||
} // endif ctyp
|
||||
|
||||
if (ctyp == 1111)
|
||||
((PJDBCCOL)colp)->uuid = true;
|
||||
|
||||
} // endfor colp
|
||||
|
||||
// All is Ok
|
||||
brc = false;
|
||||
|
||||
err:
|
||||
// Not used anymore
|
||||
env->DeleteLocalRef(parms);
|
||||
return brc;
|
||||
} // end of SetUUID
|
||||
|
||||
/***********************************************************************/
|
||||
/* Utility routine. */
|
||||
|
@ -770,6 +964,7 @@ int JDBConn::Rewind(PCSZ sql)
|
|||
/***********************************************************************/
|
||||
void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val)
|
||||
{
|
||||
const char *field;
|
||||
PGLOBAL& g = m_G;
|
||||
jint ctyp;
|
||||
jstring cn, jn = nullptr;
|
||||
|
@ -793,6 +988,11 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val)
|
|||
if (!gmID(g, objfldid, "ObjectField", "(ILjava/lang/String;)Ljava/lang/Object;")) {
|
||||
jb = env->CallObjectMethod(job, objfldid, (jint)rank, jn);
|
||||
|
||||
if (Check(0)) {
|
||||
sprintf(g->Message, "Getting jp: %s", Msg);
|
||||
throw (int)TYPE_AM_JDBC;
|
||||
} // endif Check
|
||||
|
||||
if (jb == nullptr) {
|
||||
val->Reset();
|
||||
val->SetNull(true);
|
||||
|
@ -818,7 +1018,7 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val)
|
|||
cn = nullptr;
|
||||
|
||||
if (cn) {
|
||||
const char *field = env->GetStringUTFChars(cn, (jboolean)false);
|
||||
field = env->GetStringUTFChars(cn, (jboolean)false);
|
||||
val->SetValue_psz((PSZ)field);
|
||||
} else
|
||||
val->Reset();
|
||||
|
@ -885,6 +1085,19 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val)
|
|||
break;
|
||||
case java.sql.Types.BOOLEAN:
|
||||
System.out.print(jdi.BooleanField(i)); */
|
||||
case 1111: // UUID
|
||||
if (!gmID(g, uidfldid, "UuidField", "(ILjava/lang/String;)Ljava/lang/String;"))
|
||||
cn = (jstring)env->CallObjectMethod(job, uidfldid, (jint)rank, jn);
|
||||
else
|
||||
cn = nullptr;
|
||||
|
||||
if (cn) {
|
||||
const char *field = env->GetStringUTFChars(cn, (jboolean)false);
|
||||
val->SetValue_psz((PSZ)field);
|
||||
} else
|
||||
val->Reset();
|
||||
|
||||
break;
|
||||
case 0: // NULL
|
||||
val->SetNull(true);
|
||||
// passthru
|
||||
|
@ -1055,7 +1268,14 @@ bool JDBConn::SetParam(JDBCCOL *colp)
|
|||
if (gmID(g, setid, "SetNullParm", "(II)I"))
|
||||
return true;
|
||||
|
||||
jrc = env->CallIntMethod(job, setid, i, (jint)GetJDBCType(val->GetType()));
|
||||
jrc = env->CallIntMethod(job, setid, i,
|
||||
(colp->uuid ? 1111 : (jint)GetJDBCType(val->GetType())));
|
||||
} else if (colp->uuid) {
|
||||
if (gmID(g, setid, "SetUuidParm", "(ILjava/lang/String;)V"))
|
||||
return true;
|
||||
|
||||
jst = env->NewStringUTF(val->GetCharValue());
|
||||
env->CallVoidMethod(job, setid, i, jst);
|
||||
} else switch (val->GetType()) {
|
||||
case TYPE_STRING:
|
||||
if (gmID(g, setid, "SetStringParm", "(ILjava/lang/String;)V"))
|
||||
|
@ -1274,105 +1494,6 @@ bool JDBConn::SetParam(JDBCCOL *colp)
|
|||
return qrp;
|
||||
} // end of GetMetaData
|
||||
|
||||
/***********************************************************************/
|
||||
/* A helper class to split an optionally qualified table name into */
|
||||
/* components. */
|
||||
/* These formats are understood: */
|
||||
/* "CatalogName.SchemaName.TableName" */
|
||||
/* "SchemaName.TableName" */
|
||||
/* "TableName" */
|
||||
/***********************************************************************/
|
||||
class SQLQualifiedName
|
||||
{
|
||||
static const uint max_parts= 3; // Catalog.Schema.Table
|
||||
MYSQL_LEX_STRING m_part[max_parts];
|
||||
char m_buf[512];
|
||||
|
||||
void lex_string_set(MYSQL_LEX_STRING *S, char *str, size_t length)
|
||||
{
|
||||
S->str= str;
|
||||
S->length= length;
|
||||
} // end of lex_string_set
|
||||
|
||||
void lex_string_shorten_down(MYSQL_LEX_STRING *S, size_t offs)
|
||||
{
|
||||
DBUG_ASSERT(offs <= S->length);
|
||||
S->str+= offs;
|
||||
S->length-= offs;
|
||||
} // end of lex_string_shorten_down
|
||||
|
||||
/*********************************************************************/
|
||||
/* Find the rightmost '.' delimiter and return the length */
|
||||
/* of the qualifier, including the rightmost '.' delimier. */
|
||||
/* For example, for the string {"a.b.c",5} it will return 4, */
|
||||
/* which is the length of the qualifier "a.b." */
|
||||
/*********************************************************************/
|
||||
size_t lex_string_find_qualifier(MYSQL_LEX_STRING *S)
|
||||
{
|
||||
size_t i;
|
||||
for (i= S->length; i > 0; i--)
|
||||
{
|
||||
if (S->str[i - 1] == '.')
|
||||
{
|
||||
S->str[i - 1]= '\0';
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
} // end of lex_string_find_qualifier
|
||||
|
||||
public:
|
||||
/*********************************************************************/
|
||||
/* Initialize to the given optionally qualified name. */
|
||||
/* NULL pointer in "name" is supported. */
|
||||
/* name qualifier has precedence over schema. */
|
||||
/*********************************************************************/
|
||||
SQLQualifiedName(JCATPARM *cap)
|
||||
{
|
||||
const char *name = (const char *)cap->Tab;
|
||||
char *db = (char *)cap->DB;
|
||||
size_t len, i;
|
||||
|
||||
// Initialize the parts
|
||||
for (i = 0; i < max_parts; i++)
|
||||
lex_string_set(&m_part[i], NULL, 0);
|
||||
|
||||
if (name) {
|
||||
// Initialize the first (rightmost) part
|
||||
lex_string_set(&m_part[0], m_buf,
|
||||
strmake(m_buf, name, sizeof(m_buf) - 1) - m_buf);
|
||||
|
||||
// Initialize the other parts, if exist.
|
||||
for (i= 1; i < max_parts; i++) {
|
||||
if (!(len= lex_string_find_qualifier(&m_part[i - 1])))
|
||||
break;
|
||||
|
||||
lex_string_set(&m_part[i], m_part[i - 1].str, len - 1);
|
||||
lex_string_shorten_down(&m_part[i - 1], len);
|
||||
} // endfor i
|
||||
|
||||
} // endif name
|
||||
|
||||
// If it was not specified, set schema as the passed db name
|
||||
if (db && !m_part[1].length)
|
||||
lex_string_set(&m_part[1], db, strlen(db));
|
||||
|
||||
} // end of SQLQualifiedName
|
||||
|
||||
char *ptr(uint i)
|
||||
{
|
||||
DBUG_ASSERT(i < max_parts);
|
||||
return (char *)(m_part[i].length ? m_part[i].str : NULL);
|
||||
} // end of ptr
|
||||
|
||||
size_t length(uint i)
|
||||
{
|
||||
DBUG_ASSERT(i < max_parts);
|
||||
return m_part[i].length;
|
||||
} // end of length
|
||||
|
||||
}; // end of class SQLQualifiedName
|
||||
|
||||
/***********************************************************************/
|
||||
/* Allocate recset and call SQLTables, SQLColumns or SQLPrimaryKeys. */
|
||||
/***********************************************************************/
|
||||
|
|
|
@ -29,6 +29,7 @@ public:
|
|||
// Attributes
|
||||
public:
|
||||
char *GetQuoteChar(void) { return m_IDQuoteChar; }
|
||||
bool SetUUID(PGLOBAL g, PTDBJDBC tjp);
|
||||
virtual int GetMaxValue(int infotype);
|
||||
|
||||
public:
|
||||
|
@ -58,13 +59,6 @@ public:
|
|||
|
||||
protected:
|
||||
// Members
|
||||
#if 0
|
||||
JavaVM *jvm; // Pointer to the JVM (Java Virtual Machine)
|
||||
JNIEnv *env; // Pointer to native interface
|
||||
jclass jdi; // Pointer to the java wrapper class
|
||||
jobject job; // The java wrapper class object
|
||||
jmethodID errid; // The GetErrmsg method ID
|
||||
#endif // 0
|
||||
jmethodID xqid; // The ExecuteQuery method ID
|
||||
jmethodID xuid; // The ExecuteUpdate method ID
|
||||
jmethodID xid; // The Execute method ID
|
||||
|
@ -84,8 +78,7 @@ protected:
|
|||
jmethodID timfldid; // The TimeField method ID
|
||||
jmethodID tspfldid; // The TimestampField method ID
|
||||
jmethodID bigfldid; // The BigintField method ID
|
||||
// PCSZ Msg;
|
||||
// PCSZ m_Wrap;
|
||||
jmethodID uidfldid; // The UuidField method ID
|
||||
char m_IDQuoteChar[2];
|
||||
PCSZ m_Pwd;
|
||||
int m_Ncol;
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
SET GLOBAL connect_class_path='C:/MariaDB-10.2/MariaDB/storage/connect/mysql-test/connect/std_data/JavaWrappers.jar;C:/Jconnectors/postgresql-42.2.1.jar';
|
||||
CREATE TABLE t2 (
|
||||
command varchar(128) not null,
|
||||
number int(5) not null flag=1,
|
||||
message varchar(255) flag=2)
|
||||
ENGINE=CONNECT TABLE_TYPE=JDBC CONNECTION='jdbc:postgresql://localhost/mtr'
|
||||
OPTION_LIST='User=mtr,Password=mtr,Schema=public,Execsrc=1';
|
||||
ENGINE=CONNECT TABLE_TYPE=JDBC
|
||||
CONNECTION='jdbc:postgresql://localhost/test?user=postgres&password=tinono'
|
||||
OPTION_LIST='Execsrc=1';
|
||||
SELECT * FROM t2 WHERE command='drop table employee';
|
||||
command number message
|
||||
drop table employee 0 Execute: org.postgresql.util.PSQLException: ERREUR: la table « employee » n'existe pas
|
||||
|
@ -14,17 +16,18 @@ SELECT * FROM t2 WHERE command = "insert into employee values(4567,'Johnson', 'E
|
|||
command number message
|
||||
insert into employee values(4567,'Johnson', 'Engineer', 12560.50) 1 Affected rows
|
||||
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC CATFUNC=tables
|
||||
CONNECTION='jdbc:postgresql://localhost/mtr'
|
||||
OPTION_LIST='User=mtr,Password=mtr,Schema=public,Tabtype=TABLE,Maxres=10';
|
||||
CONNECTION='jdbc:postgresql://localhost/test?user=postgres&password=tinono'
|
||||
OPTION_LIST='Tabtype=TABLE,Maxres=10';
|
||||
SELECT * FROM t1;
|
||||
Table_Cat Table_Schema Table_Name Table_Type Remark
|
||||
public employee TABLE NULL
|
||||
public t1 TABLE NULL
|
||||
public t2 TABLE NULL
|
||||
NULL public employee TABLE NULL
|
||||
NULL public t1 TABLE NULL
|
||||
NULL public t2 TABLE NULL
|
||||
NULL public tchar TABLE NULL
|
||||
NULL public testuuid TABLE NULL
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC CATFUNC=columns
|
||||
CONNECTION='jdbc:postgresql://localhost/mtr' tabname=employee
|
||||
OPTION_LIST='User=mtr,Password=mtr,Maxres=10';
|
||||
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC tabname=employee CATFUNC=columns
|
||||
CONNECTION='jdbc:postgresql://localhost/test?user=postgres&password=tinono';
|
||||
SELECT * FROM t1;
|
||||
Table_Cat Table_Schema Table_Name Column_Name Data_Type Type_Name Column_Size Buffer_Length Decimal_Digits Radix Nullable Remarks
|
||||
NULL public employee id 4 int4 10 0 0 10 0 NULL
|
||||
|
@ -34,13 +37,14 @@ NULL public employee salary 2 numeric 8 0 2 10 1 NULL
|
|||
DROP TABLE t1;
|
||||
CREATE SERVER 'postgresql' FOREIGN DATA WRAPPER 'postgresql' OPTIONS (
|
||||
HOST 'localhost',
|
||||
DATABASE 'mtr',
|
||||
USER 'mtr',
|
||||
PASSWORD 'mtr',
|
||||
DATABASE 'test',
|
||||
USER 'postgres',
|
||||
PASSWORD 'tinono',
|
||||
PORT 0,
|
||||
SOCKET '',
|
||||
OWNER 'root');
|
||||
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC CONNECTION='postgresql/public.employee';
|
||||
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC
|
||||
CONNECTION='postgresql/public.employee';
|
||||
SELECT * FROM t1;
|
||||
id name title salary
|
||||
4567 Johnson Engineer 12560.50
|
||||
|
@ -60,6 +64,3 @@ SELECT * FROM t2 WHERE command='drop table employee';
|
|||
command number message
|
||||
drop table employee 0 Affected rows
|
||||
DROP TABLE t2;
|
||||
SET GLOBAL connect_jvm_path=NULL;
|
||||
SET GLOBAL connect_class_path=NULL;
|
||||
SET GLOBAL time_zone = SYSTEM;
|
||||
|
|
BIN
storage/connect/mysql-test/connect/std_data/JavaWrappers.jar
Normal file
BIN
storage/connect/mysql-test/connect/std_data/JavaWrappers.jar
Normal file
Binary file not shown.
|
@ -3,25 +3,32 @@
|
|||
#
|
||||
# This test is run against Postgresql driver
|
||||
#
|
||||
eval SET GLOBAL connect_class_path='$MTR_SUITE_DIR/std_data/JavaWrappers.jar;C:/Jconnectors/postgresql-42.2.1.jar';
|
||||
CREATE TABLE t2 (
|
||||
command varchar(128) not null,
|
||||
number int(5) not null flag=1,
|
||||
message varchar(255) flag=2)
|
||||
ENGINE=CONNECT TABLE_TYPE=JDBC CONNECTION='jdbc:postgresql://localhost/mtr'
|
||||
OPTION_LIST='User=mtr,Password=mtr,Schema=public,Execsrc=1';
|
||||
ENGINE=CONNECT TABLE_TYPE=JDBC
|
||||
CONNECTION='jdbc:postgresql://localhost/test?user=postgres&password=tinono'
|
||||
OPTION_LIST='Execsrc=1';
|
||||
#CONNECTION='jdbc:postgresql://localhost/mtr'
|
||||
#OPTION_LIST='User=mtr,Password=mtr,Schema=public,Execsrc=1';
|
||||
SELECT * FROM t2 WHERE command='drop table employee';
|
||||
SELECT * FROM t2 WHERE command = 'create table employee (id int not null, name varchar(32), title char(16), salary decimal(8,2))';
|
||||
SELECT * FROM t2 WHERE command = "insert into employee values(4567,'Johnson', 'Engineer', 12560.50)";
|
||||
|
||||
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC CATFUNC=tables
|
||||
CONNECTION='jdbc:postgresql://localhost/mtr'
|
||||
OPTION_LIST='User=mtr,Password=mtr,Schema=public,Tabtype=TABLE,Maxres=10';
|
||||
CONNECTION='jdbc:postgresql://localhost/test?user=postgres&password=tinono'
|
||||
OPTION_LIST='Tabtype=TABLE,Maxres=10';
|
||||
#CONNECTION='jdbc:postgresql://localhost/mtr'
|
||||
#OPTION_LIST='User=mtr,Password=mtr,Schema=public,Tabtype=TABLE,Maxres=10';
|
||||
SELECT * FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC CATFUNC=columns
|
||||
CONNECTION='jdbc:postgresql://localhost/mtr' tabname=employee
|
||||
OPTION_LIST='User=mtr,Password=mtr,Maxres=10';
|
||||
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC tabname=employee CATFUNC=columns
|
||||
CONNECTION='jdbc:postgresql://localhost/test?user=postgres&password=tinono';
|
||||
#CONNECTION='jdbc:postgresql://localhost/mtr' tabname=employee;
|
||||
#OPTION_LIST='User=mtr,Password=mtr,Maxres=10';
|
||||
SELECT * FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
|
@ -30,14 +37,18 @@ DROP TABLE t1;
|
|||
#
|
||||
CREATE SERVER 'postgresql' FOREIGN DATA WRAPPER 'postgresql' OPTIONS (
|
||||
HOST 'localhost',
|
||||
DATABASE 'mtr',
|
||||
USER 'mtr',
|
||||
PASSWORD 'mtr',
|
||||
DATABASE 'test',
|
||||
USER 'postgres',
|
||||
PASSWORD 'tinono',
|
||||
PORT 0,
|
||||
SOCKET '',
|
||||
OWNER 'root');
|
||||
#DATABASE 'mtr',
|
||||
#USER 'mtr',
|
||||
#PASSWORD 'mtr',
|
||||
|
||||
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC CONNECTION='postgresql/public.employee';
|
||||
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC
|
||||
CONNECTION='postgresql/public.employee';
|
||||
SELECT * FROM t1;
|
||||
INSERT INTO t1 VALUES(3126,'Smith', 'Clerk', 5230.00);
|
||||
UPDATE t1 SET salary = salary + 100.00;
|
||||
|
|
|
@ -22,10 +22,11 @@ DROP TABLE t1;
|
|||
# 1 - The current directory.
|
||||
# 2 - The paths of the connect_class_path global variable.
|
||||
# 3 - The paths of the CLASSPATH environment variable.
|
||||
# In this test we use an executable jar file that contains all what is needed.
|
||||
eval SET GLOBAL connect_class_path='$MTR_SUITE_DIR/std_data/JdbcMariaDB.jar';
|
||||
# In this test we use an executable jar file that contains all the eisting wrappers.
|
||||
#eval SET GLOBAL connect_class_path='$MTR_SUITE_DIR/std_data/JdbcMariaDB.jar';
|
||||
eval SET GLOBAL connect_class_path='$MTR_SUITE_DIR/std_data/JavaWrappers.jar';
|
||||
|
||||
# Paths to the JDK classes and to the MySQL and MariaDB drivers can be defined in the CLASSPATH environment variable
|
||||
# Paths to the JDK classes and to the JDBC drivers should be defined in the CLASSPATH environment variable
|
||||
#CREATE FUNCTION envar RETURNS STRING SONAME 'ha_connect.dll';
|
||||
#SELECT envar('CLASSPATH');
|
||||
|
||||
|
|
|
@ -362,7 +362,8 @@ enum COLUSE {U_P = 0x01, /* the projection list. */
|
|||
U_IS_NULL = 0x80, /* The column has a null value */
|
||||
U_SPECIAL = 0x100, /* The column is special */
|
||||
U_UNSIGNED = 0x200, /* The column type is unsigned */
|
||||
U_ZEROFILL = 0x400}; /* The column is zero filled */
|
||||
U_ZEROFILL = 0x400, /* The column is zero filled */
|
||||
U_UUID = 0x800}; /* The column is a UUID */
|
||||
|
||||
/***********************************************************************/
|
||||
/* DB description class and block pointer definitions. */
|
||||
|
|
|
@ -605,6 +605,10 @@ bool TDBJDBC::OpenDB(PGLOBAL g)
|
|||
else if (Quoted)
|
||||
Quote = Jcp->GetQuoteChar();
|
||||
|
||||
if (Mode != MODE_READ && Mode != MODE_READX)
|
||||
if (Jcp->SetUUID(g, this))
|
||||
PushWarning(g, this, 1);
|
||||
|
||||
Use = USE_OPEN; // Do it now in case we are recursively called
|
||||
|
||||
/*********************************************************************/
|
||||
|
@ -970,6 +974,7 @@ void TDBJDBC::CloseDB(PGLOBAL g)
|
|||
JDBCCOL::JDBCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am)
|
||||
: EXTCOL(cdp, tdbp, cprec, i, am)
|
||||
{
|
||||
uuid = false;
|
||||
} // end of JDBCCOL constructor
|
||||
|
||||
/***********************************************************************/
|
||||
|
@ -977,6 +982,7 @@ JDBCCOL::JDBCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am)
|
|||
/***********************************************************************/
|
||||
JDBCCOL::JDBCCOL(void) : EXTCOL()
|
||||
{
|
||||
uuid = false;
|
||||
} // end of JDBCCOL constructor
|
||||
|
||||
/***********************************************************************/
|
||||
|
@ -985,12 +991,11 @@ JDBCCOL::JDBCCOL(void) : EXTCOL()
|
|||
/***********************************************************************/
|
||||
JDBCCOL::JDBCCOL(JDBCCOL *col1, PTDB tdbp) : EXTCOL(col1, tdbp)
|
||||
{
|
||||
uuid = col1->uuid;
|
||||
} // end of JDBCCOL copy constructor
|
||||
|
||||
/***********************************************************************/
|
||||
/* ReadColumn: when SQLFetch is used there is nothing to do as the */
|
||||
/* column buffer was bind to the record set. This is also the case */
|
||||
/* when calculating MaxSize (Bufp is NULL even when Rows is not). */
|
||||
/* ReadColumn: retrieve the column value via the JDBC driver. */
|
||||
/***********************************************************************/
|
||||
void JDBCCOL::ReadColumn(PGLOBAL g)
|
||||
{
|
||||
|
|
|
@ -101,6 +101,7 @@ protected:
|
|||
/***********************************************************************/
|
||||
class JDBCCOL : public EXTCOL {
|
||||
friend class TDBJDBC;
|
||||
friend class JDBConn;
|
||||
public:
|
||||
// Constructors
|
||||
JDBCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am = "JDBC");
|
||||
|
@ -119,6 +120,7 @@ protected:
|
|||
JDBCCOL(void);
|
||||
|
||||
// Members
|
||||
bool uuid; // For PostgreSQL
|
||||
}; // end of class JDBCCOL
|
||||
|
||||
/***********************************************************************/
|
||||
|
|
Loading…
Add table
Reference in a new issue