mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
- Fix MDEV-10496. Memory leak in discovery
modified: storage/connect/ha_connect.cc modified: storage/connect/mycat.cc - Fix wrong lrecl calculation for virtual columns modified: storage/connect/reldef.cpp - Typo modified: storage/connect/jdbconn.cpp modified: storage/connect/json.cpp
This commit is contained in:
@@ -224,6 +224,7 @@ uint GetWorkSize(void);
|
|||||||
void SetWorkSize(uint);
|
void SetWorkSize(uint);
|
||||||
extern "C" const char *msglang(void);
|
extern "C" const char *msglang(void);
|
||||||
|
|
||||||
|
static void PopUser(PCONNECT xp);
|
||||||
static PCONNECT GetUser(THD *thd, PCONNECT xp);
|
static PCONNECT GetUser(THD *thd, PCONNECT xp);
|
||||||
static PGLOBAL GetPlug(THD *thd, PCONNECT& lxp);
|
static PGLOBAL GetPlug(THD *thd, PCONNECT& lxp);
|
||||||
|
|
||||||
@@ -831,42 +832,51 @@ ha_connect::~ha_connect(void)
|
|||||||
table ? table->s->table_name.str : "<null>",
|
table ? table->s->table_name.str : "<null>",
|
||||||
xp, xp ? xp->count : 0);
|
xp, xp ? xp->count : 0);
|
||||||
|
|
||||||
if (xp) {
|
PopUser(xp);
|
||||||
PCONNECT p;
|
|
||||||
|
|
||||||
xp->count--;
|
|
||||||
|
|
||||||
for (p= user_connect::to_users; p; p= p->next)
|
|
||||||
if (p == xp)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (p && !p->count) {
|
|
||||||
if (p->next)
|
|
||||||
p->next->previous= p->previous;
|
|
||||||
|
|
||||||
if (p->previous)
|
|
||||||
p->previous->next= p->next;
|
|
||||||
else
|
|
||||||
user_connect::to_users= p->next;
|
|
||||||
|
|
||||||
} // endif p
|
|
||||||
|
|
||||||
if (!xp->count) {
|
|
||||||
PlugCleanup(xp->g, true);
|
|
||||||
delete xp;
|
|
||||||
} // endif count
|
|
||||||
|
|
||||||
} // endif xp
|
|
||||||
|
|
||||||
} // end of ha_connect destructor
|
} // end of ha_connect destructor
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
/* Check whether this user can be removed. */
|
||||||
|
/****************************************************************************/
|
||||||
|
static void PopUser(PCONNECT xp)
|
||||||
|
{
|
||||||
|
if (xp) {
|
||||||
|
xp->count--;
|
||||||
|
|
||||||
|
if (!xp->count) {
|
||||||
|
PCONNECT p;
|
||||||
|
|
||||||
|
for (p= user_connect::to_users; p; p= p->next)
|
||||||
|
if (p == xp)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (p) {
|
||||||
|
if (p->next)
|
||||||
|
p->next->previous= p->previous;
|
||||||
|
|
||||||
|
if (p->previous)
|
||||||
|
p->previous->next= p->next;
|
||||||
|
else
|
||||||
|
user_connect::to_users= p->next;
|
||||||
|
|
||||||
|
} // endif p
|
||||||
|
|
||||||
|
PlugCleanup(xp->g, true);
|
||||||
|
delete xp;
|
||||||
|
} // endif count
|
||||||
|
|
||||||
|
} // endif xp
|
||||||
|
|
||||||
|
} // end of PopUser
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
/* Get a pointer to the user of this handler. */
|
/* Get a pointer to the user of this handler. */
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
static PCONNECT GetUser(THD *thd, PCONNECT xp)
|
static PCONNECT GetUser(THD *thd, PCONNECT xp)
|
||||||
{
|
{
|
||||||
if (!thd)
|
if (!thd)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (xp && thd == xp->thdp)
|
if (xp && thd == xp->thdp)
|
||||||
@@ -890,7 +900,6 @@ static PCONNECT GetUser(THD *thd, PCONNECT xp)
|
|||||||
return xp;
|
return xp;
|
||||||
} // end of GetUser
|
} // end of GetUser
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
/* Get the global pointer of the user of this handler. */
|
/* Get the global pointer of the user of this handler. */
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
@@ -5261,7 +5270,18 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
|
|||||||
if (!(shm= (char*)db))
|
if (!(shm= (char*)db))
|
||||||
db= table_s->db.str; // Default value
|
db= table_s->db.str; // Default value
|
||||||
|
|
||||||
// Check table type
|
// Save stack and allocation environment and prepare error return
|
||||||
|
if (g->jump_level == MAX_JUMP) {
|
||||||
|
strcpy(g->Message, MSG(TOO_MANY_JUMPS));
|
||||||
|
goto jer;
|
||||||
|
} // endif jump_level
|
||||||
|
|
||||||
|
if ((rc= setjmp(g->jumper[++g->jump_level])) != 0) {
|
||||||
|
my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
|
||||||
|
goto err;
|
||||||
|
} // endif rc
|
||||||
|
|
||||||
|
// Check table type
|
||||||
if (ttp == TAB_UNDEF) {
|
if (ttp == TAB_UNDEF) {
|
||||||
topt->type= (src) ? "MYSQL" : (tab) ? "PROXY" : "DOS";
|
topt->type= (src) ? "MYSQL" : (tab) ? "PROXY" : "DOS";
|
||||||
ttp= GetTypeID(topt->type);
|
ttp= GetTypeID(topt->type);
|
||||||
@@ -5270,20 +5290,9 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
|
|||||||
} else if (ttp == TAB_NIY) {
|
} else if (ttp == TAB_NIY) {
|
||||||
sprintf(g->Message, "Unsupported table type %s", topt->type);
|
sprintf(g->Message, "Unsupported table type %s", topt->type);
|
||||||
my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
|
my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
|
||||||
return HA_ERR_INTERNAL_ERROR;
|
goto err;
|
||||||
} // endif ttp
|
} // endif ttp
|
||||||
|
|
||||||
// Save stack and allocation environment and prepare error return
|
|
||||||
if (g->jump_level == MAX_JUMP) {
|
|
||||||
strcpy(g->Message, MSG(TOO_MANY_JUMPS));
|
|
||||||
return HA_ERR_INTERNAL_ERROR;
|
|
||||||
} // endif jump_level
|
|
||||||
|
|
||||||
if ((rc= setjmp(g->jumper[++g->jump_level])) != 0) {
|
|
||||||
my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
|
|
||||||
goto err;
|
|
||||||
} // endif rc
|
|
||||||
|
|
||||||
if (!tab) {
|
if (!tab) {
|
||||||
if (ttp == TAB_TBL) {
|
if (ttp == TAB_TBL) {
|
||||||
// Make tab the first table of the list
|
// Make tab the first table of the list
|
||||||
@@ -5843,6 +5852,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
|
|||||||
rc= init_table_share(thd, table_s, create_info, &sql);
|
rc= init_table_share(thd, table_s, create_info, &sql);
|
||||||
|
|
||||||
g->jump_level--;
|
g->jump_level--;
|
||||||
|
PopUser(xp);
|
||||||
return rc;
|
return rc;
|
||||||
} // endif ok
|
} // endif ok
|
||||||
|
|
||||||
@@ -5850,7 +5860,9 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
|
|||||||
|
|
||||||
err:
|
err:
|
||||||
g->jump_level--;
|
g->jump_level--;
|
||||||
return HA_ERR_INTERNAL_ERROR;
|
jer:
|
||||||
|
PopUser(xp);
|
||||||
|
return HA_ERR_INTERNAL_ERROR;
|
||||||
} // end of connect_assisted_discovery
|
} // end of connect_assisted_discovery
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -498,145 +498,6 @@ PQRYRES JDBCDrivers(PGLOBAL g, int maxres, bool info)
|
|||||||
return qrp;
|
return qrp;
|
||||||
} // end of JDBCDrivers
|
} // end of JDBCDrivers
|
||||||
|
|
||||||
#if 0
|
|
||||||
/*************************************************************************/
|
|
||||||
/* JDBCDataSources: constructs the result blocks containing all JDBC */
|
|
||||||
/* data sources available on the local host. */
|
|
||||||
/* Called with info=true to have result column names. */
|
|
||||||
/*************************************************************************/
|
|
||||||
PQRYRES JDBCDataSources(PGLOBAL g, int maxres, bool info)
|
|
||||||
{
|
|
||||||
int buftyp[] ={ TYPE_STRING, TYPE_STRING };
|
|
||||||
XFLD fldtyp[] ={ FLD_NAME, FLD_REM };
|
|
||||||
unsigned int length[] ={ 0, 256 };
|
|
||||||
bool b[] ={ false, true };
|
|
||||||
int i, n = 0, ncol = 2;
|
|
||||||
PCOLRES crp;
|
|
||||||
PQRYRES qrp;
|
|
||||||
JDBConn *jcp = NULL;
|
|
||||||
|
|
||||||
/************************************************************************/
|
|
||||||
/* Do an evaluation of the result size. */
|
|
||||||
/************************************************************************/
|
|
||||||
if (!info) {
|
|
||||||
jcp = new(g)JDBConn(g, NULL);
|
|
||||||
n = jcp->GetMaxValue(SQL_MAX_DSN_LENGTH);
|
|
||||||
length[0] = (n) ? (n + 1) : 256;
|
|
||||||
|
|
||||||
if (!maxres)
|
|
||||||
maxres = 512; // Estimated max number of data sources
|
|
||||||
|
|
||||||
} else {
|
|
||||||
length[0] = 256;
|
|
||||||
maxres = 0;
|
|
||||||
} // endif info
|
|
||||||
|
|
||||||
if (trace)
|
|
||||||
htrc("JDBCDataSources: max=%d len=%d\n", maxres, length[0]);
|
|
||||||
|
|
||||||
/************************************************************************/
|
|
||||||
/* Allocate the structures used to refer to the result set. */
|
|
||||||
/************************************************************************/
|
|
||||||
qrp = PlgAllocResult(g, ncol, maxres, IDS_DSRC,
|
|
||||||
buftyp, fldtyp, length, false, true);
|
|
||||||
|
|
||||||
for (i = 0, crp = qrp->Colresp; crp; i++, crp = crp->Next)
|
|
||||||
if (b[i])
|
|
||||||
crp->Kdata->SetNullable(true);
|
|
||||||
|
|
||||||
/************************************************************************/
|
|
||||||
/* Now get the results into blocks. */
|
|
||||||
/************************************************************************/
|
|
||||||
if (!info && qrp && jcp->GetDataSources(qrp))
|
|
||||||
qrp = NULL;
|
|
||||||
|
|
||||||
/************************************************************************/
|
|
||||||
/* Return the result pointer for use by GetData routines. */
|
|
||||||
/************************************************************************/
|
|
||||||
return qrp;
|
|
||||||
} // end of JDBCDataSources
|
|
||||||
|
|
||||||
/**************************************************************************/
|
|
||||||
/* PrimaryKeys: constructs the result blocks containing all the */
|
|
||||||
/* JDBC catalog information concerning primary keys. */
|
|
||||||
/**************************************************************************/
|
|
||||||
PQRYRES JDBCPrimaryKeys(PGLOBAL g, JDBConn *op, char *dsn, char *table)
|
|
||||||
{
|
|
||||||
static int buftyp[] ={ TYPE_STRING, TYPE_STRING, TYPE_STRING,
|
|
||||||
TYPE_STRING, TYPE_SHORT, TYPE_STRING };
|
|
||||||
static unsigned int length[] ={ 0, 0, 0, 0, 6, 128 };
|
|
||||||
int n, ncol = 5;
|
|
||||||
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 = jcp->GetMaxValue(SQL_MAX_COLUMNS_IN_TABLE);
|
|
||||||
maxres = (n) ? (int)n : 250;
|
|
||||||
n = jcp->GetMaxValue(SQL_MAX_CATALOG_NAME_LEN);
|
|
||||||
length[0] = (n) ? (n + 1) : 128;
|
|
||||||
n = jcp->GetMaxValue(SQL_MAX_SCHEMA_NAME_LEN);
|
|
||||||
length[1] = (n) ? (n + 1) : 128;
|
|
||||||
n = jcp->GetMaxValue(SQL_MAX_TABLE_NAME_LEN);
|
|
||||||
length[2] = (n) ? (n + 1) : 128;
|
|
||||||
n = jcp->GetMaxValue(SQL_MAX_COLUMN_NAME_LEN);
|
|
||||||
length[3] = (n) ? (n + 1) : 128;
|
|
||||||
|
|
||||||
if (trace)
|
|
||||||
htrc("JDBCPrimaryKeys: max=%d len=%d,%d,%d\n",
|
|
||||||
maxres, length[0], length[1], length[2]);
|
|
||||||
|
|
||||||
/************************************************************************/
|
|
||||||
/* Allocate the structure used to refer to the result set. */
|
|
||||||
/************************************************************************/
|
|
||||||
qrp = PlgAllocResult(g, ncol, maxres, IDS_PKEY,
|
|
||||||
buftyp, NULL, length, false, true);
|
|
||||||
|
|
||||||
if (trace)
|
|
||||||
htrc("Getting pkey results ncol=%d\n", qrp->Nbcol);
|
|
||||||
|
|
||||||
cap = AllocCatInfo(g, CAT_KEY, NULL, table, qrp);
|
|
||||||
|
|
||||||
/************************************************************************/
|
|
||||||
/* Now get the results into blocks. */
|
|
||||||
/************************************************************************/
|
|
||||||
if ((n = jcp->GetCatInfo(cap)) >= 0) {
|
|
||||||
qrp->Nblin = n;
|
|
||||||
// ResetNullValues(cap);
|
|
||||||
|
|
||||||
if (trace)
|
|
||||||
htrc("PrimaryKeys: 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 JDBCPrimaryKeys
|
|
||||||
#endif // 0
|
|
||||||
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
/* JDBConn construction/destruction. */
|
/* JDBConn construction/destruction. */
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
@@ -739,60 +600,6 @@ bool JDBConn::gmID(PGLOBAL g, jmethodID& mid, const char *name, const char *sig
|
|||||||
|
|
||||||
} // end of gmID
|
} // end of gmID
|
||||||
|
|
||||||
#if 0
|
|
||||||
/***********************************************************************/
|
|
||||||
/* Utility routine. */
|
|
||||||
/***********************************************************************/
|
|
||||||
PSZ JDBConn::GetStringInfo(ushort infotype)
|
|
||||||
{
|
|
||||||
//ASSERT(m_hdbc != SQL_NULL_HDBC);
|
|
||||||
char *p, buffer[MAX_STRING_INFO];
|
|
||||||
SWORD result;
|
|
||||||
RETCODE rc;
|
|
||||||
|
|
||||||
rc = SQLGetInfo(m_hdbc, infotype, buffer, sizeof(buffer), &result);
|
|
||||||
|
|
||||||
if (!Check(rc)) {
|
|
||||||
ThrowDJX(rc, "SQLGetInfo"); // Temporary
|
|
||||||
// *buffer = '\0';
|
|
||||||
} // endif rc
|
|
||||||
|
|
||||||
p = PlugDup(m_G, buffer);
|
|
||||||
return p;
|
|
||||||
} // end of GetStringInfo
|
|
||||||
|
|
||||||
/***********************************************************************/
|
|
||||||
/* Utility routines. */
|
|
||||||
/***********************************************************************/
|
|
||||||
void JDBConn::OnSetOptions(HSTMT hstmt)
|
|
||||||
{
|
|
||||||
RETCODE rc;
|
|
||||||
ASSERT(m_hdbc != SQL_NULL_HDBC);
|
|
||||||
|
|
||||||
if ((signed)m_QueryTimeout != -1) {
|
|
||||||
// Attempt to set query timeout. Ignore failure
|
|
||||||
rc = SQLSetStmtOption(hstmt, SQL_QUERY_TIMEOUT, m_QueryTimeout);
|
|
||||||
|
|
||||||
if (!Check(rc))
|
|
||||||
// don't attempt it again
|
|
||||||
m_QueryTimeout = (DWORD)-1;
|
|
||||||
|
|
||||||
} // endif m_QueryTimeout
|
|
||||||
|
|
||||||
if (m_RowsetSize > 0) {
|
|
||||||
// Attempt to set rowset size.
|
|
||||||
// In case of failure reset it to 0 to use Fetch.
|
|
||||||
rc = SQLSetStmtOption(hstmt, SQL_ROWSET_SIZE, m_RowsetSize);
|
|
||||||
|
|
||||||
if (!Check(rc))
|
|
||||||
// don't attempt it again
|
|
||||||
m_RowsetSize = 0;
|
|
||||||
|
|
||||||
} // endif m_RowsetSize
|
|
||||||
|
|
||||||
} // end of OnSetOptions
|
|
||||||
#endif // 0
|
|
||||||
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
/* Utility routine. */
|
/* Utility routine. */
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
@@ -1007,7 +814,7 @@ int JDBConn::Open(PJPARM sop)
|
|||||||
#define N 1
|
#define N 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Java source will be compiled as ajar file installed in the plugin dir
|
// Java source will be compiled as a jar file installed in the plugin dir
|
||||||
jpop->Append(sep);
|
jpop->Append(sep);
|
||||||
jpop->Append(GetPluginDir());
|
jpop->Append(GetPluginDir());
|
||||||
jpop->Append("JdbcInterface.jar");
|
jpop->Append("JdbcInterface.jar");
|
||||||
|
@@ -595,7 +595,7 @@ PSZ Serialize(PGLOBAL g, PJSON jsp, char *fn, int pretty)
|
|||||||
fputs(EL, fs);
|
fputs(EL, fs);
|
||||||
fclose(fs);
|
fclose(fs);
|
||||||
str = (err) ? NULL : strcpy(g->Message, "Ok");
|
str = (err) ? NULL : strcpy(g->Message, "Ok");
|
||||||
} else if (!err) {
|
} else if (!err) {
|
||||||
str = ((JOUTSTR*)jp)->Strp;
|
str = ((JOUTSTR*)jp)->Strp;
|
||||||
jp->WriteChr('\0');
|
jp->WriteChr('\0');
|
||||||
PlugSubAlloc(g, NULL, ((JOUTSTR*)jp)->N);
|
PlugSubAlloc(g, NULL, ((JOUTSTR*)jp)->N);
|
||||||
@@ -767,7 +767,7 @@ bool JOUTSTR::Escape(const char *s)
|
|||||||
{
|
{
|
||||||
WriteChr('"');
|
WriteChr('"');
|
||||||
|
|
||||||
for (unsigned int i = 0; i < strlen(s); i++)
|
for (unsigned int i = 0; s[i]; i++)
|
||||||
switch (s[i]) {
|
switch (s[i]) {
|
||||||
case '"':
|
case '"':
|
||||||
case '\\':
|
case '\\':
|
||||||
@@ -816,7 +816,7 @@ bool JOUTFILE::Escape(const char *s)
|
|||||||
// This is temporary
|
// This is temporary
|
||||||
fputc('"', Stream);
|
fputc('"', Stream);
|
||||||
|
|
||||||
for (unsigned int i = 0; i < strlen(s); i++)
|
for (unsigned int i = 0; s[i]; i++)
|
||||||
switch (s[i]) {
|
switch (s[i]) {
|
||||||
case '"': fputs("\\\"", Stream); break;
|
case '"': fputs("\\\"", Stream); break;
|
||||||
case '\\': fputs("\\\\", Stream); break;
|
case '\\': fputs("\\\\", Stream); break;
|
||||||
|
@@ -109,19 +109,7 @@ PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char *tab, char *db, bool info);
|
|||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
char *GetPluginDir(void)
|
char *GetPluginDir(void)
|
||||||
{
|
{
|
||||||
char *plugin_dir;
|
return opt_plugin_dir;
|
||||||
|
|
||||||
#if defined(_WIN64)
|
|
||||||
plugin_dir = (char *)GetProcAddress(GetModuleHandle(NULL),
|
|
||||||
"?opt_plugin_dir@@3PADEA");
|
|
||||||
#elif defined(_WIN32)
|
|
||||||
plugin_dir = (char*)GetProcAddress(GetModuleHandle(NULL),
|
|
||||||
"?opt_plugin_dir@@3PADA");
|
|
||||||
#else
|
|
||||||
plugin_dir = opt_plugin_dir;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return plugin_dir;
|
|
||||||
} // end of GetPluginDir
|
} // end of GetPluginDir
|
||||||
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
|
@@ -294,7 +294,7 @@ int TABDEF::GetColCatInfo(PGLOBAL g)
|
|||||||
nlg+= nof;
|
nlg+= nof;
|
||||||
case TAB_DIR:
|
case TAB_DIR:
|
||||||
case TAB_XML:
|
case TAB_XML:
|
||||||
poff= loff + 1;
|
poff= loff + (pcf->Flags & U_VIRTUAL ? 0 : 1);
|
||||||
break;
|
break;
|
||||||
case TAB_INI:
|
case TAB_INI:
|
||||||
case TAB_MAC:
|
case TAB_MAC:
|
||||||
|
Reference in New Issue
Block a user