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:
Johan Wikman 2016-10-26 12:48:48 +03:00
parent 19e017e499
commit 7499c1e1bf
5 changed files with 104 additions and 1 deletions

View File

@ -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.
*

View File

@ -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

View File

@ -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,
};

View File

@ -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);

View File

@ -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)