diff --git a/storage/connect/myconn.cpp b/storage/connect/myconn.cpp index 5a36d157b65..0964e0c0bbb 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 #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 e8551b820e9..213929be156 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,8 +584,8 @@ bool TDBMYSQL::MakeInsert(PGLOBAL g) #else // !MYSQL_PREPARED_STATEMENTS strcpy(g->Message, "Prepared statements not used (not supported)"); PushWarning(g, this); - Prep = FALSE; -#endif // !MYSQL_PREPARED_STATEMENTS + Prep = false; +#endif // !MYSQL_PREPARED_STATEMENTS } // endif Prep for (colp = Columns; colp; colp = colp->GetNext()) { @@ -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 /***********************************************************************/ @@ -1234,7 +1237,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) { @@ -1254,12 +1257,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 @@ -1270,7 +1273,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 /***********************************************************************/ @@ -1318,7 +1321,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) @@ -1355,7 +1358,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;} diff --git a/storage/connect/xindex.cpp b/storage/connect/xindex.cpp index 2a7a10528fb..50d19ac67fc 100755 --- a/storage/connect/xindex.cpp +++ b/storage/connect/xindex.cpp @@ -282,25 +282,25 @@ int XINDEX::Qcompare(int *i1, int *i2) return k; } // end of Qcompare -/***********************************************************************/ -/* AddColumns: here we try to determine whether it is worthwhile to */ -/* add to the keys the values of the columns selected for this table. */ -/* Sure enough, it is done while records are read and permit to avoid */ -/* reading the table while doing the join (Dynamic index only) */ -/***********************************************************************/ -bool XINDEX::AddColumns(void) - { - if (!Dynamic) - return false; // Not applying to static index - else if (IsMul()) - return false; // Not done yet for multiple index - else if (Tbxp->GetAmType() == TYPE_AM_VCT && ((PTDBVCT)Tbxp)->IsSplit()) - return false; // This would require to read additional files - else - return true; - - } // end of AddColumns - +/***********************************************************************/ +/* AddColumns: here we try to determine whether it is worthwhile to */ +/* add to the keys the values of the columns selected for this table. */ +/* Sure enough, it is done while records are read and permit to avoid */ +/* reading the table while doing the join (Dynamic index only) */ +/***********************************************************************/ +bool XINDEX::AddColumns(void) + { + if (!Dynamic) + return false; // Not applying to static index + else if (IsMul()) + return false; // Not done yet for multiple index + else if (Tbxp->GetAmType() == TYPE_AM_VCT && ((PTDBVCT)Tbxp)->IsSplit()) + return false; // This would require to read additional files + else + return true; + + } // end of AddColumns + /***********************************************************************/ /* Make: Make and index on key column(s). */ /***********************************************************************/ @@ -378,48 +378,48 @@ bool XINDEX::Make(PGLOBAL g, PIXDEF sxp) To_LastCol = prev; - if (AddColumns()) { - PCOL kolp = To_Cols[0]; // Temporary while imposing Nk = 1 - - i = 0; - - // Allocate the accompanying - for (colp = Tbxp->GetColumns(); colp; colp = colp->GetNext()) { - // Count how many columns to add -// for (k = 0; k < Nk; k++) -// if (colp == To_Cols[k]) -// break; - -// if (k == nk) - if (colp != kolp) - i++; - - } // endfor colp - - if (i && i < 10) // Should be a parameter - for (colp = Tbxp->GetColumns(); colp; colp = colp->GetNext()) { -// for (k = 0; k < Nk; k++) -// if (colp == To_Cols[k]) -// break; - -// if (k < nk) - if (colp == kolp) - continue; // This is a key column - - kcp = new(g) KXYCOL(this); - - if (kcp->Init(g, colp, n, true, NULL)) - return true; - - if (trace) - htrc("Adding colp=%p Buf_Type=%d size=%d\n", - colp, colp->GetResultType(), n); - - prev->Next = kcp; - prev = kcp; - } // endfor colp - - } // endif AddColumns + if (AddColumns()) { + PCOL kolp = To_Cols[0]; // Temporary while imposing Nk = 1 + + i = 0; + + // Allocate the accompanying + for (colp = Tbxp->GetColumns(); colp; colp = colp->GetNext()) { + // Count how many columns to add +// for (k = 0; k < Nk; k++) +// if (colp == To_Cols[k]) +// break; + +// if (k == nk) + if (colp != kolp) + i++; + + } // endfor colp + + if (i && i < 10) // Should be a parameter + for (colp = Tbxp->GetColumns(); colp; colp = colp->GetNext()) { +// for (k = 0; k < Nk; k++) +// if (colp == To_Cols[k]) +// break; + +// if (k < nk) + if (colp == kolp) + continue; // This is a key column + + kcp = new(g) KXYCOL(this); + + if (kcp->Init(g, colp, n, true, NULL)) + return true; + + if (trace) + htrc("Adding colp=%p Buf_Type=%d size=%d\n", + colp, colp->GetResultType(), n); + + prev->Next = kcp; + prev = kcp; + } // endfor colp + + } // endif AddColumns #if 0 /*********************************************************************/ diff --git a/storage/connect/xindex.h b/storage/connect/xindex.h index 50f8282e5c3..75ced0c85a8 100644 --- a/storage/connect/xindex.h +++ b/storage/connect/xindex.h @@ -278,7 +278,7 @@ class DllExport XINDEX : public XXBASE { bool GetAllSizes(PGLOBAL g, int &ndif, int &numk); protected: - bool AddColumns(void); + bool AddColumns(void); bool NextValDif(void); // Members