diff --git a/extensions/mysql/mysql/MyBoundResults.cpp b/extensions/mysql/mysql/MyBoundResults.cpp index bdd8ecc0..8d17a815 100644 --- a/extensions/mysql/mysql/MyBoundResults.cpp +++ b/extensions/mysql/mysql/MyBoundResults.cpp @@ -69,19 +69,14 @@ enum_field_types GetTheirType(DBType type) return MYSQL_TYPE_STRING; } -MyBoundResults::MyBoundResults(MYSQL_STMT *stmt, MYSQL_RES *res) -: m_stmt(stmt), m_pRes(res), m_Initialized(false), m_RowCount(0), m_CurRow(0) +MyBoundResults::MyBoundResults(MYSQL_STMT *stmt, MYSQL_RES *res, unsigned int num_fields) +: m_stmt(stmt), m_pRes(res), m_ColCount(num_fields), m_Initialized(false), m_RowCount(0), m_CurRow(0) { /** - * Important things to note here: - * 1) We're guaranteed at least one field. - * 2) The field information should never change, and thus we - * never rebuild it. If someone ALTERs the table during - * a prepared query's lifetime, it's their own death. + * Important thing to note here: + * We're guaranteed at least one field. */ - m_ColCount = (unsigned int)mysql_num_fields(m_pRes); - /* Allocate buffers */ m_bind = (MYSQL_BIND *)malloc(sizeof(MYSQL_BIND) * m_ColCount); m_pull = (ResultBind *)malloc(sizeof(ResultBind) * m_ColCount); diff --git a/extensions/mysql/mysql/MyBoundResults.h b/extensions/mysql/mysql/MyBoundResults.h index 92303f68..016420ba 100644 --- a/extensions/mysql/mysql/MyBoundResults.h +++ b/extensions/mysql/mysql/MyBoundResults.h @@ -55,7 +55,7 @@ class MyBoundResults : { friend class MyStatement; public: - MyBoundResults(MYSQL_STMT *stmt, MYSQL_RES *res); + MyBoundResults(MYSQL_STMT *stmt, MYSQL_RES *res, unsigned int num_fields); ~MyBoundResults(); public: //IResultSet unsigned int GetRowCount(); diff --git a/extensions/mysql/mysql/MyStatement.cpp b/extensions/mysql/mysql/MyStatement.cpp index b3b001a5..c95a6aca 100644 --- a/extensions/mysql/mysql/MyStatement.cpp +++ b/extensions/mysql/mysql/MyStatement.cpp @@ -33,7 +33,7 @@ #include "MyBoundResults.h" MyStatement::MyStatement(MyDatabase *db, MYSQL_STMT *stmt) -: m_mysql(db->m_mysql), m_pParent(db), m_stmt(stmt), m_rs(NULL), m_Results(false) +: m_mysql(db->m_mysql), m_pParent(db), m_stmt(stmt), m_pRes(NULL), m_rs(NULL), m_Results(false) { m_Params = (unsigned int)mysql_stmt_param_count(m_stmt); @@ -48,14 +48,18 @@ MyStatement::MyStatement(MyDatabase *db, MYSQL_STMT *stmt) m_bind = NULL; } - m_pRes = mysql_stmt_result_metadata(stmt); m_Results = false; } MyStatement::~MyStatement() { + while (FetchMoreResults()) + { + /* Spin until all are gone */ + } + /* Free result set structures */ - delete m_rs; + ClearResults(); /* Free old blobs */ for (unsigned int i=0; im_mysql)) { + return false; + } + + ClearResults(); + + if (mysql_stmt_next_result(m_stmt) != 0) + { + return false; + } + + /* the column count is > 0 if there is a result set + * 0 if the result is only the final status packet in CALL queries. */ - return false; + unsigned int num_fields = mysql_stmt_field_count(m_stmt); + if (num_fields == 0) + { + return false; + } + + /* Skip away if we don't have data */ + m_pRes = mysql_stmt_result_metadata(m_stmt); + if (!m_pRes) + { + return false; + } + + /* If we don't have a result manager, create one. */ + if (!m_rs) + { + m_rs = new MyBoundResults(m_stmt, m_pRes, num_fields); + } + + /* Tell the result set to update its bind info, + * and initialize itself if necessary. + */ + if (!(m_Results = m_rs->Initialize())) + { + return false; + } + + /* Try precaching the results. */ + m_Results = (mysql_stmt_store_result(m_stmt) == 0); + + /* Update now that the data is known. */ + m_rs->Update(); + + /* Return indicator */ + return m_Results; } void *MyStatement::CopyBlob(unsigned int param, const void *blobptr, size_t length) @@ -211,7 +275,13 @@ bool MyStatement::BindParamNull(unsigned int param) bool MyStatement::Execute() { /* Clear any past result first! */ - m_Results = false; + while (FetchMoreResults()) + { + /* Spin until all are gone */ + } + + /* Free result set structures */ + ClearResults(); /* Bind the parameters */ if (m_Params) @@ -227,17 +297,24 @@ bool MyStatement::Execute() return false; } + /* the column count is > 0 if there is a result set + * 0 if the result is only the final status packet in CALL queries. + */ + unsigned int num_fields = mysql_stmt_field_count(m_stmt); + if (num_fields == 0) + { + return true; + } + /* Skip away if we don't have data */ + m_pRes = mysql_stmt_result_metadata(m_stmt); if (!m_pRes) { return true; } - /* If we don't have a result manager, create one. */ - if (!m_rs) - { - m_rs = new MyBoundResults(m_stmt, m_pRes); - } + /* Create our result manager. */ + m_rs = new MyBoundResults(m_stmt, m_pRes, num_fields); /* Tell the result set to update its bind info, * and initialize itself if necessary. diff --git a/extensions/mysql/mysql/MyStatement.h b/extensions/mysql/mysql/MyStatement.h index c6e5ba82..7fce2894 100644 --- a/extensions/mysql/mysql/MyStatement.h +++ b/extensions/mysql/mysql/MyStatement.h @@ -67,6 +67,7 @@ public: //IPreparedQuery unsigned int GetInsertID(); private: void *CopyBlob(unsigned int param, const void *blobptr, size_t length); + void ClearResults(); private: MYSQL *m_mysql; ke::RefPtr m_pParent;