Bug #80614 C API doc / mysql_stmt_bind_result
Submitted: 4 Mar 2016 10:08 Modified: 9 Mar 2016 11:51
Reporter: Artur Södler Email Updates:
Status: Verified Impact on me:
None 
Category:MySQL Server: C API (client library) Severity:S3 (Non-critical)
Version:5.7.11 OS:Microsoft Windows (XP)
Assigned to: CPU Architecture:Any

[4 Mar 2016 10:08] Artur Södler
Description:
Please document that mysql_stmt_bind_result() is copying bind[] data (but not bind[].buffer[]). Respectively that it is NOT copying bind[] data, if so, and in which versions.

This helps to understand two important points:
1. Changes to the bind[] data after the call to mysql_stmt_bind_result() have no effect.
2. The struct st_mysql_bind members length_value, is_null_value and error_value cannot be returned, unless you set the length, is_null and error members or call mysql_stmt_fetch_column().

Please note that the source code says explicitly that length_value is not used if length is not NULL — implying it *was* used if length is NULL.

Thank you.

How to repeat:
Show the behaviour by deleting line 26 of the following code snippet:

switch (mysql_stmt_fetch (m_pStmt)) {
default: MyFail();
case 1: MyThrowMysql ("mysql_stmt_fetch");
case MYSQL_NO_DATA: m_bEof = true; return false;
case MYSQL_DATA_TRUNCATED:
   {
      MYSQL_BIND *pb = m_pBindOut;
      for (size_t i=0; i<nNumFieldsOut; ++i) {
         if (pb->error_value) {
            unsigned long nLen = pb->length_value;
            unsigned long nOffset = pb->buffer_length; // save the already received part
            char *p = new char [nLen];
            memcpy (p, pb->buffer, nOffset); // save the already received part
            delete [] (char *) pb->buffer;
            pb->buffer = p + nOffset;
            pb->buffer_length = nLen - nOffset;
            if (mysql_stmt_fetch_column (m_pStmt, pb, i, nOffset))
               MyThrowMysql ("mysql_stmt_fetch_column");
            pb->buffer = p;
            pb->buffer_length = nLen;
         }
         ++pb;
      }
   }
   // skip this bind_result call to reproduce:
   if (mysql_stmt_bind_result (m_pStmt, m_pBindOut))
      MyThrowMysql ("mysql_stmt_bind_result");
case 0: break;
}

Suggested fix:
Suggestion 1:

Original doc text: "mysql_stmt_bind_result() is used to associate (that is, bind) output columns in the result set to data buffers and length buffers."

Add: "Internally, mysql_stmt_bind_result() keeps a copy of the bind[] array. You may delete the bind array passed to mysql_stmt_bind_result() immediately after the call."

And/or add: "To update any bind information in the middle of a sequence of fetches, you must call mysql_stmt_bind_result() again."

Suggestion 2:

mysql.h: "length, is_null and error MUST NOT be NULL for use in mysql_stmt_bind_result()."
[9 Mar 2016 11:51] Chiranjeevi Battula
Hello Artur Södler,

Thank you for the bug report.
Verified based on internal discussion with dev's.

Thanks,
Chiranjeevi