MXS-1137: Do not cache when [user|system] vars are used

If user or system variables are used in a SELECT statement, then
the result will not be cached. That ensures that the wrong result
will not be returned.
This commit is contained in:
Johan Wikman 2017-03-01 15:26:26 +02:00
parent aa51528481
commit 4902ed7cf5
2 changed files with 15 additions and 31 deletions

View File

@ -40,32 +40,8 @@ will be used and populated until the first `UPDATE`, `INSERT` or `DELETE`
statement is encountered.
### Variables
The cache key is effectively the entire _SELECT_ statement. However, the
value of any variables used in the select is **not** considered. For instance,
if a variable is used in the _WHERE_ clause of the select, a subsequent
identical select will return the wrong result, if the value of the variable
has been changed in between.
```
MySQL [testdb]> create table tbl (a int, b int);
MySQL [testdb]> insert into tbl values (1, 2), (3, 4);
MySQL [testdb]> set @var=2;
MySQL [testdb]> select a from tbl where b=@var;
+------+
| a |
+------+
| 1 |
+------+
MySQL [testdb]> set @var=4;
MySQL [testdb]> select a from tbl where b=@var;
+------+
| a |
+------+
| 1 |
+------+
```
In the second case, the correct answer would have been `3` and not `1`.
If user or system variables are used in the _SELECT_ statement, the result
will not be cached.
### Security

View File

@ -707,14 +707,22 @@ bool CacheFilterSession::should_consult_cache(GWBUF* pPacket)
if (consult_cache)
{
// We do not care whether the query was fully parsed or not.
// If a query cannot be fully parsed, the worst thing that can
// happen is that caching is not used, even though it would be
// possible.
if (qc_get_operation(pPacket) != QUERY_OP_SELECT)
if (qc_query_is_type(type_mask, QUERY_TYPE_USERVAR_READ) ||
qc_query_is_type(type_mask, QUERY_TYPE_SYSVAR_READ))
{
consult_cache = false;
}
else
{
// We do not care whether the query was fully parsed or not.
// If a query cannot be fully parsed, the worst thing that can
// happen is that caching is not used, even though it would be
// possible.
if (qc_get_operation(pPacket) != QUERY_OP_SELECT)
{
consult_cache = false;
}
}
}
return consult_cache;