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()."
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()."