Commit 46defc43 authored by Olivier Bertrand's avatar Olivier Bertrand

- 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
  added:      storage/connect/mysql-test/connect/std_data/JavaWrappers.jar
parent ed5e84ed
package wrappers; package wrappers;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.Console; import java.io.Console;
import java.io.IOException; import java.io.IOException;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.sql.Date;
import java.sql.Time;
import java.sql.Timestamp;
public class Client { public class Client {
static boolean DEBUG = true; static boolean DEBUG = true;
...@@ -58,6 +62,9 @@ public class Client { ...@@ -58,6 +62,9 @@ public class Client {
String query; String query;
System.out.println("Successfully connected to " + parms[1]); System.out.println("Successfully connected to " + parms[1]);
s = jdi.GetQuoteString();
System.out.println("Qstr = '" + s + "'");
while ((query = getLine("Query: ", false)) != null) { while ((query = getLine("Query: ", false)) != null) {
n = jdi.Execute(query); n = jdi.Execute(query);
System.out.println("Returned n = " + n); System.out.println("Returned n = " + n);
...@@ -79,7 +86,11 @@ public class Client { ...@@ -79,7 +86,11 @@ public class Client {
private static void PrintResult(int ncol) { private static void PrintResult(int ncol) {
// Get result set meta data // Get result set meta data
int i; int i;
Date date = new Date(0);
Time time = new Time(0);
Timestamp tsp = new Timestamp(0);
String columnName; String columnName;
Object job;
// Get the column names; column indices start from 1 // Get the column names; column indices start from 1
for (i = 1; i <= ncol; i++) { for (i = 1; i <= ncol; i++) {
...@@ -112,6 +123,7 @@ public class Client { ...@@ -112,6 +123,7 @@ public class Client {
case java.sql.Types.VARCHAR: case java.sql.Types.VARCHAR:
case java.sql.Types.LONGVARCHAR: case java.sql.Types.LONGVARCHAR:
case java.sql.Types.CHAR: case java.sql.Types.CHAR:
case 1111:
System.out.print(jdi.StringField(i, null)); System.out.print(jdi.StringField(i, null));
break; break;
case java.sql.Types.INTEGER: case java.sql.Types.INTEGER:
...@@ -120,14 +132,17 @@ public class Client { ...@@ -120,14 +132,17 @@ public class Client {
case java.sql.Types.BIGINT: case java.sql.Types.BIGINT:
System.out.print(jdi.BigintField(i, null)); System.out.print(jdi.BigintField(i, null));
break; break;
case java.sql.Types.TIMESTAMP:
System.out.print(jdi.TimestampField(i, null));
break;
case java.sql.Types.TIME: 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; break;
case java.sql.Types.DATE: 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; break;
case java.sql.Types.SMALLINT: case java.sql.Types.SMALLINT:
System.out.print(jdi.IntField(i, null)); System.out.print(jdi.IntField(i, null));
...@@ -141,6 +156,8 @@ public class Client { ...@@ -141,6 +156,8 @@ public class Client {
case java.sql.Types.BOOLEAN: case java.sql.Types.BOOLEAN:
System.out.print(jdi.BooleanField(i, null)); System.out.print(jdi.BooleanField(i, null));
default: default:
job = jdi.ObjectField(i, null);
System.out.print(job.toString());
break; break;
} // endswitch Type } // endswitch Type
......
This diff was suppressed by a .gitattributes entry.
package wrappers; package wrappers;
import java.math.*; import java.math.BigDecimal;
import java.sql.*; 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.Collections;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.List; import java.util.List;
import java.util.UUID;
import javax.sql.DataSource; import javax.sql.DataSource;
...@@ -223,6 +235,24 @@ public class JdbcInterface { ...@@ -223,6 +235,24 @@ public class JdbcInterface {
} // end of SetTimestampParm } // 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) { public int SetNullParm(int i, int typ) {
int rc = 0; int rc = 0;
...@@ -481,6 +511,8 @@ public class JdbcInterface { ...@@ -481,6 +511,8 @@ public class JdbcInterface {
System.out.println("Executing query '" + query + "'"); System.out.println("Executing query '" + query + "'");
try { try {
if (rs != null)
rs.close();
rs = stmt.executeQuery(query); rs = stmt.executeQuery(query);
rsmd = rs.getMetaData(); rsmd = rs.getMetaData();
ncol = rsmd.getColumnCount(); ncol = rsmd.getColumnCount();
...@@ -720,6 +752,22 @@ public class JdbcInterface { ...@@ -720,6 +752,22 @@ public class JdbcInterface {
return null; return null;
} // end of ObjectField } // 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) { public int GetDrivers(String[] s, int mxs) {
int n = 0; int n = 0;
List<Driver> drivers = Collections.list(DriverManager.getDrivers()); List<Driver> drivers = Collections.list(DriverManager.getDrivers());
......
package wrappers; package wrappers;
import java.sql.*; import java.sql.SQLException;
import java.util.Hashtable; import java.util.Hashtable;
import javax.sql.DataSource; import javax.sql.DataSource;
import org.postgresql.jdbc2.optional.PoolingDataSource; import org.postgresql.jdbc2.optional.PoolingDataSource;
public class PostgresqlInterface extends JdbcInterface { public class PostgresqlInterface extends JdbcInterface {
......
...@@ -220,7 +220,6 @@ DllExport BOOL PlugIsAbsolutePath(LPCSTR path); ...@@ -220,7 +220,6 @@ DllExport BOOL PlugIsAbsolutePath(LPCSTR path);
DllExport bool AllocSarea(PGLOBAL, uint); DllExport bool AllocSarea(PGLOBAL, uint);
DllExport void FreeSarea(PGLOBAL); DllExport void FreeSarea(PGLOBAL);
DllExport BOOL PlugSubSet(PGLOBAL, void *, uint); DllExport BOOL PlugSubSet(PGLOBAL, void *, uint);
void *PlugSubAlloc(PGLOBAL, void *, size_t); // Does throw
DllExport char *PlugDup(PGLOBAL g, const char *str); DllExport char *PlugDup(PGLOBAL g, const char *str);
DllExport void *MakePtr(void *, OFFSET); DllExport void *MakePtr(void *, OFFSET);
DllExport void htrc(char const *fmt, ...); DllExport void htrc(char const *fmt, ...);
...@@ -231,4 +230,9 @@ DllExport uint GetTraceValue(void); ...@@ -231,4 +230,9 @@ DllExport uint GetTraceValue(void);
} // extern "C" } // extern "C"
#endif #endif
/***********************************************************************/
/* Non exported routine declarations. */
/***********************************************************************/
void *PlugSubAlloc(PGLOBAL, void *, size_t); // Does throw
/*-------------------------- End of Global.H --------------------------*/ /*-------------------------- End of Global.H --------------------------*/
...@@ -174,9 +174,9 @@ ...@@ -174,9 +174,9 @@
#define JSONMAX 10 // JSON Default max grp size #define JSONMAX 10 // JSON Default max grp size
extern "C" { extern "C" {
char version[]= "Version 1.06.0006 February 02, 2018"; char version[]= "Version 1.06.0007 March 11, 2018";
#if defined(__WIN__) #if defined(__WIN__)
char compver[]= "Version 1.06.0006 " __DATE__ " " __TIME__; char compver[]= "Version 1.06.0007 " __DATE__ " " __TIME__;
char slash= '\\'; char slash= '\\';
#else // !__WIN__ #else // !__WIN__
char slash= '/'; char slash= '/';
...@@ -288,11 +288,16 @@ static MYSQL_THDVAR_SET( ...@@ -288,11 +288,16 @@ static MYSQL_THDVAR_SET(
0, // def (NO) 0, // def (NO)
&xtrace_typelib); // typelib &xtrace_typelib); // typelib
// Getting exact info values // Getting exact info values
static MYSQL_THDVAR_BOOL(exact_info, PLUGIN_VAR_RQCMDARG, static MYSQL_THDVAR_BOOL(exact_info, PLUGIN_VAR_RQCMDARG,
"Getting exact info values", "Getting exact info values",
NULL, NULL, 0); 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: Temporary file usage:
no: Not using temporary file no: Not using temporary file
...@@ -427,6 +432,7 @@ handlerton *connect_hton= NULL; ...@@ -427,6 +432,7 @@ handlerton *connect_hton= NULL;
uint GetTraceValue(void) uint GetTraceValue(void)
{return (uint)(connect_hton ? THDVAR(current_thd, xtrace) : 0);} {return (uint)(connect_hton ? THDVAR(current_thd, xtrace) : 0);}
bool ExactInfo(void) {return THDVAR(current_thd, exact_info);} 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);} USETEMP UseTemp(void) {return (USETEMP)THDVAR(current_thd, use_tempfile);}
int GetConvSize(void) {return THDVAR(current_thd, conv_size);} int GetConvSize(void) {return THDVAR(current_thd, conv_size);}
TYPCONV GetTypeConv(void) {return (TYPCONV)THDVAR(current_thd, type_conv);} TYPCONV GetTypeConv(void) {return (TYPCONV)THDVAR(current_thd, type_conv);}
...@@ -3196,7 +3202,7 @@ const COND *ha_connect::cond_push(const COND *cond) ...@@ -3196,7 +3202,7 @@ const COND *ha_connect::cond_push(const COND *cond)
{ {
DBUG_ENTER("ha_connect::cond_push"); DBUG_ENTER("ha_connect::cond_push");
if (tdbp) { if (tdbp && CondPushEnabled()) {
PGLOBAL& g= xp->g; PGLOBAL& g= xp->g;
AMT tty= tdbp->GetAmType(); AMT tty= tdbp->GetAmType();
bool x= (tty == TYPE_AM_MYX || tty == TYPE_AM_XDBC); bool x= (tty == TYPE_AM_MYX || tty == TYPE_AM_XDBC);
...@@ -7243,7 +7249,8 @@ static struct st_mysql_sys_var* connect_system_variables[]= { ...@@ -7243,7 +7249,8 @@ static struct st_mysql_sys_var* connect_system_variables[]= {
#if defined(JAVA_SUPPORT) || defined(CMGO_SUPPORT) #if defined(JAVA_SUPPORT) || defined(CMGO_SUPPORT)
MYSQL_SYSVAR(enable_mongo), MYSQL_SYSVAR(enable_mongo),
#endif // JAVA_SUPPORT || CMGO_SUPPORT #endif // JAVA_SUPPORT || CMGO_SUPPORT
NULL MYSQL_SYSVAR(cond_push),
NULL
}; };
maria_declare_plugin(connect) maria_declare_plugin(connect)
...@@ -7256,10 +7263,10 @@ maria_declare_plugin(connect) ...@@ -7256,10 +7263,10 @@ maria_declare_plugin(connect)
PLUGIN_LICENSE_GPL, PLUGIN_LICENSE_GPL,
connect_init_func, /* Plugin Init */ connect_init_func, /* Plugin Init */
connect_done_func, /* Plugin Deinit */ connect_done_func, /* Plugin Deinit */
0x0106, /* version number (1.05) */ 0x0107, /* version number (1.05) */
NULL, /* status variables */ NULL, /* status variables */
connect_system_variables, /* system variables */ connect_system_variables, /* system variables */
"1.06.0006", /* string version */ "1.06.0007", /* string version */
MariaDB_PLUGIN_MATURITY_STABLE /* maturity */ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
} }
maria_declare_plugin_end; maria_declare_plugin_end;
/************ Jdbconn C++ Functions Source Code File (.CPP) ************/ /************ 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. */ /* This file contains the JDBC connection classes functions. */
/***********************************************************************/ /***********************************************************************/
...@@ -116,10 +116,26 @@ int TranslateJDBCType(int stp, char *tn, int prec, int& len, char& v) ...@@ -116,10 +116,26 @@ int TranslateJDBCType(int stp, char *tn, int prec, int& len, char& v)
return TYPE_ERROR; return TYPE_ERROR;
else else
len = MY_MIN(abs(len), GetConvSize()); len = MY_MIN(abs(len), GetConvSize());
// Pass through // Pass through
case 12: // VARCHAR 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) case -9: // NVARCHAR (unicode)
// Postgresql can return this when size is unknown
if (len == 0x7FFFFFFF)
len = GetConvSize();
v = 'V'; v = 'V';
// Pass through
case 1: // CHAR case 1: // CHAR
case -15: // NCHAR (unicode) case -15: // NCHAR (unicode)
case -8: // ROWID case -8: // ROWID
...@@ -171,6 +187,14 @@ int TranslateJDBCType(int stp, char *tn, int prec, int& len, char& v) ...@@ -171,6 +187,14 @@ int TranslateJDBCType(int stp, char *tn, int prec, int& len, char& v)
case -5: // BIGINT case -5: // BIGINT
type = TYPE_BIGINT; type = TYPE_BIGINT;
break; 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 0: // NULL
case -2: // BINARY case -2: // BINARY
case -4: // LONGVARBINARY case -4: // LONGVARBINARY
...@@ -192,6 +216,104 @@ int TranslateJDBCType(int stp, char *tn, int prec, int& len, char& v) ...@@ -192,6 +216,104 @@ int TranslateJDBCType(int stp, char *tn, int prec, int& len, char& v)
return type; return type;
} // end of TranslateJDBCType } // 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. */ /* Allocate the structure used to refer to the result set. */
/***********************************************************************/ /***********************************************************************/
...@@ -519,7 +641,7 @@ JDBConn::JDBConn(PGLOBAL g, PCSZ wrapper) : JAVAConn(g, wrapper) ...@@ -519,7 +641,7 @@ JDBConn::JDBConn(PGLOBAL g, PCSZ wrapper) : JAVAConn(g, wrapper)
xqid = xuid = xid = grs = readid = fetchid = typid = errid = nullptr; xqid = xuid = xid = grs = readid = fetchid = typid = errid = nullptr;
prepid = xpid = pcid = nullptr; prepid = xpid = pcid = nullptr;
chrfldid = intfldid = dblfldid = fltfldid = bigfldid = nullptr; chrfldid = intfldid = dblfldid = fltfldid = bigfldid = nullptr;
objfldid = datfldid = timfldid = tspfldid = nullptr; objfldid = datfldid = timfldid = tspfldid = uidfldid = nullptr;
DiscFunc = "JdbcDisconnect"; DiscFunc = "JdbcDisconnect";
m_Ncol = 0; m_Ncol = 0;
m_Aff = 0; m_Aff = 0;
...@@ -535,12 +657,84 @@ JDBConn::JDBConn(PGLOBAL g, PCSZ wrapper) : JAVAConn(g, wrapper) ...@@ -535,12 +657,84 @@ JDBConn::JDBConn(PGLOBAL g, PCSZ wrapper) : JAVAConn(g, wrapper)
m_IDQuoteChar[1] = 0; m_IDQuoteChar[1] = 0;
} // end of JDBConn } // end of JDBConn
//JDBConn::~JDBConn() /***********************************************************************/
// { /* Search for UUID columns. */
//if (Connected()) /***********************************************************************/
// EndCom(); bool JDBConn::SetUUID(PGLOBAL g, PTDBJDBC tjp)
{
int ncol, ctyp;
bool brc = true;
PCSZ fnc = "GetColumns";
PCOL colp;
JCATPARM *cap;
//jint jtyp;
jboolean rc = false;
jobjectArray parms;
jmethodID catid = nullptr;
if (gmID(g, catid, fnc, "([Ljava/lang/String;)I"))
return true;
else if (gmID(g, intfldid, "IntField", "(ILjava/lang/String;)I"))
return true;
else if (gmID(g, readid, "ReadNext", "()I"))
return true;
cap = AllocCatInfo(g, JCAT_COL, tjp->Schema, tjp->TableName, NULL);
SQLQualifiedName name(cap);
// Build the java string array
parms = env->NewObjectArray(4, env->FindClass("java/lang/String"), NULL);
env->SetObjectArrayElement(parms, 0, env->NewStringUTF(name.ptr(2)));
env->SetObjectArrayElement(parms, 1, env->NewStringUTF(name.ptr(1)));
env->SetObjectArrayElement(parms, 2, env->NewStringUTF(name.ptr(0)));
for (colp = tjp->GetColumns(); colp; colp = colp->GetNext()) {
env->SetObjectArrayElement(parms, 3, env->NewStringUTF(colp->GetName()));
ncol = env->CallIntMethod(job, catid, parms);
if (Check(ncol)) {
sprintf(g->Message, "%s: %s", fnc, Msg);
goto err;
} // endif Check
rc = env->CallBooleanMethod(job, readid);
if (Check(rc)) {
sprintf(g->Message, "ReadNext: %s", Msg);
goto err;
} else if (rc == 0) {
sprintf(g->Message, "table %s does not exist", tjp->TableName);
goto err;
} // endif rc
// Returns 666 is case of error
//jtyp = env->CallIntMethod(job, typid, 5, nullptr);
//if (Check((jtyp == 666) ? -1 : 1)) {
// sprintf(g->Message, "Getting jtyp: %s", Msg);
// goto err;
//} // endif ctyp
ctyp = (int)env->CallIntMethod(job, intfldid, 5, nullptr);
if (Check(ctyp)) {
sprintf(g->Message, "Getting ctyp: %s", Msg);
goto err;
} // endif ctyp
if (ctyp == 1111)
((PJDBCCOL)colp)->uuid = true;
} // endfor colp
// } // end of ~JDBConn // All is Ok
brc = false;
err:
// Not used anymore
env->DeleteLocalRef(parms);
return brc;
} // end of SetUUID
/***********************************************************************/ /***********************************************************************/
/* Utility routine. */ /* Utility routine. */
...@@ -770,6 +964,7 @@ int JDBConn::Rewind(PCSZ sql) ...@@ -770,6 +964,7 @@ int JDBConn::Rewind(PCSZ sql)
/***********************************************************************/ /***********************************************************************/
void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val) void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val)
{ {
const char *field;
PGLOBAL& g = m_G; PGLOBAL& g = m_G;
jint ctyp; jint ctyp;
jstring cn, jn = nullptr; jstring cn, jn = nullptr;
...@@ -793,6 +988,11 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val) ...@@ -793,6 +988,11 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val)
if (!gmID(g, objfldid, "ObjectField", "(ILjava/lang/String;)Ljava/lang/Object;")) { if (!gmID(g, objfldid, "ObjectField", "(ILjava/lang/String;)Ljava/lang/Object;")) {
jb = env->CallObjectMethod(job, objfldid, (jint)rank, jn); 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) { if (jb == nullptr) {
val->Reset(); val->Reset();
val->SetNull(true); val->SetNull(true);
...@@ -818,7 +1018,7 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val) ...@@ -818,7 +1018,7 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val)
cn = nullptr; cn = nullptr;
if (cn) { if (cn) {
const char *field = env->GetStringUTFChars(cn, (jboolean)false); field = env->GetStringUTFChars(cn, (jboolean)false);
val->SetValue_psz((PSZ)field); val->SetValue_psz((PSZ)field);
} else } else
val->Reset(); val->Reset();
...@@ -885,6 +1085,19 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val) ...@@ -885,6 +1085,19 @@ void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val)
break; break;
case java.sql.Types.BOOLEAN: case java.sql.Types.BOOLEAN:
System.out.print(jdi.BooleanField(i)); */ 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 case 0: // NULL
val->SetNull(true); val->SetNull(true);
// passthru // passthru
...@@ -1055,7 +1268,14 @@ bool JDBConn::SetParam(JDBCCOL *colp) ...@@ -1055,7 +1268,14 @@ bool JDBConn::SetParam(JDBCCOL *colp)
if (gmID(g, setid, "SetNullParm", "(II)I")) if (gmID(g, setid, "SetNullParm", "(II)I"))
return true; 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()) { } else switch (val->GetType()) {
case TYPE_STRING: case TYPE_STRING:
if (gmID(g, setid, "SetStringParm", "(ILjava/lang/String;)V")) if (gmID(g, setid, "SetStringParm", "(ILjava/lang/String;)V"))
...@@ -1274,105 +1494,6 @@ bool JDBConn::SetParam(JDBCCOL *colp) ...@@ -1274,105 +1494,6 @@ bool JDBConn::SetParam(JDBCCOL *colp)
return qrp; return qrp;
} // end of GetMetaData } // 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. */ /* Allocate recset and call SQLTables, SQLColumns or SQLPrimaryKeys. */
/***********************************************************************/ /***********************************************************************/
......
...@@ -29,6 +29,7 @@ class JDBConn : public JAVAConn { ...@@ -29,6 +29,7 @@ class JDBConn : public JAVAConn {
// Attributes // Attributes
public: public:
char *GetQuoteChar(void) { return m_IDQuoteChar; } char *GetQuoteChar(void) { return m_IDQuoteChar; }
bool SetUUID(PGLOBAL g, PTDBJDBC tjp);
virtual int GetMaxValue(int infotype); virtual int GetMaxValue(int infotype);
public: public:
...@@ -58,13 +59,6 @@ class JDBConn : public JAVAConn { ...@@ -58,13 +59,6 @@ class JDBConn : public JAVAConn {
protected: protected:
// Members // 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 xqid; // The ExecuteQuery method ID
jmethodID xuid; // The ExecuteUpdate method ID jmethodID xuid; // The ExecuteUpdate method ID
jmethodID xid; // The Execute method ID jmethodID xid; // The Execute method ID
...@@ -84,8 +78,7 @@ class JDBConn : public JAVAConn { ...@@ -84,8 +78,7 @@ class JDBConn : public JAVAConn {
jmethodID timfldid; // The TimeField method ID jmethodID timfldid; // The TimeField method ID
jmethodID tspfldid; // The TimestampField method ID jmethodID tspfldid; // The TimestampField method ID
jmethodID bigfldid; // The BigintField method ID jmethodID bigfldid; // The BigintField method ID
// PCSZ Msg; jmethodID uidfldid; // The UuidField method ID
// PCSZ m_Wrap;
char m_IDQuoteChar[2]; char m_IDQuoteChar[2];
PCSZ m_Pwd; PCSZ m_Pwd;
int m_Ncol; int m_Ncol;
......
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 ( CREATE TABLE t2 (
command varchar(128) not null, command varchar(128) not null,
number int(5) not null flag=1, number int(5) not null flag=1,
message varchar(255) flag=2) message varchar(255) flag=2)
ENGINE=CONNECT TABLE_TYPE=JDBC CONNECTION='jdbc:postgresql://localhost/mtr' ENGINE=CONNECT TABLE_TYPE=JDBC
OPTION_LIST='User=mtr,Password=mtr,Schema=public,Execsrc=1'; CONNECTION='jdbc:postgresql://localhost/test?user=postgres&password=tinono'
OPTION_LIST='Execsrc=1';
SELECT * FROM t2 WHERE command='drop table employee'; SELECT * FROM t2 WHERE command='drop table employee';
command number message command number message
drop table employee 0 Execute: org.postgresql.util.PSQLException: ERREUR: la table « employee » n'existe pas 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 ...@@ -14,17 +16,18 @@ SELECT * FROM t2 WHERE command = "insert into employee values(4567,'Johnson', 'E
command number message command number message
insert into employee values(4567,'Johnson', 'Engineer', 12560.50) 1 Affected rows insert into employee values(4567,'Johnson', 'Engineer', 12560.50) 1 Affected rows
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC CATFUNC=tables CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC CATFUNC=tables
CONNECTION='jdbc:postgresql://localhost/mtr' CONNECTION='jdbc:postgresql://localhost/test?user=postgres&password=tinono'
OPTION_LIST='User=mtr,Password=mtr,Schema=public,Tabtype=TABLE,Maxres=10'; OPTION_LIST='Tabtype=TABLE,Maxres=10';
SELECT * FROM t1; SELECT * FROM t1;
Table_Cat Table_Schema Table_Name Table_Type Remark Table_Cat Table_Schema Table_Name Table_Type Remark
public employee TABLE NULL NULL public employee TABLE NULL
public t1 TABLE NULL NULL public t1 TABLE NULL
public t2 TABLE NULL NULL public t2 TABLE NULL
NULL public tchar TABLE NULL
NULL public testuuid TABLE NULL
DROP TABLE t1; DROP TABLE t1;
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC CATFUNC=columns CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC tabname=employee CATFUNC=columns
CONNECTION='jdbc:postgresql://localhost/mtr' tabname=employee CONNECTION='jdbc:postgresql://localhost/test?user=postgres&password=tinono';
OPTION_LIST='User=mtr,Password=mtr,Maxres=10';
SELECT * FROM t1; SELECT * FROM t1;
Table_Cat Table_Schema Table_Name Column_Name Data_Type Type_Name Column_Size Buffer_Length Decimal_Digits Radix Nullable Remarks 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 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 ...@@ -34,13 +37,14 @@ NULL public employee salary 2 numeric 8 0 2 10 1 NULL
DROP TABLE t1; DROP TABLE t1;
CREATE SERVER 'postgresql' FOREIGN DATA WRAPPER 'postgresql' OPTIONS ( CREATE SERVER 'postgresql' FOREIGN DATA WRAPPER 'postgresql' OPTIONS (
HOST 'localhost', HOST 'localhost',
DATABASE 'mtr', DATABASE 'test',
USER 'mtr', USER 'postgres',
PASSWORD 'mtr', PASSWORD 'tinono',
PORT 0, PORT 0,
SOCKET '', SOCKET '',
OWNER 'root'); 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; SELECT * FROM t1;
id name title salary id name title salary
4567 Johnson Engineer 12560.50 4567 Johnson Engineer 12560.50
...@@ -60,6 +64,3 @@ SELECT * FROM t2 WHERE command='drop table employee'; ...@@ -60,6 +64,3 @@ SELECT * FROM t2 WHERE command='drop table employee';
command number message command number message
drop table employee 0 Affected rows drop table employee 0 Affected rows
DROP TABLE t2; DROP TABLE t2;
SET GLOBAL connect_jvm_path=NULL;
SET GLOBAL connect_class_path=NULL;
SET GLOBAL time_zone = SYSTEM;
This diff was suppressed by a .gitattributes entry.
...@@ -3,25 +3,32 @@ ...@@ -3,25 +3,32 @@
# #
# This test is run against Postgresql driver # 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 ( CREATE TABLE t2 (
command varchar(128) not null, command varchar(128) not null,
number int(5) not null flag=1, number int(5) not null flag=1,
message varchar(255) flag=2) message varchar(255) flag=2)
ENGINE=CONNECT TABLE_TYPE=JDBC CONNECTION='jdbc:postgresql://localhost/mtr' ENGINE=CONNECT TABLE_TYPE=JDBC
OPTION_LIST='User=mtr,Password=mtr,Schema=public,Execsrc=1'; 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='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 = '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)"; SELECT * FROM t2 WHERE command = "insert into employee values(4567,'Johnson', 'Engineer', 12560.50)";
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC CATFUNC=tables CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC CATFUNC=tables
CONNECTION='jdbc:postgresql://localhost/mtr' CONNECTION='jdbc:postgresql://localhost/test?user=postgres&password=tinono'
OPTION_LIST='User=mtr,Password=mtr,Schema=public,Tabtype=TABLE,Maxres=10'; 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; SELECT * FROM t1;
DROP TABLE t1; DROP TABLE t1;
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC CATFUNC=columns CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=JDBC tabname=employee CATFUNC=columns
CONNECTION='jdbc:postgresql://localhost/mtr' tabname=employee CONNECTION='jdbc:postgresql://localhost/test?user=postgres&password=tinono';
OPTION_LIST='User=mtr,Password=mtr,Maxres=10'; #CONNECTION='jdbc:postgresql://localhost/mtr' tabname=employee;
#OPTION_LIST='User=mtr,Password=mtr,Maxres=10';
SELECT * FROM t1; SELECT * FROM t1;
DROP TABLE t1; DROP TABLE t1;
...@@ -30,14 +37,18 @@ DROP TABLE t1; ...@@ -30,14 +37,18 @@ DROP TABLE t1;
# #
CREATE SERVER 'postgresql' FOREIGN DATA WRAPPER 'postgresql' OPTIONS ( CREATE SERVER 'postgresql' FOREIGN DATA WRAPPER 'postgresql' OPTIONS (
HOST 'localhost', HOST 'localhost',
DATABASE 'mtr', DATABASE 'test',
USER 'mtr', USER 'postgres',
PASSWORD 'mtr', PASSWORD 'tinono',
PORT 0, PORT 0,
SOCKET '', SOCKET '',
OWNER 'root'); 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; SELECT * FROM t1;
INSERT INTO t1 VALUES(3126,'Smith', 'Clerk', 5230.00); INSERT INTO t1 VALUES(3126,'Smith', 'Clerk', 5230.00);
UPDATE t1 SET salary = salary + 100.00; UPDATE t1 SET salary = salary + 100.00;
......
...@@ -22,10 +22,11 @@ DROP TABLE t1; ...@@ -22,10 +22,11 @@ DROP TABLE t1;
# 1 - The current directory. # 1 - The current directory.
# 2 - The paths of the connect_class_path global variable. # 2 - The paths of the connect_class_path global variable.
# 3 - The paths of the CLASSPATH environment variable. # 3 - The paths of the CLASSPATH environment variable.
# In this test we use an executable jar file that contains all what is needed. # 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/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'; #CREATE FUNCTION envar RETURNS STRING SONAME 'ha_connect.dll';
#SELECT envar('CLASSPATH'); #SELECT envar('CLASSPATH');
......
...@@ -362,7 +362,8 @@ enum COLUSE {U_P = 0x01, /* the projection list. */ ...@@ -362,7 +362,8 @@ enum COLUSE {U_P = 0x01, /* the projection list. */
U_IS_NULL = 0x80, /* The column has a null value */ U_IS_NULL = 0x80, /* The column has a null value */
U_SPECIAL = 0x100, /* The column is special */ U_SPECIAL = 0x100, /* The column is special */
U_UNSIGNED = 0x200, /* The column type is unsigned */ 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. */ /* DB description class and block pointer definitions. */
......
...@@ -605,6 +605,10 @@ bool TDBJDBC::OpenDB(PGLOBAL g) ...@@ -605,6 +605,10 @@ bool TDBJDBC::OpenDB(PGLOBAL g)
else if (Quoted) else if (Quoted)
Quote = Jcp->GetQuoteChar(); 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 Use = USE_OPEN; // Do it now in case we are recursively called
/*********************************************************************/ /*********************************************************************/
...@@ -970,6 +974,7 @@ void TDBJDBC::CloseDB(PGLOBAL g) ...@@ -970,6 +974,7 @@ void TDBJDBC::CloseDB(PGLOBAL g)
JDBCCOL::JDBCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am) JDBCCOL::JDBCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am)
: EXTCOL(cdp, tdbp, cprec, i, am) : EXTCOL(cdp, tdbp, cprec, i, am)
{ {
uuid = false;
} // end of JDBCCOL constructor } // end of JDBCCOL constructor
/***********************************************************************/ /***********************************************************************/
...@@ -977,6 +982,7 @@ JDBCCOL::JDBCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am) ...@@ -977,6 +982,7 @@ JDBCCOL::JDBCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am)
/***********************************************************************/ /***********************************************************************/
JDBCCOL::JDBCCOL(void) : EXTCOL() JDBCCOL::JDBCCOL(void) : EXTCOL()
{ {
uuid = false;
} // end of JDBCCOL constructor } // end of JDBCCOL constructor
/***********************************************************************/ /***********************************************************************/
...@@ -985,12 +991,11 @@ JDBCCOL::JDBCCOL(void) : EXTCOL() ...@@ -985,12 +991,11 @@ JDBCCOL::JDBCCOL(void) : EXTCOL()
/***********************************************************************/ /***********************************************************************/
JDBCCOL::JDBCCOL(JDBCCOL *col1, PTDB tdbp) : EXTCOL(col1, tdbp) JDBCCOL::JDBCCOL(JDBCCOL *col1, PTDB tdbp) : EXTCOL(col1, tdbp)
{ {
uuid = col1->uuid;
} // end of JDBCCOL copy constructor } // end of JDBCCOL copy constructor
/***********************************************************************/ /***********************************************************************/
/* ReadColumn: when SQLFetch is used there is nothing to do as the */ /* ReadColumn: retrieve the column value via the JDBC driver. */
/* column buffer was bind to the record set. This is also the case */
/* when calculating MaxSize (Bufp is NULL even when Rows is not). */
/***********************************************************************/ /***********************************************************************/
void JDBCCOL::ReadColumn(PGLOBAL g) void JDBCCOL::ReadColumn(PGLOBAL g)
{ {
......
...@@ -101,6 +101,7 @@ class TDBJDBC : public TDBEXT { ...@@ -101,6 +101,7 @@ class TDBJDBC : public TDBEXT {
/***********************************************************************/ /***********************************************************************/
class JDBCCOL : public EXTCOL { class JDBCCOL : public EXTCOL {
friend class TDBJDBC; friend class TDBJDBC;
friend class JDBConn;
public: public:
// Constructors // Constructors
JDBCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am = "JDBC"); JDBCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am = "JDBC");
...@@ -119,6 +120,7 @@ class JDBCCOL : public EXTCOL { ...@@ -119,6 +120,7 @@ class JDBCCOL : public EXTCOL {
JDBCCOL(void); JDBCCOL(void);
// Members // Members
bool uuid; // For PostgreSQL
}; // end of class JDBCCOL }; // end of class JDBCCOL
/***********************************************************************/ /***********************************************************************/
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment