Commit f3af6da9 authored by Olivier Bertrand's avatar Olivier Bertrand

- 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
parent 24369d21
......@@ -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;}
......
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