MXS-1150: Do not cache non-cachable functions

The resultset of SELECTs that use functions whose result will
always vary or whose result depend upon the user executing the
query should not be cached. The list of functions is the same
as that specified for the query cache of MariaDB:
https://mariadb.com/kb/en/mariadb/query-cache/
This commit is contained in:
Johan Wikman
2017-03-02 12:36:38 +02:00
parent 923ed9329d
commit da5edadcda
2 changed files with 122 additions and 4 deletions

View File

@ -35,6 +35,108 @@ inline bool cache_max_resultset_size_exceeded(const CACHE_CONFIG& config, uint64
}
namespace
{
const char* NON_CACHEABLE_FUNCTIONS[] =
{
"benchmark",
"connection_id",
"convert_tz",
"curdate",
"current_date",
"current_timestamp",
"curtime",
"database",
"encrypt",
"found_rows",
"get_lock",
"is_free_lock",
"is_used_lock",
"last_insert_id",
"load_file",
"localtime",
"localtimestamp",
"master_pos_wait",
"now",
"rand",
"release_lock",
"session_user",
"sleep",
"sysdate",
"system_user",
"unix_timestamp",
"user",
"uuid",
"uuid_short",
};
const char* NON_CACHEABLE_VARIABLES[] =
{
"current_date",
"current_timestamp",
"localtime",
"localtimestamp",
};
const size_t N_NON_CACHEABLE_FUNCTIONS = sizeof(NON_CACHEABLE_FUNCTIONS)/sizeof(NON_CACHEABLE_FUNCTIONS[0]);
const size_t N_NON_CACHEABLE_VARIABLES = sizeof(NON_CACHEABLE_VARIABLES)/sizeof(NON_CACHEABLE_VARIABLES[0]);
int compare_name(const void* pLeft, const void* pRight)
{
return strcasecmp((const char*)pLeft, *(const char**)pRight);
}
inline bool uses_name(const char* zName, const char** pzNames, size_t nNames)
{
return bsearch(zName, pzNames, nNames, sizeof(const char*), compare_name) != NULL;
}
bool uses_non_cacheable_function(GWBUF* pPacket)
{
bool rv = false;
const QC_FUNCTION_INFO* pInfo;
size_t nInfos;
qc_get_function_info(pPacket, &pInfo, &nInfos);
const QC_FUNCTION_INFO* pEnd = pInfo + nInfos;
while (!rv && (pInfo != pEnd))
{
rv = uses_name(pInfo->name, NON_CACHEABLE_FUNCTIONS, N_NON_CACHEABLE_FUNCTIONS);
++pInfo;
}
return rv;
}
bool uses_non_cacheable_variable(GWBUF* pPacket)
{
bool rv = false;
const QC_FIELD_INFO* pInfo;
size_t nInfos;
qc_get_field_info(pPacket, &pInfo, &nInfos);
const QC_FIELD_INFO* pEnd = pInfo + nInfos;
while (!rv && (pInfo != pEnd))
{
rv = uses_name(pInfo->column, NON_CACHEABLE_VARIABLES, N_NON_CACHEABLE_VARIABLES);
++pInfo;
}
return rv;
}
}
CacheFilterSession::CacheFilterSession(MXS_SESSION* pSession, Cache* pCache, char* zDefaultDb)
: maxscale::FilterSession(pSession)
, m_state(CACHE_EXPECTING_NOTHING)
@ -719,6 +821,16 @@ bool CacheFilterSession::should_consult_cache(GWBUF* pPacket)
consult_cache = false;
zReason = "system variables are read";
}
else if (uses_non_cacheable_function(pPacket))
{
consult_cache = false;
zReason = "uses non-cacheable function";
}
else if (uses_non_cacheable_variable(pPacket))
{
consult_cache = false;
zReason = "uses non-cacheable variable";
}
}
else
{