libsql: fix prepared statement result binding

This commit is contained in:
server
2026-04-13 20:49:57 +02:00
parent 54a4134bf7
commit 6061e43c20
2 changed files with 38 additions and 13 deletions

View File

@@ -30,6 +30,12 @@ void CStmt::Destroy()
free(m_puiParamLen);
m_puiParamLen = NULL;
}
m_vec_param.clear();
m_vec_result.clear();
m_vec_result_len.clear();
m_uiParamCount = 0;
m_uiResultCount = 0;
}
void CStmt::Error(const char * c_pszMsg)
@@ -41,6 +47,8 @@ bool CStmt::Prepare(CAsyncSQL * sql, const char * c_pszQuery)
{
m_pkStmt = mysql_stmt_init(sql->GetSQLHandle());
m_stQuery = c_pszQuery;
m_uiParamCount = 0;
m_uiResultCount = 0;
if (mysql_stmt_prepare(m_pkStmt, m_stQuery.c_str(), m_stQuery.length()))
{
@@ -48,11 +56,7 @@ bool CStmt::Prepare(CAsyncSQL * sql, const char * c_pszQuery)
return false;
}
int iParamCount = 0;
for (unsigned int i = 0; i < m_stQuery.length(); ++i)
if (c_pszQuery[i] == '?')
++iParamCount;
const auto iParamCount = mysql_stmt_param_count(m_pkStmt);
if (iParamCount)
{
@@ -62,13 +66,12 @@ bool CStmt::Prepare(CAsyncSQL * sql, const char * c_pszQuery)
m_puiParamLen = (long unsigned int *) calloc(iParamCount, sizeof(long unsigned int));
}
m_vec_result.resize(48);
memset(&m_vec_result[0], 0, sizeof(MYSQL_BIND) * 48);
if (mysql_stmt_bind_result(m_pkStmt, &m_vec_result[0]))
const auto iFieldCount = mysql_stmt_field_count(m_pkStmt);
if (iFieldCount)
{
Error("mysql_stmt_bind_result");
return 0;
m_vec_result.resize(iFieldCount);
memset(&m_vec_result[0], 0, sizeof(MYSQL_BIND) * iFieldCount);
m_vec_result_len.resize(iFieldCount, 0);
}
return true;
@@ -114,6 +117,7 @@ bool CStmt::BindResult(enum_field_types type, void * p, int iMaxLen)
bind->buffer_type = type;
bind->buffer = (void *) p;
bind->buffer_length = iMaxLen;
bind->length = &m_vec_result_len[m_uiResultCount - 1];
return true;
}
@@ -130,9 +134,21 @@ int CStmt::Execute()
MYSQL_BIND * bind = &m_vec_param[i];
if (bind->buffer_type == MYSQL_TYPE_STRING)
{
*(m_puiParamLen + i) = strlen((const char *) bind->buffer);
sys_log(0, "param %d len %d buf %s", i, *m_puiParamLen, (const char *) bind->buffer);
}
if (!m_vec_result.empty())
{
if (m_uiResultCount != m_vec_result.size())
{
sys_log(0, "Result binding not enough %d, expected %d query: %s", m_uiResultCount, m_vec_result.size(), m_stQuery.c_str());
return 0;
}
if (mysql_stmt_bind_result(m_pkStmt, &m_vec_result[0]))
{
Error("mysql_stmt_bind_result");
return 0;
}
}
@@ -157,3 +173,10 @@ bool CStmt::Fetch()
return !mysql_stmt_fetch(m_pkStmt);
}
unsigned long CStmt::GetResultLength(unsigned int index) const
{
if (index >= m_vec_result_len.size())
return 0;
return m_vec_result_len[index];
}

View File

@@ -17,6 +17,7 @@ class CStmt
bool BindResult(enum_field_types type, void * p, int iMaxLen=0);
int Execute();
bool Fetch();
unsigned long GetResultLength(unsigned int index) const;
void Error(const char * c_pszMsg);
@@ -35,6 +36,7 @@ class CStmt
long unsigned int * m_puiParamLen;
std::vector<MYSQL_BIND> m_vec_result;
std::vector<unsigned long> m_vec_result_len;
unsigned int m_uiResultCount;
};