diff --git a/include/maxscale/query_classifier.hh b/include/maxscale/query_classifier.hh index aca6be8bc..b2bddc9cb 100644 --- a/include/maxscale/query_classifier.hh +++ b/include/maxscale/query_classifier.hh @@ -488,6 +488,19 @@ struct QUERY_CLASSIFIER * @return The result of the provided info. */ QC_STMT_RESULT (* qc_get_result_from_info)(const QC_STMT_INFO* info); + + /** + * Return statement currently being classified. + * + * @param ppStmp Pointer to pointer that on return will point to the + * statement being classified. + * @param pLen Pointer to value that on return will contain the length + * of the returned string. + * + * @return QC_RESULT_OK if a statement was returned (i.e. a statement is being + * classified), QC_RESULT_ERROR otherwise. + */ + int32_t (* qc_get_current_stmt)(const char** ppStmt, size_t* pLen); }; /** @@ -1034,3 +1047,20 @@ struct QC_CACHE_ENTRY * be added the hits of that key if it already is in the map. */ void qc_get_cache_state(std::map& state); + +/** + * Return statement currently being classified. + * + * @param ppStmp Pointer to pointer that on return will point to the + * statement being classified. + * @param pLen Pointer to value that on return will contain the length + * of the returned string. + * + * @return True, if a statement was returned (i.e. a statement is being + * classified), false otherwise. + * + * @note A string /may/ be returned /only/ when this function is called from + * a signal handler that is called due to the classifier causing + * a crash. + */ +bool qc_get_current_stmt(const char** ppStmt, size_t* pLen); diff --git a/query_classifier/qc_mysqlembedded/qc_mysqlembedded.cc b/query_classifier/qc_mysqlembedded/qc_mysqlembedded.cc index 743c4d525..766918919 100644 --- a/query_classifier/qc_mysqlembedded/qc_mysqlembedded.cc +++ b/query_classifier/qc_mysqlembedded/qc_mysqlembedded.cc @@ -3852,6 +3852,12 @@ int32_t qc_mysql_set_options(uint32_t options) return rv; } +int32_t qc_mysql_get_current_stmt(const char** ppStmt, size_t* pLen) +{ + return QC_RESULT_ERROR; +} + + /** * EXPORTS */ @@ -3890,6 +3896,7 @@ MXS_MODULE* MXS_CREATE_MODULE() qc_mysql_get_options, qc_mysql_set_options, nullptr, // qc_get_result_from_info not supported + qc_mysql_get_current_stmt }; static MXS_MODULE info = diff --git a/query_classifier/qc_sqlite/qc_sqlite.cc b/query_classifier/qc_sqlite/qc_sqlite.cc index 84288ecef..4ca2defe3 100644 --- a/query_classifier/qc_sqlite/qc_sqlite.cc +++ b/query_classifier/qc_sqlite/qc_sqlite.cc @@ -5446,6 +5446,20 @@ QC_STMT_RESULT qc_sqlite_get_result_from_info(const QC_STMT_INFO* pInfo) return static_cast(pInfo)->get_result(); } +int32_t qc_sqlite_get_current_stmt(const char** ppStmt, size_t* pLen) +{ + int32_t rv = QC_RESULT_ERROR; + + if (this_thread.pInfo && this_thread.pInfo->m_pQuery && (this_thread.pInfo->m_nQuery != 0)) + { + *ppStmt = this_thread.pInfo->m_pQuery; + *pLen = this_thread.pInfo->m_nQuery; + rv = QC_RESULT_OK; + } + + return rv; +} + /** * EXPORTS */ @@ -5484,6 +5498,7 @@ MXS_MODULE* MXS_CREATE_MODULE() qc_sqlite_get_options, qc_sqlite_set_options, qc_sqlite_get_result_from_info, + qc_sqlite_get_current_stmt }; static MXS_MODULE info = diff --git a/server/core/gateway.cc b/server/core/gateway.cc index 057e71377..a17f366e9 100644 --- a/server/core/gateway.cc +++ b/server/core/gateway.cc @@ -426,6 +426,17 @@ static void sigfatal_handler(int i) "Commit ID: %s System name: %s Release string: %s", MAXSCALE_VERSION, i, maxscale_commit, cnf->sysname, cnf->release_string); + const char* pStmt; + size_t nStmt; + + if (!qc_get_current_stmt(&pStmt, &nStmt)) + { + pStmt = "none/unknown"; + nStmt = strlen(pStmt); + } + + MXS_ALERT("Statement currently being classified: %.*s", (int)nStmt, pStmt); + if (DCB* dcb = dcb_get_current()) { if (dcb->session) diff --git a/server/core/query_classifier.cc b/server/core/query_classifier.cc index d85564037..1eb78efd3 100644 --- a/server/core/query_classifier.cc +++ b/server/core/query_classifier.cc @@ -1350,6 +1350,14 @@ bool qc_set_options(uint32_t options) return rv == QC_RESULT_OK; } +bool qc_get_current_stmt(const char** ppStmt, size_t* pLen) +{ + QC_TRACE(); + mxb_assert(this_unit.classifier); + + return this_unit.classifier->qc_get_current_stmt(ppStmt, pLen) == QC_RESULT_OK; +} + void qc_get_cache_properties(QC_CACHE_PROPERTIES* properties) { properties->max_size = this_unit.cache_max_size();