qc: Add minimal support for qc_get_prepare_name
If the query is a PREPARE or EXECUTE statement, then qc_get_prepare_name will return the name of the prepared statement.
This commit is contained in:
parent
19e017e499
commit
7499c1e1bf
@ -17,7 +17,7 @@
|
||||
|
||||
MXS_BEGIN_DECLS
|
||||
|
||||
#define QUERY_CLASSIFIER_VERSION {1, 0, 0}
|
||||
#define QUERY_CLASSIFIER_VERSION {1, 1, 0}
|
||||
|
||||
/**
|
||||
* qc_query_type_t defines bits that provide information about a
|
||||
@ -115,6 +115,7 @@ typedef struct query_classifier
|
||||
bool (*qc_query_has_clause)(GWBUF* stmt);
|
||||
char* (*qc_get_affected_fields)(GWBUF* stmt);
|
||||
char** (*qc_get_database_names)(GWBUF* stmt, int* size);
|
||||
char* (*qc_get_prepare_name)(GWBUF* stmt);
|
||||
} QUERY_CLASSIFIER;
|
||||
|
||||
/**
|
||||
@ -266,6 +267,24 @@ char** qc_get_database_names(GWBUF* stmt, int* size);
|
||||
*/
|
||||
qc_query_op_t qc_get_operation(GWBUF* stmt);
|
||||
|
||||
/**
|
||||
* Returns the name of the prepared statement, if the statement
|
||||
* is a PREPARE or EXECUTE statement.
|
||||
*
|
||||
* @param stmt A buffer containing a COM_QUERY packet.
|
||||
*
|
||||
* @return The name of the prepared statement, if the statement
|
||||
* is a PREPARE or EXECUTE statement; otherwise NULL.
|
||||
*
|
||||
* @note The returned string @b must be freed by the caller.
|
||||
*
|
||||
* @note Even though a COM_STMT_PREPARE can be given to the query
|
||||
* classifier for parsing, this function will in that case
|
||||
* return NULL since the id of the statement is provided by
|
||||
* the server.
|
||||
*/
|
||||
char* qc_get_prepare_name(GWBUF* stmt);
|
||||
|
||||
/**
|
||||
* Returns the tables accessed by the statement.
|
||||
*
|
||||
|
@ -1904,6 +1904,21 @@ qc_query_op_t qc_get_operation(GWBUF* querybuf)
|
||||
return operation;
|
||||
}
|
||||
|
||||
char* qc_get_prepare_name(GWBUF* stmt)
|
||||
{
|
||||
char* name = NULL;
|
||||
|
||||
if (stmt)
|
||||
{
|
||||
if (ensure_query_is_parsed(stmt))
|
||||
{
|
||||
MXS_WARNING("qc_get_prepare_name not implemented yet.");
|
||||
}
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
@ -2048,6 +2063,7 @@ static QUERY_CLASSIFIER qc =
|
||||
qc_query_has_clause,
|
||||
qc_get_affected_fields,
|
||||
qc_get_database_names,
|
||||
qc_get_prepare_name,
|
||||
};
|
||||
|
||||
/* @see function load_module in load_utils.c for explanation of the following
|
||||
|
@ -2834,6 +2834,34 @@ static char** qc_sqlite_get_database_names(GWBUF* query, int* sizep)
|
||||
return database_names;
|
||||
}
|
||||
|
||||
static char* qc_sqlite_get_prepare_name(GWBUF* query)
|
||||
{
|
||||
QC_TRACE();
|
||||
ss_dassert(this_unit.initialized);
|
||||
ss_dassert(this_thread.initialized);
|
||||
|
||||
char* name = NULL;
|
||||
QC_SQLITE_INFO* info = get_query_info(query);
|
||||
|
||||
if (info)
|
||||
{
|
||||
if (qc_info_is_valid(info->status))
|
||||
{
|
||||
MXS_WARNING("qc_get_prepare_name not implemented yet.");
|
||||
}
|
||||
else if (MXS_LOG_PRIORITY_IS_ENABLED(LOG_INFO))
|
||||
{
|
||||
log_invalid_data(query, "cannot report the name of a prepared statement");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MXS_ERROR("The query could not be parsed. Response not valid.");
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* EXPORTS
|
||||
*/
|
||||
@ -2857,6 +2885,7 @@ static QUERY_CLASSIFIER qc =
|
||||
qc_sqlite_query_has_clause,
|
||||
qc_sqlite_get_affected_fields,
|
||||
qc_sqlite_get_database_names,
|
||||
qc_sqlite_get_prepare_name,
|
||||
};
|
||||
|
||||
|
||||
|
@ -814,6 +814,36 @@ bool compare_get_database_names(QUERY_CLASSIFIER* pClassifier1, GWBUF* pCopy1,
|
||||
return success;
|
||||
}
|
||||
|
||||
bool compare_get_prepare_name(QUERY_CLASSIFIER* pClassifier1, GWBUF* pCopy1,
|
||||
QUERY_CLASSIFIER* pClassifier2, GWBUF* pCopy2)
|
||||
{
|
||||
bool success = false;
|
||||
const char HEADING[] = "qc_get_prepare_name : ";
|
||||
|
||||
char* rv1 = pClassifier1->qc_get_prepare_name(pCopy1);
|
||||
char* rv2 = pClassifier2->qc_get_prepare_name(pCopy2);
|
||||
|
||||
stringstream ss;
|
||||
ss << HEADING;
|
||||
|
||||
if ((!rv1 && !rv2) || (rv1 && rv2 && (strcmp(rv1, rv2) == 0)))
|
||||
{
|
||||
ss << "Ok : " << (rv1 ? rv1 : "NULL");
|
||||
success = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ss << "ERR: " << (rv1 ? rv1 : "NULL") << " != " << (rv2 ? rv2 : "NULL");
|
||||
}
|
||||
|
||||
report(success, ss.str());
|
||||
|
||||
free(rv1);
|
||||
free(rv2);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool compare(QUERY_CLASSIFIER* pClassifier1, QUERY_CLASSIFIER* pClassifier2, const string& s)
|
||||
{
|
||||
GWBUF* pCopy1 = create_gwbuf(s);
|
||||
@ -832,6 +862,7 @@ bool compare(QUERY_CLASSIFIER* pClassifier1, QUERY_CLASSIFIER* pClassifier2, con
|
||||
errors += !compare_query_has_clause(pClassifier1, pCopy1, pClassifier2, pCopy2);
|
||||
errors += !compare_get_affected_fields(pClassifier1, pCopy1, pClassifier2, pCopy2);
|
||||
errors += !compare_get_database_names(pClassifier1, pCopy1, pClassifier2, pCopy2);
|
||||
errors += !compare_get_prepare_name(pClassifier1, pCopy1, pClassifier2, pCopy2);
|
||||
|
||||
gwbuf_free(pCopy1);
|
||||
gwbuf_free(pCopy2);
|
||||
|
@ -205,6 +205,14 @@ char** qc_get_database_names(GWBUF* query, int* sizep)
|
||||
return classifier->qc_get_database_names(query, sizep);
|
||||
}
|
||||
|
||||
char* qc_get_prepare_name(GWBUF* query)
|
||||
{
|
||||
QC_TRACE();
|
||||
ss_dassert(classifier);
|
||||
|
||||
return classifier->qc_get_prepare_name(query);
|
||||
}
|
||||
|
||||
const char* qc_op_to_string(qc_query_op_t op)
|
||||
{
|
||||
switch (op)
|
||||
|
Loading…
x
Reference in New Issue
Block a user