summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlivier Bertrand <bertrandop@gmail.com>2014-04-27 19:18:20 +0200
committerOlivier Bertrand <bertrandop@gmail.com>2014-04-27 19:18:20 +0200
commitf3af6da9765a4541d63de91e8a848d3c3116e957 (patch)
tree7d725fe7e7ac037890850614ae59c331769aa0aa
parent24369d217578bfc8140d0617169b6ad527e61e78 (diff)
downloadmariadb-git-f3af6da9765a4541d63de91e8a848d3c3116e957.tar.gz
- 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
-rw-r--r--storage/connect/myconn.cpp71
-rw-r--r--storage/connect/myconn.h1
-rw-r--r--storage/connect/tabmysql.cpp51
-rw-r--r--storage/connect/tabmysql.h5
4 files changed, 100 insertions, 28 deletions
diff --git a/storage/connect/myconn.cpp b/storage/connect/myconn.cpp
index 2e563dbaf1e..8700a24ac96 100644
--- a/storage/connect/myconn.cpp
+++ b/storage/connect/myconn.cpp
@@ -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 {
diff --git a/storage/connect/myconn.h b/storage/connect/myconn.h
index 5bfa58ffb0c..7e892eece34 100644
--- a/storage/connect/myconn.h
+++ b/storage/connect/myconn.h
@@ -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
diff --git a/storage/connect/tabmysql.cpp b/storage/connect/tabmysql.cpp
index a57c7b21c94..dea6978f73e 100644
--- a/storage/connect/tabmysql.cpp
+++ b/storage/connect/tabmysql.cpp
@@ -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) {
diff --git a/storage/connect/tabmysql.h b/storage/connect/tabmysql.h
index 0387fcc7da9..96991fb14c1 100644
--- a/storage/connect/tabmysql.h
+++ b/storage/connect/tabmysql.h
@@ -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;}