qc: Add qc_get_field_info

This function returns more detailed information about the fields
of a statement. Supersedes qc_get_affected_fields() that will
be deprecated and removed.

Note that this function now introduced new kind of behaviour; the
returned data belongs to the GWBUF and remains valid for as long as
the GWBUF is alive. That means that unnecessary copying need not
be done.
This commit is contained in:
Johan Wikman 2016-11-01 16:34:28 +02:00
parent ab487e687f
commit c652f1330a
4 changed files with 73 additions and 0 deletions

View File

@ -87,6 +87,18 @@ typedef enum qc_parse_result
} qc_parse_result_t;
/**
* QC_FIELD_INFO contains information about a field used in a statement.
*/
typedef struct qc_field_info
{
char* database; /** Present if the field is of the form "a.b.c", NULL otherwise. */
char* table; /** Present if the field is of the form "a.b", NULL otherwise. */
char* column; /** Always present. */
// TODO: Possibly add bits telling where the field is used; e.g. in the select
// TODO: part or the where part, or both.
} QC_FIELD_INFO;
/**
* QUERY_CLASSIFIER defines the object a query classifier plugin must
* implement and return.
@ -117,6 +129,7 @@ typedef struct query_classifier
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);
void (*qc_get_field_info)(GWBUF* stmt, const QC_FIELD_INFO** infos, size_t* n_infos);
} QUERY_CLASSIFIER;
/**
@ -223,6 +236,21 @@ qc_parse_result_t qc_parse(GWBUF* stmt);
*/
char* qc_get_affected_fields(GWBUF* stmt);
/**
* Returns information about affected fields.
*
* @param stmt A buffer containing a COM_QUERY packet.
* @param infos Pointer to pointer that after the call will point to an
* array of QC_FIELD_INFO:s.
* @param n_infos Pointer to size_t variable where the number of items
* in @c infos will be returned.
*
* @note The returned array belongs to the GWBUF and remains valid for as
* long as the GWBUF is valid. If the data is needed for longer than
* that, it must be copied.
*/
void qc_get_field_info(GWBUF* stmt, const QC_FIELD_INFO** infos, size_t* n_infos);
/**
* Returns the statement, with literals replaced with question marks.
*

View File

@ -2010,6 +2010,14 @@ qc_query_op_t qc_get_prepare_operation(GWBUF* stmt)
return operation;
}
void qc_get_field_info(GWBUF* stmt, const QC_FIELD_INFO** infos, size_t* n_infos)
{
MXS_ERROR("qc_get_field_info not implemented yet.");
*infos = NULL;
*n_infos = 0;
}
namespace
{
@ -2156,6 +2164,7 @@ static QUERY_CLASSIFIER qc =
qc_get_database_names,
qc_get_prepare_name,
qc_get_prepare_operation,
qc_get_field_info,
};
/* @see function load_module in load_utils.c for explanation of the following

View File

@ -248,6 +248,21 @@ static bool ensure_query_is_parsed(GWBUF* query)
return parsed;
}
void free_field_infos(QC_FIELD_INFO* infos, size_t n_infos)
{
if (infos)
{
for (int i = 0; i < n_infos; ++i)
{
MXS_FREE(infos[i].database);
MXS_FREE(infos[i].table);
MXS_FREE(infos[i].column);
}
MXS_FREE(infos);
}
}
static void free_string_array(char** sa)
{
if (sa)
@ -2954,6 +2969,18 @@ static qc_query_op_t qc_sqlite_get_prepare_operation(GWBUF* query)
return op;
}
void qc_sqlite_get_field_info(GWBUF* stmt, const QC_FIELD_INFO** infos, size_t* n_infos)
{
QC_TRACE();
ss_dassert(this_unit.initialized);
ss_dassert(this_thread.initialized);
MXS_ERROR("qc_get_field_info not implemented yet.");
*infos = NULL;
*n_infos = 0;
}
/**
* EXPORTS
*/
@ -2979,6 +3006,7 @@ static QUERY_CLASSIFIER qc =
qc_sqlite_get_database_names,
qc_sqlite_get_prepare_name,
qc_sqlite_get_prepare_operation,
qc_sqlite_get_field_info,
};

View File

@ -197,6 +197,14 @@ char* qc_get_affected_fields(GWBUF* query)
return classifier->qc_get_affected_fields(query);
}
void qc_get_field_info(GWBUF* query, const QC_FIELD_INFO** infos, size_t* n_infos)
{
QC_TRACE();
ss_dassert(classifier);
classifier->qc_get_field_info(query, infos, n_infos);
}
char** qc_get_database_names(GWBUF* query, int* sizep)
{
QC_TRACE();