- Enable MYSQL tables to USE result instead of STORE result.
See the issue reported in MDEV-6142. modified: storage/connect/myconn.cpp storage/connect/myconn.h storage/connect/tabmysql.cpp storage/connect/tabmysql.h
This commit is contained in:
parent
24369d2175
commit
f3af6da976
@ -31,6 +31,10 @@
|
||||
/* */
|
||||
/************************************************************************/
|
||||
#include "my_global.h"
|
||||
#if !defined(MYSQL_PREPARED_STATEMENTS)
|
||||
#include "my_sys.h"
|
||||
#include "mysqld_error.h"
|
||||
#endif // !MYSQL_PREPARED_STATEMENTS
|
||||
#if defined(WIN32)
|
||||
//#include <windows.h>
|
||||
#else // !WIN32
|
||||
@ -59,6 +63,59 @@ uint GetDefaultPort(void)
|
||||
return mysqld_port;
|
||||
} // end of GetDefaultPort
|
||||
|
||||
#if !defined(MYSQL_PREPARED_STATEMENTS)
|
||||
/**************************************************************************
|
||||
Alloc struct for use with unbuffered reads. Data is fetched by domand
|
||||
when calling to mysql_fetch_row.
|
||||
mysql_data_seek is a noop.
|
||||
|
||||
No other queries may be specified with the same MYSQL handle.
|
||||
There shouldn't be much processing per row because mysql server shouldn't
|
||||
have to wait for the client (and will not wait more than 30 sec/packet).
|
||||
NOTE: copied from client.c cli_use_result
|
||||
**************************************************************************/
|
||||
static MYSQL_RES *connect_use_result(MYSQL *mysql)
|
||||
{
|
||||
MYSQL_RES *result;
|
||||
DBUG_ENTER("connect_use_result");
|
||||
|
||||
if (!mysql->fields)
|
||||
DBUG_RETURN(NULL);
|
||||
|
||||
if (mysql->status != MYSQL_STATUS_GET_RESULT) {
|
||||
my_message(ER_UNKNOWN_ERROR, "Command out of sync", MYF(0));
|
||||
DBUG_RETURN(NULL);
|
||||
} // endif status
|
||||
|
||||
if (!(result = (MYSQL_RES*) my_malloc(sizeof(*result) +
|
||||
sizeof(ulong) * mysql->field_count,
|
||||
MYF(MY_WME | MY_ZEROFILL))))
|
||||
DBUG_RETURN(NULL);
|
||||
|
||||
result->lengths = (ulong*)(result+1);
|
||||
result->methods = mysql->methods;
|
||||
|
||||
/* Ptrs: to one row */
|
||||
if (!(result->row = (MYSQL_ROW)my_malloc(sizeof(result->row[0]) *
|
||||
(mysql->field_count+1), MYF(MY_WME)))) {
|
||||
my_free(result);
|
||||
DBUG_RETURN(NULL);
|
||||
} // endif row
|
||||
|
||||
result->fields = mysql->fields;
|
||||
result->field_alloc = mysql->field_alloc;
|
||||
result->field_count = mysql->field_count;
|
||||
result->current_field = 0;
|
||||
result->handle = mysql;
|
||||
result->current_row = 0;
|
||||
mysql->fields = 0; /* fields is now in result */
|
||||
clear_alloc_root(&mysql->field_alloc);
|
||||
mysql->status = MYSQL_STATUS_USE_RESULT;
|
||||
mysql->unbuffered_fetch_owner = &result->unbuffered_fetch_cancelled;
|
||||
DBUG_RETURN(result); /* Data is ready to be fetched */
|
||||
} // end of connect_use_result
|
||||
#endif // !MYSQL_PREPARED_STATEMENTS
|
||||
|
||||
/************************************************************************/
|
||||
/* MyColumns: constructs the result blocks containing all columns */
|
||||
/* of a MySQL table or view. */
|
||||
@ -339,6 +396,7 @@ MYSQLC::MYSQLC(void)
|
||||
m_Row = NULL;
|
||||
m_Fields = -1;
|
||||
N = 0;
|
||||
m_Use = false;
|
||||
} // end of MYSQLC constructor
|
||||
|
||||
/***********************************************************************/
|
||||
@ -600,7 +658,16 @@ int MYSQLC::ExecSQL(PGLOBAL g, const char *query, int *w)
|
||||
rc = RC_FX;
|
||||
//} else if (mysql_field_count(m_DB) > 0) {
|
||||
} else if (m_DB->field_count > 0) {
|
||||
if (!(m_Res = mysql_store_result(m_DB))) {
|
||||
if (m_Use)
|
||||
#if defined(MYSQL_PREPARED_STATEMENTS)
|
||||
m_Res = mysql_use_result(m_DB);
|
||||
#else // !MYSQL_PREPARED_STATEMENTS)
|
||||
m_Res = connect_use_result(m_DB);
|
||||
#endif // !MYSQL_PREPARED_STATEMENTS
|
||||
else
|
||||
m_Res = mysql_store_result(m_DB);
|
||||
|
||||
if (!m_Res) {
|
||||
char *msg = (char*)PlugSubAlloc(g, NULL, 512 + strlen(query));
|
||||
|
||||
sprintf(msg, "mysql_store_result failed: %s", mysql_error(m_DB));
|
||||
@ -609,7 +676,7 @@ int MYSQLC::ExecSQL(PGLOBAL g, const char *query, int *w)
|
||||
rc = RC_FX;
|
||||
} else {
|
||||
m_Fields = mysql_num_fields(m_Res);
|
||||
m_Rows = (int)mysql_num_rows(m_Res);
|
||||
m_Rows = (!m_Use) ? (int)mysql_num_rows(m_Res) : 0;
|
||||
} // endif m_Res
|
||||
|
||||
} else {
|
||||
|
@ -96,5 +96,6 @@ class DllItem MYSQLC {
|
||||
int N;
|
||||
int m_Fields; // The number of result fields
|
||||
int m_Afrw; // The number of affected rows
|
||||
bool m_Use; // Use or store result set
|
||||
}; // end of class MYSQLC
|
||||
|
||||
|
@ -84,10 +84,11 @@ MYSQLDEF::MYSQLDEF(void)
|
||||
Username = NULL;
|
||||
Password = NULL;
|
||||
Portnumber = 0;
|
||||
Isview = FALSE;
|
||||
Bind = FALSE;
|
||||
Delayed = FALSE;
|
||||
Xsrc = FALSE;
|
||||
Isview = false;
|
||||
Bind = false;
|
||||
Delayed = false;
|
||||
Xsrc = false;
|
||||
Huge = false;
|
||||
} // end of MYSQLDEF constructor
|
||||
|
||||
/***********************************************************************/
|
||||
@ -329,7 +330,7 @@ bool MYSQLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
|
||||
} else {
|
||||
// MYSQL access from a PROXY table
|
||||
Database = GetStringCatInfo(g, "Database", "*");
|
||||
Isview = GetBoolCatInfo("View", FALSE);
|
||||
Isview = GetBoolCatInfo("View", false);
|
||||
|
||||
// We must get other connection parms from the calling table
|
||||
Remove_tshp(Cat);
|
||||
@ -363,7 +364,8 @@ bool MYSQLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
|
||||
// Specific for command executing tables
|
||||
Xsrc = GetBoolCatInfo("Execsrc", false);
|
||||
Mxr = GetIntCatInfo("Maxerr", 0);
|
||||
return FALSE;
|
||||
Huge = GetBoolCatInfo("Huge", false);
|
||||
return false;
|
||||
} // end of DefineAM
|
||||
|
||||
/***********************************************************************/
|
||||
@ -401,6 +403,7 @@ TDBMYSQL::TDBMYSQL(PMYDEF tdp) : TDBASE(tdp)
|
||||
Isview = tdp->Isview;
|
||||
Prep = tdp->Bind;
|
||||
Delayed = tdp->Delayed;
|
||||
Myc.m_Use = tdp->Huge;
|
||||
} else {
|
||||
Host = NULL;
|
||||
Database = NULL;
|
||||
@ -412,15 +415,15 @@ TDBMYSQL::TDBMYSQL(PMYDEF tdp) : TDBASE(tdp)
|
||||
Qrystr = NULL;
|
||||
Quoted = 0;
|
||||
Port = 0;
|
||||
Isview = FALSE;
|
||||
Prep = FALSE;
|
||||
Delayed = FALSE;
|
||||
Isview = false;
|
||||
Prep = false;
|
||||
Delayed = false;
|
||||
} // endif tdp
|
||||
|
||||
Bind = NULL;
|
||||
Query = NULL;
|
||||
Qbuf = NULL;
|
||||
Fetched = FALSE;
|
||||
Fetched = false;
|
||||
m_Rc = RC_FX;
|
||||
AftRows = 0;
|
||||
N = -1;
|
||||
@ -555,17 +558,17 @@ bool TDBMYSQL::MakeInsert(PGLOBAL g)
|
||||
char *colist, *valist = NULL;
|
||||
char *tk = "`";
|
||||
int len = 0, qlen = 0;
|
||||
bool b = FALSE;
|
||||
bool b = false;
|
||||
PCOL colp;
|
||||
|
||||
if (Query)
|
||||
return FALSE; // already done
|
||||
return false; // already done
|
||||
|
||||
for (colp = Columns; colp; colp = colp->GetNext())
|
||||
if (!colp->IsSpecial()) {
|
||||
// if (colp->IsSpecial()) {
|
||||
// strcpy(g->Message, MSG(NO_SPEC_COL));
|
||||
// return TRUE;
|
||||
// return true;
|
||||
// } else {
|
||||
len += (strlen(colp->GetName()) + 4);
|
||||
((PMYCOL)colp)->Rank = Nparm++;
|
||||
@ -581,7 +584,7 @@ bool TDBMYSQL::MakeInsert(PGLOBAL g)
|
||||
#else // !MYSQL_PREPARED_STATEMENTS
|
||||
strcpy(g->Message, "Prepared statements not used (not supported)");
|
||||
PushWarning(g, this);
|
||||
Prep = FALSE;
|
||||
Prep = false;
|
||||
#endif // !MYSQL_PREPARED_STATEMENTS
|
||||
} // endif Prep
|
||||
|
||||
@ -590,7 +593,7 @@ bool TDBMYSQL::MakeInsert(PGLOBAL g)
|
||||
strcat(colist, ", ");
|
||||
if (Prep) strcat(valist, ",");
|
||||
} else
|
||||
b = TRUE;
|
||||
b = true;
|
||||
|
||||
strcat(strcat(strcat(colist, tk), colp->GetName()), tk);
|
||||
|
||||
@ -628,7 +631,7 @@ bool TDBMYSQL::MakeInsert(PGLOBAL g)
|
||||
Qbuf = (char *)PlugSubAlloc(g, NULL, qlen);
|
||||
} // endelse Prep
|
||||
|
||||
return FALSE;
|
||||
return false;
|
||||
} // end of MakeInsert
|
||||
|
||||
/***********************************************************************/
|
||||
@ -906,9 +909,9 @@ bool TDBMYSQL::SetColumnRanks(PGLOBAL g)
|
||||
{
|
||||
for (PCOL colp = Columns; colp; colp = colp->GetNext())
|
||||
if (((PMYCOL)colp)->FindRank(g))
|
||||
return TRUE;
|
||||
return true;
|
||||
|
||||
return FALSE;
|
||||
return false;
|
||||
} // end of SetColumnRanks
|
||||
|
||||
/***********************************************************************/
|
||||
@ -1233,7 +1236,7 @@ bool MYSQLCOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check)
|
||||
{
|
||||
if (!(To_Val = value)) {
|
||||
sprintf(g->Message, MSG(VALUE_ERROR), Name);
|
||||
return TRUE;
|
||||
return true;
|
||||
} else if (Buf_Type == value->GetType()) {
|
||||
// Values are of the (good) column type
|
||||
if (Buf_Type == TYPE_DATE) {
|
||||
@ -1253,12 +1256,12 @@ bool MYSQLCOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check)
|
||||
if (check) {
|
||||
sprintf(g->Message, MSG(TYPE_VALUE_ERR), Name,
|
||||
GetTypeName(Buf_Type), GetTypeName(value->GetType()));
|
||||
return TRUE;
|
||||
return true;
|
||||
} // endif check
|
||||
|
||||
newval:
|
||||
if (InitValue(g)) // Allocate the matching value block
|
||||
return TRUE;
|
||||
return true;
|
||||
|
||||
} // endif's Value, Buf_Type
|
||||
|
||||
@ -1269,7 +1272,7 @@ bool MYSQLCOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check)
|
||||
|
||||
// Set the Column
|
||||
Status = (ok) ? BUF_EMPTY : BUF_NO;
|
||||
return FALSE;
|
||||
return false;
|
||||
} // end of SetBuffer
|
||||
|
||||
/***********************************************************************/
|
||||
@ -1317,7 +1320,7 @@ void MYSQLCOL::ReadColumn(PGLOBAL g)
|
||||
|
||||
longjmp(g->jumper[g->jump_level], 11);
|
||||
} else
|
||||
tdbp->Fetched = TRUE;
|
||||
tdbp->Fetched = true;
|
||||
|
||||
if ((buf = ((PTDBMY)To_Tdb)->Myc.GetCharField(Rank))) {
|
||||
if (trace > 1)
|
||||
@ -1354,7 +1357,7 @@ void MYSQLCOL::WriteColumn(PGLOBAL g)
|
||||
/* Do convert the column value if necessary. */
|
||||
/*********************************************************************/
|
||||
if (Value != To_Val)
|
||||
Value->SetValue_pval(To_Val, FALSE); // Convert the inserted value
|
||||
Value->SetValue_pval(To_Val, false); // Convert the inserted value
|
||||
|
||||
#if defined(MYSQL_PREPARED_STATEMENTS)
|
||||
if (((PTDBMY)To_Tdb)->Prep) {
|
||||
|
@ -58,10 +58,11 @@ class MYSQLDEF : public TABDEF {/* Logical table description */
|
||||
int Portnumber; /* MySQL port number (0 = default) */
|
||||
int Mxr; /* Maxerr for an Exec table */
|
||||
int Quoted; /* Identifier quoting level */
|
||||
bool Isview; /* TRUE if this table is a MySQL view */
|
||||
bool Isview; /* true if this table is a MySQL view */
|
||||
bool Bind; /* Use prepared statement on insert */
|
||||
bool Delayed; /* Delayed insert */
|
||||
bool Xsrc; /* Execution type */
|
||||
bool Huge; /* True for big table */
|
||||
}; // end of MYSQLDEF
|
||||
|
||||
/***********************************************************************/
|
||||
@ -84,7 +85,7 @@ class TDBMYSQL : public TDBASE {
|
||||
virtual int GetRecpos(void) {return N;}
|
||||
virtual int GetProgMax(PGLOBAL g);
|
||||
virtual void ResetDB(void) {N = 0;}
|
||||
virtual int RowNumber(PGLOBAL g, bool b = FALSE);
|
||||
virtual int RowNumber(PGLOBAL g, bool b = false);
|
||||
virtual bool IsView(void) {return Isview;}
|
||||
virtual PSZ GetServer(void) {return Server;}
|
||||
void SetDatabase(LPCSTR db) {Database = (char*)db;}
|
||||
|
Loading…
x
Reference in New Issue
Block a user