- 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:
Olivier Bertrand 2014-04-27 19:18:20 +02:00
parent 24369d2175
commit f3af6da976
4 changed files with 100 additions and 28 deletions

View File

@ -31,6 +31,10 @@
/* */ /* */
/************************************************************************/ /************************************************************************/
#include "my_global.h" #include "my_global.h"
#if !defined(MYSQL_PREPARED_STATEMENTS)
#include "my_sys.h"
#include "mysqld_error.h"
#endif // !MYSQL_PREPARED_STATEMENTS
#if defined(WIN32) #if defined(WIN32)
//#include <windows.h> //#include <windows.h>
#else // !WIN32 #else // !WIN32
@ -59,6 +63,59 @@ uint GetDefaultPort(void)
return mysqld_port; return mysqld_port;
} // end of GetDefaultPort } // 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 */ /* MyColumns: constructs the result blocks containing all columns */
/* of a MySQL table or view. */ /* of a MySQL table or view. */
@ -339,6 +396,7 @@ MYSQLC::MYSQLC(void)
m_Row = NULL; m_Row = NULL;
m_Fields = -1; m_Fields = -1;
N = 0; N = 0;
m_Use = false;
} // end of MYSQLC constructor } // end of MYSQLC constructor
/***********************************************************************/ /***********************************************************************/
@ -600,7 +658,16 @@ int MYSQLC::ExecSQL(PGLOBAL g, const char *query, int *w)
rc = RC_FX; rc = RC_FX;
//} else if (mysql_field_count(m_DB) > 0) { //} else if (mysql_field_count(m_DB) > 0) {
} else if (m_DB->field_count > 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)); char *msg = (char*)PlugSubAlloc(g, NULL, 512 + strlen(query));
sprintf(msg, "mysql_store_result failed: %s", mysql_error(m_DB)); 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; rc = RC_FX;
} else { } else {
m_Fields = mysql_num_fields(m_Res); 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 } // endif m_Res
} else { } else {

View File

@ -96,5 +96,6 @@ class DllItem MYSQLC {
int N; int N;
int m_Fields; // The number of result fields int m_Fields; // The number of result fields
int m_Afrw; // The number of affected rows int m_Afrw; // The number of affected rows
bool m_Use; // Use or store result set
}; // end of class MYSQLC }; // end of class MYSQLC

View File

@ -84,10 +84,11 @@ MYSQLDEF::MYSQLDEF(void)
Username = NULL; Username = NULL;
Password = NULL; Password = NULL;
Portnumber = 0; Portnumber = 0;
Isview = FALSE; Isview = false;
Bind = FALSE; Bind = false;
Delayed = FALSE; Delayed = false;
Xsrc = FALSE; Xsrc = false;
Huge = false;
} // end of MYSQLDEF constructor } // end of MYSQLDEF constructor
/***********************************************************************/ /***********************************************************************/
@ -329,7 +330,7 @@ bool MYSQLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
} else { } else {
// MYSQL access from a PROXY table // MYSQL access from a PROXY table
Database = GetStringCatInfo(g, "Database", "*"); Database = GetStringCatInfo(g, "Database", "*");
Isview = GetBoolCatInfo("View", FALSE); Isview = GetBoolCatInfo("View", false);
// We must get other connection parms from the calling table // We must get other connection parms from the calling table
Remove_tshp(Cat); Remove_tshp(Cat);
@ -363,7 +364,8 @@ bool MYSQLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
// Specific for command executing tables // Specific for command executing tables
Xsrc = GetBoolCatInfo("Execsrc", false); Xsrc = GetBoolCatInfo("Execsrc", false);
Mxr = GetIntCatInfo("Maxerr", 0); Mxr = GetIntCatInfo("Maxerr", 0);
return FALSE; Huge = GetBoolCatInfo("Huge", false);
return false;
} // end of DefineAM } // end of DefineAM
/***********************************************************************/ /***********************************************************************/
@ -401,6 +403,7 @@ TDBMYSQL::TDBMYSQL(PMYDEF tdp) : TDBASE(tdp)
Isview = tdp->Isview; Isview = tdp->Isview;
Prep = tdp->Bind; Prep = tdp->Bind;
Delayed = tdp->Delayed; Delayed = tdp->Delayed;
Myc.m_Use = tdp->Huge;
} else { } else {
Host = NULL; Host = NULL;
Database = NULL; Database = NULL;
@ -412,15 +415,15 @@ TDBMYSQL::TDBMYSQL(PMYDEF tdp) : TDBASE(tdp)
Qrystr = NULL; Qrystr = NULL;
Quoted = 0; Quoted = 0;
Port = 0; Port = 0;
Isview = FALSE; Isview = false;
Prep = FALSE; Prep = false;
Delayed = FALSE; Delayed = false;
} // endif tdp } // endif tdp
Bind = NULL; Bind = NULL;
Query = NULL; Query = NULL;
Qbuf = NULL; Qbuf = NULL;
Fetched = FALSE; Fetched = false;
m_Rc = RC_FX; m_Rc = RC_FX;
AftRows = 0; AftRows = 0;
N = -1; N = -1;
@ -555,17 +558,17 @@ bool TDBMYSQL::MakeInsert(PGLOBAL g)
char *colist, *valist = NULL; char *colist, *valist = NULL;
char *tk = "`"; char *tk = "`";
int len = 0, qlen = 0; int len = 0, qlen = 0;
bool b = FALSE; bool b = false;
PCOL colp; PCOL colp;
if (Query) if (Query)
return FALSE; // already done return false; // already done
for (colp = Columns; colp; colp = colp->GetNext()) for (colp = Columns; colp; colp = colp->GetNext())
if (!colp->IsSpecial()) { if (!colp->IsSpecial()) {
// if (colp->IsSpecial()) { // if (colp->IsSpecial()) {
// strcpy(g->Message, MSG(NO_SPEC_COL)); // strcpy(g->Message, MSG(NO_SPEC_COL));
// return TRUE; // return true;
// } else { // } else {
len += (strlen(colp->GetName()) + 4); len += (strlen(colp->GetName()) + 4);
((PMYCOL)colp)->Rank = Nparm++; ((PMYCOL)colp)->Rank = Nparm++;
@ -581,7 +584,7 @@ bool TDBMYSQL::MakeInsert(PGLOBAL g)
#else // !MYSQL_PREPARED_STATEMENTS #else // !MYSQL_PREPARED_STATEMENTS
strcpy(g->Message, "Prepared statements not used (not supported)"); strcpy(g->Message, "Prepared statements not used (not supported)");
PushWarning(g, this); PushWarning(g, this);
Prep = FALSE; Prep = false;
#endif // !MYSQL_PREPARED_STATEMENTS #endif // !MYSQL_PREPARED_STATEMENTS
} // endif Prep } // endif Prep
@ -590,7 +593,7 @@ bool TDBMYSQL::MakeInsert(PGLOBAL g)
strcat(colist, ", "); strcat(colist, ", ");
if (Prep) strcat(valist, ","); if (Prep) strcat(valist, ",");
} else } else
b = TRUE; b = true;
strcat(strcat(strcat(colist, tk), colp->GetName()), tk); strcat(strcat(strcat(colist, tk), colp->GetName()), tk);
@ -628,7 +631,7 @@ bool TDBMYSQL::MakeInsert(PGLOBAL g)
Qbuf = (char *)PlugSubAlloc(g, NULL, qlen); Qbuf = (char *)PlugSubAlloc(g, NULL, qlen);
} // endelse Prep } // endelse Prep
return FALSE; return false;
} // end of MakeInsert } // end of MakeInsert
/***********************************************************************/ /***********************************************************************/
@ -906,9 +909,9 @@ bool TDBMYSQL::SetColumnRanks(PGLOBAL g)
{ {
for (PCOL colp = Columns; colp; colp = colp->GetNext()) for (PCOL colp = Columns; colp; colp = colp->GetNext())
if (((PMYCOL)colp)->FindRank(g)) if (((PMYCOL)colp)->FindRank(g))
return TRUE; return true;
return FALSE; return false;
} // end of SetColumnRanks } // end of SetColumnRanks
/***********************************************************************/ /***********************************************************************/
@ -1233,7 +1236,7 @@ bool MYSQLCOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check)
{ {
if (!(To_Val = value)) { if (!(To_Val = value)) {
sprintf(g->Message, MSG(VALUE_ERROR), Name); sprintf(g->Message, MSG(VALUE_ERROR), Name);
return TRUE; return true;
} else if (Buf_Type == value->GetType()) { } else if (Buf_Type == value->GetType()) {
// Values are of the (good) column type // Values are of the (good) column type
if (Buf_Type == TYPE_DATE) { if (Buf_Type == TYPE_DATE) {
@ -1253,12 +1256,12 @@ bool MYSQLCOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check)
if (check) { if (check) {
sprintf(g->Message, MSG(TYPE_VALUE_ERR), Name, sprintf(g->Message, MSG(TYPE_VALUE_ERR), Name,
GetTypeName(Buf_Type), GetTypeName(value->GetType())); GetTypeName(Buf_Type), GetTypeName(value->GetType()));
return TRUE; return true;
} // endif check } // endif check
newval: newval:
if (InitValue(g)) // Allocate the matching value block if (InitValue(g)) // Allocate the matching value block
return TRUE; return true;
} // endif's Value, Buf_Type } // endif's Value, Buf_Type
@ -1269,7 +1272,7 @@ bool MYSQLCOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check)
// Set the Column // Set the Column
Status = (ok) ? BUF_EMPTY : BUF_NO; Status = (ok) ? BUF_EMPTY : BUF_NO;
return FALSE; return false;
} // end of SetBuffer } // end of SetBuffer
/***********************************************************************/ /***********************************************************************/
@ -1317,7 +1320,7 @@ void MYSQLCOL::ReadColumn(PGLOBAL g)
longjmp(g->jumper[g->jump_level], 11); longjmp(g->jumper[g->jump_level], 11);
} else } else
tdbp->Fetched = TRUE; tdbp->Fetched = true;
if ((buf = ((PTDBMY)To_Tdb)->Myc.GetCharField(Rank))) { if ((buf = ((PTDBMY)To_Tdb)->Myc.GetCharField(Rank))) {
if (trace > 1) if (trace > 1)
@ -1354,7 +1357,7 @@ void MYSQLCOL::WriteColumn(PGLOBAL g)
/* Do convert the column value if necessary. */ /* Do convert the column value if necessary. */
/*********************************************************************/ /*********************************************************************/
if (Value != To_Val) 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 defined(MYSQL_PREPARED_STATEMENTS)
if (((PTDBMY)To_Tdb)->Prep) { if (((PTDBMY)To_Tdb)->Prep) {

View File

@ -58,10 +58,11 @@ class MYSQLDEF : public TABDEF {/* Logical table description */
int Portnumber; /* MySQL port number (0 = default) */ int Portnumber; /* MySQL port number (0 = default) */
int Mxr; /* Maxerr for an Exec table */ int Mxr; /* Maxerr for an Exec table */
int Quoted; /* Identifier quoting level */ 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 Bind; /* Use prepared statement on insert */
bool Delayed; /* Delayed insert */ bool Delayed; /* Delayed insert */
bool Xsrc; /* Execution type */ bool Xsrc; /* Execution type */
bool Huge; /* True for big table */
}; // end of MYSQLDEF }; // end of MYSQLDEF
/***********************************************************************/ /***********************************************************************/
@ -84,7 +85,7 @@ class TDBMYSQL : public TDBASE {
virtual int GetRecpos(void) {return N;} virtual int GetRecpos(void) {return N;}
virtual int GetProgMax(PGLOBAL g); virtual int GetProgMax(PGLOBAL g);
virtual void ResetDB(void) {N = 0;} 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 bool IsView(void) {return Isview;}
virtual PSZ GetServer(void) {return Server;} virtual PSZ GetServer(void) {return Server;}
void SetDatabase(LPCSTR db) {Database = (char*)db;} void SetDatabase(LPCSTR db) {Database = (char*)db;}