Make PREPARE operation explicit
The operation of the statement to be prepared is no longer reported as the operation of the PREPARE statement. Instead, when the type of the statement is QUERY_TYPE_PREPARE_NAMED_STMT, the operation can be obtained using qc_get_prepare_operation(). The qc_mysqlembedded implementation will be provided in a subsequent commit.
This commit is contained in:
parent
8c20ad5cd0
commit
91e36ecaed
@ -116,6 +116,7 @@ typedef struct query_classifier
|
||||
char* (*qc_get_affected_fields)(GWBUF* stmt);
|
||||
char** (*qc_get_database_names)(GWBUF* stmt, int* size);
|
||||
char* (*qc_get_prepare_name)(GWBUF* stmt);
|
||||
qc_query_op_t (*qc_get_prepare_operation)(GWBUF* stmt);
|
||||
} QUERY_CLASSIFIER;
|
||||
|
||||
/**
|
||||
@ -285,6 +286,17 @@ qc_query_op_t qc_get_operation(GWBUF* stmt);
|
||||
*/
|
||||
char* qc_get_prepare_name(GWBUF* stmt);
|
||||
|
||||
/**
|
||||
* Returns the operator of the prepared statement, if the statement
|
||||
* is a PREPARE statement.
|
||||
*
|
||||
* @param stmt A buffer containing a COM_QUERY packet.
|
||||
*
|
||||
* @return The operator of the prepared statement, if the statement
|
||||
* is a PREPARE statement; otherwise QUERY_OP_UNDEFINED.
|
||||
*/
|
||||
qc_query_op_t qc_get_prepare_operation(GWBUF* stmt);
|
||||
|
||||
/**
|
||||
* Returns the tables accessed by the statement.
|
||||
*
|
||||
|
@ -1929,6 +1929,26 @@ char* qc_get_prepare_name(GWBUF* stmt)
|
||||
return name;
|
||||
}
|
||||
|
||||
qc_query_op_t qc_get_prepare_operation(GWBUF* stmt)
|
||||
{
|
||||
qc_query_op_t operation = QUERY_OP_UNDEFINED;
|
||||
|
||||
if (stmt)
|
||||
{
|
||||
if (ensure_query_is_parsed(stmt))
|
||||
{
|
||||
LEX* lex = get_lex(stmt);
|
||||
|
||||
if (lex->sql_command == SQLCOM_PREPARE)
|
||||
{
|
||||
MXS_WARNING("qc_get_prepare_operation not implemented yet.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return operation;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
@ -2074,6 +2094,7 @@ static QUERY_CLASSIFIER qc =
|
||||
qc_get_affected_fields,
|
||||
qc_get_database_names,
|
||||
qc_get_prepare_name,
|
||||
qc_get_prepare_operation,
|
||||
};
|
||||
|
||||
/* @see function load_module in load_utils.c for explanation of the following
|
||||
|
@ -79,6 +79,7 @@ typedef struct qc_sqlite_info
|
||||
int keyword_1; // The first encountered keyword.
|
||||
int keyword_2; // The second encountered keyword.
|
||||
char* prepare_name; // The name of a prepared statement.
|
||||
qc_query_op_t prepare_operation; // The operation of a prepared statement.
|
||||
size_t preparable_stmt_offset; // The start of the preparable statement.
|
||||
size_t preparable_stmt_length; // The length of the preparable statement.
|
||||
} QC_SQLITE_INFO;
|
||||
@ -331,6 +332,7 @@ static QC_SQLITE_INFO* info_init(QC_SQLITE_INFO* info)
|
||||
info->keyword_1 = 0; // Sqlite3 starts numbering tokens from 1, so 0 means
|
||||
info->keyword_2 = 0; // that we have not seen a keyword.
|
||||
info->prepare_name = NULL;
|
||||
info->prepare_operation = QUERY_OP_UNDEFINED;
|
||||
info->preparable_stmt_offset = 0;
|
||||
info->preparable_stmt_length = 0;
|
||||
|
||||
@ -482,9 +484,7 @@ static bool parse_query(GWBUF* query)
|
||||
this_thread.info->query = NULL;
|
||||
this_thread.info->query_len = 0;
|
||||
|
||||
// TODO: Perhaps the rest of the stuff should be
|
||||
// TODO: copied as well.
|
||||
info->operation = preparable_info->operation;
|
||||
info->prepare_operation = preparable_info->operation;
|
||||
|
||||
info_free(preparable_info);
|
||||
}
|
||||
@ -2923,6 +2923,34 @@ static char* qc_sqlite_get_prepare_name(GWBUF* query)
|
||||
return name;
|
||||
}
|
||||
|
||||
static qc_query_op_t qc_sqlite_get_prepare_operation(GWBUF* query)
|
||||
{
|
||||
QC_TRACE();
|
||||
ss_dassert(this_unit.initialized);
|
||||
ss_dassert(this_thread.initialized);
|
||||
|
||||
qc_query_op_t op = QUERY_OP_UNDEFINED;
|
||||
QC_SQLITE_INFO* info = get_query_info(query);
|
||||
|
||||
if (info)
|
||||
{
|
||||
if (qc_info_is_valid(info->status))
|
||||
{
|
||||
op = info->prepare_operation;
|
||||
}
|
||||
else if (MXS_LOG_PRIORITY_IS_ENABLED(LOG_INFO))
|
||||
{
|
||||
log_invalid_data(query, "cannot report the operation of a prepared statement");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MXS_ERROR("The query could not be parsed. Response not valid.");
|
||||
}
|
||||
|
||||
return op;
|
||||
}
|
||||
|
||||
/**
|
||||
* EXPORTS
|
||||
*/
|
||||
@ -2947,6 +2975,7 @@ static QUERY_CLASSIFIER qc =
|
||||
qc_sqlite_get_affected_fields,
|
||||
qc_sqlite_get_database_names,
|
||||
qc_sqlite_get_prepare_name,
|
||||
qc_sqlite_get_prepare_operation,
|
||||
};
|
||||
|
||||
|
||||
|
@ -844,6 +844,33 @@ bool compare_get_prepare_name(QUERY_CLASSIFIER* pClassifier1, GWBUF* pCopy1,
|
||||
return success;
|
||||
}
|
||||
|
||||
bool compare_get_prepare_operation(QUERY_CLASSIFIER* pClassifier1, GWBUF* pCopy1,
|
||||
QUERY_CLASSIFIER* pClassifier2, GWBUF* pCopy2)
|
||||
{
|
||||
bool success = false;
|
||||
const char HEADING[] = "qc_get_prepare_operation : ";
|
||||
|
||||
qc_query_op_t rv1 = pClassifier1->qc_get_prepare_operation(pCopy1);
|
||||
qc_query_op_t rv2 = pClassifier2->qc_get_prepare_operation(pCopy2);
|
||||
|
||||
stringstream ss;
|
||||
ss << HEADING;
|
||||
|
||||
if (rv1 == rv2)
|
||||
{
|
||||
ss << "Ok : " << qc_op_to_string(rv1);
|
||||
success = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ss << "ERR: " << qc_op_to_string(rv1) << " != " << qc_op_to_string(rv2);
|
||||
}
|
||||
|
||||
report(success, ss.str());
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool compare(QUERY_CLASSIFIER* pClassifier1, QUERY_CLASSIFIER* pClassifier2, const string& s)
|
||||
{
|
||||
GWBUF* pCopy1 = create_gwbuf(s);
|
||||
@ -863,6 +890,7 @@ bool compare(QUERY_CLASSIFIER* pClassifier1, QUERY_CLASSIFIER* pClassifier2, con
|
||||
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);
|
||||
errors += !compare_get_prepare_operation(pClassifier1, pCopy1, pClassifier2, pCopy2);
|
||||
|
||||
gwbuf_free(pCopy1);
|
||||
gwbuf_free(pCopy2);
|
||||
|
Loading…
x
Reference in New Issue
Block a user