Trying to run the following
std::wstring query1 = L"SELECT st.table_id FROM information_schema.INNODB_TABLES st WHERE st.name = ?;";
or
std::wstring query1 = L"SELECT st.table_id FROM information_schema.INNODB_TABLES st WHERE st.name = CONCAT(?, '/', ?);";
returns SQL_NO_DATA
, but if the parameter is spelled out the record is returned.
Code is as follows:
auto res1 = mysql_stmt_init( m_db );
if( !res1 )
{
std::wstring err = m_pimpl->m_myconv.from_bytes( mysql_stmt_error( res1 ) );
errors.push_back( err );
result = 1;
}
else
{
if( mysql_stmt_prepare( res1, m_pimpl->m_myconv.to_bytes( query1.c_str() ).c_str(), query1.length() ) )
{
std::wstring err = m_pimpl->m_myconv.from_bytes( mysql_stmt_error( res1 ) );
errors.push_back( err );
result = 1;
}
else
{
MYSQL_BIND params[2];
unsigned long str_length1, str_length2;
str_length1 = strlen( m_pimpl->m_myconv.to_bytes( schema.c_str() ) .c_str() ) * 2;
str_length2 = strlen( m_pimpl->m_myconv.to_bytes( table.c_str() ).c_str() ) * 2;
char *str_data1 = new char[str_length1], *str_data2 = new char[str_length2];
memset( str_data1, '\0', str_length1 );
memset( str_data2, '\0', str_length2 );
memset( params, 0, sizeof( params ) );
strncpy( str_data1, m_pimpl->m_myconv.to_bytes( schema.c_str() ) .c_str(), str_length1 );
strncpy( str_data2, m_pimpl->m_myconv.to_bytes( table.c_str() ).c_str(), str_length2 );
params[0].buffer_type = MYSQL_TYPE_STRING;
params[0].buffer = (char *) str_data1;
params[0].buffer_length = strlen( str_data1 );
params[0].is_null = 0;
params[0].length = &str_length1;
params[1].buffer_type = MYSQL_TYPE_STRING;
params[1].buffer = (char *) str_data2;
params[1].buffer_length = strlen( str_data2 );
params[1].is_null = 0;
params[1].length = &str_length2;
if( mysql_stmt_bind_param( res1, params ) )
{
std::wstring err = m_pimpl->m_myconv.from_bytes( mysql_stmt_error( res1 ) );
errors.push_back( err );
result = 1;
}
else
{
auto prepare_meta_result = mysql_stmt_result_metadata( res1 );
if( !prepare_meta_result )
{
std::wstring err = m_pimpl->m_myconv.from_bytes( mysql_stmt_error( res1 ) );
errors.push_back( err );
result = 1;
}
else
{
if( mysql_stmt_execute( res1 ) )
{
std::wstring err = m_pimpl->m_myconv.from_bytes( mysql_stmt_error( res1 ) );
errors.push_back( err );
result = 1;
}
else
{
MYSQL_BIND results1[1];
bool is_null[1], error[1];
unsigned long length[1];
memset( results1, 0, sizeof( results1 ) );
results1[0].buffer_type = MYSQL_TYPE_LONG;
results1[0].buffer = (char *) &tableId;
results1[0].is_null = &is_null[1];
results1[0].error = &error[1];
results1[0].length = &length[1];
if( mysql_stmt_bind_result( res1, results1 ) )
{
std::wstring err = m_pimpl->m_myconv.from_bytes( mysql_stmt_error( res1 ) );
errors.push_back( err );
result = 1;
}
else
{
while( true )
{
auto dataset = mysql_stmt_fetch( res1 );
if( dataset == 1 || dataset == MYSQL_NO_DATA )
break;
else
id = tableId;
}
mysql_free_result( prepare_meta_result );
}
}
}
}
}
}
if( mysql_stmt_close( res1 ) )
{
std::wstring err = m_pimpl->m_myconv.from_bytes( mysql_stmt_error( res1 ) );
errors.push_back( err );
result = 1;
}
What am I missing?
I suspect you have a lifetime issue. Consider the following code:
You take your
wstring query1
(and WHY is it a wstring if you need it to be a std::string???), and pass it tom_pimpl->m_myconv.to_bytes
. I assume that function does the Unicode-to-ANSI translation and returns astd::string
. You then callc_str()
on that to get a buffer, and pass that tomysql_stmt_prepare
.HOWEVER, what
to_bytes
returns is a temporary. As soon as theif
statement exits, that string goes out of scope and will be destroyed, leaving the statement holding a pointer into nothing. I suggest you try:This has the additional benefit of letting you print the value of
query1s
to make sure it matches your expectation.Now, IF
mysql_stmt_prepare
actually copies the input string, instead of just grabbing a pointer, then this won't fix anything.