MXS-2674 Fix query classification
With these changes
SET @saved_cs_client= @@character_set_client;
will be classified as QUERY_TYPE_USERVAR_WRITE and
SELECT 1 AS c1 FROM t1 ORDER BY ( SELECT 1 AS c2 FROM
t1 GROUP BY GREATEST(LAST_INSERT_ID(), t1.a) ORDER BY
GREATEST(LAST_INSERT_ID(), t1.a) LIMIT 1);
will be classified as QUERY_TYPE_READ|QUERY_TYPE_MASTER_READ
This commit is contained in:
@ -1253,6 +1253,18 @@ public:
|
||||
const ExprList* pExclude,
|
||||
compound_approach_t compound_approach = ANALYZE_COMPOUND_SELECTS)
|
||||
{
|
||||
if (pSelect->pLimit)
|
||||
{
|
||||
// In case there is an ORDER BY statement without a LIMIT, which is
|
||||
// not accepted by sqlite, a pseudo LIMIT with the value of -1 is injected.
|
||||
// We need to detect that so as not to incorrectly claim that there is
|
||||
// a clause. See maxscale_create_pseudo_limit() in parse.y.
|
||||
if (pSelect->pLimit->op != TK_INTEGER || pSelect->pLimit->u.iValue != -1)
|
||||
{
|
||||
m_has_clause = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (pSelect->pSrc)
|
||||
{
|
||||
const SrcList* pSrc = pSelect->pSrc;
|
||||
@ -1316,6 +1328,14 @@ public:
|
||||
#endif
|
||||
}
|
||||
|
||||
if (pSelect->pOrderBy)
|
||||
{
|
||||
update_field_infos_from_exprlist(&aliases,
|
||||
context,
|
||||
pSelect->pOrderBy,
|
||||
pSelect->pEList);
|
||||
}
|
||||
|
||||
if (pSelect->pWith)
|
||||
{
|
||||
update_field_infos_from_with(&aliases, context, pSelect->pWith);
|
||||
@ -1860,6 +1880,9 @@ public:
|
||||
QcAliases aliases;
|
||||
uint32_t context = 0;
|
||||
update_field_infos_from_select(aliases, context, pSelect, NULL);
|
||||
|
||||
// Non-sensical to claim that a "CREATE ... SELECT ... WHERE ..." statement has a clause.
|
||||
m_has_clause = false;
|
||||
}
|
||||
else if (pOldTable)
|
||||
{
|
||||
@ -2030,7 +2053,7 @@ public:
|
||||
m_type_mask = QUERY_TYPE_WRITE;
|
||||
m_operation = QUERY_OP_UPDATE;
|
||||
update_names_from_srclist(&aliases, pTabList);
|
||||
m_has_clause = (pWhere ? true : false);
|
||||
m_has_clause = ((pWhere && pWhere->op != TK_IN) ? true : false);
|
||||
|
||||
if (pChanges)
|
||||
{
|
||||
|
||||
@ -134,6 +134,8 @@ extern void maxscaleUse(Parse*, Token*);
|
||||
extern void maxscale_update_function_info(const char* name, const Expr* pExpr);
|
||||
extern void maxscale_set_type_mask(unsigned int type_mask);
|
||||
|
||||
static Expr* maxscale_create_pseudo_limit(Parse* pParse, Token* pToken, ExprSpan* pLimit);
|
||||
|
||||
// Exposed utility functions
|
||||
void exposed_sqlite3ExprDelete(sqlite3 *db, Expr *pExpr)
|
||||
{
|
||||
@ -1516,12 +1518,14 @@ cmd ::= with(C) DELETE FROM fullname(X) indexed_opt(I) where_opt(W)
|
||||
sqlite3WithPush(pParse, C, 1);
|
||||
sqlite3SrcListIndexedBy(pParse, X, &I);
|
||||
#ifdef MAXSCALE
|
||||
// We are not interested in the order by or limit information.
|
||||
// Thus we simply delete it. sqlite also has some limitations, which
|
||||
// will not bother us if we hide the information from it.
|
||||
sqlite3ExprListDelete(pParse->db, O);
|
||||
sqlite3ExprDelete(pParse->db, L.pLimit);
|
||||
sqlite3ExprDelete(pParse->db, L.pOffset);
|
||||
Token token;
|
||||
ExprSpan limit;
|
||||
if (O && !L.pLimit) {
|
||||
L.pLimit = maxscale_create_pseudo_limit(pParse, &token, &limit);
|
||||
sqlite3ExprDelete(pParse->db, L.pOffset);
|
||||
L.pOffset = 0;
|
||||
}
|
||||
W = sqlite3LimitWhere(pParse, X, W, O, L.pLimit, L.pOffset, "DELETE");
|
||||
mxs_sqlite3DeleteFrom(pParse,X,W,0);
|
||||
#else
|
||||
W = sqlite3LimitWhere(pParse, X, W, O, L.pLimit, L.pOffset, "DELETE");
|
||||
@ -1678,12 +1682,15 @@ cmd ::= with(C) UPDATE orconf(R) fullname(X) indexed_opt(I) SET setlist(Y)
|
||||
sqlite3SrcListIndexedBy(pParse, X, &I);
|
||||
sqlite3ExprListCheckLength(pParse,Y,"set list");
|
||||
#ifdef MAXSCALE
|
||||
// We are not interested in the order by or limit information.
|
||||
// Thus we simply delete it. sqlite also has some limitations, which
|
||||
// will not bother us if we hide the information from it.
|
||||
sqlite3ExprListDelete(pParse->db, O);
|
||||
sqlite3ExprDelete(pParse->db, L.pLimit);
|
||||
sqlite3ExprDelete(pParse->db, L.pOffset);
|
||||
Token token;
|
||||
ExprSpan limit;
|
||||
if (O && !L.pLimit) {
|
||||
L.pLimit = maxscale_create_pseudo_limit(pParse, &token, &limit);
|
||||
sqlite3ExprDelete(pParse->db, L.pOffset);
|
||||
L.pOffset = 0;
|
||||
}
|
||||
|
||||
W = sqlite3LimitWhere(pParse, X, W, O, L.pLimit, L.pOffset, "UPDATE");
|
||||
mxs_sqlite3Update(pParse,X,Y,W,R);
|
||||
#else
|
||||
W = sqlite3LimitWhere(pParse, X, W, O, L.pLimit, L.pOffset, "UPDATE");
|
||||
@ -3507,3 +3514,21 @@ cmd ::= DECLARE. {
|
||||
}
|
||||
|
||||
%endif
|
||||
|
||||
%include {
|
||||
|
||||
static Expr* maxscale_create_pseudo_limit(Parse* pParse, Token* pToken, ExprSpan* pLimit)
|
||||
{
|
||||
// sqlite3 does not accept a ORDER BY without LIMIT, but MariaDB
|
||||
// does. Thus, to make sqlite3LimitWhere return non-NULL we need
|
||||
// to inject a LIMIT if there is none. We use a value of -1 to
|
||||
// tell update_field_infos_from_select() that this LIMIT should
|
||||
// not be counted as a limiting clause.
|
||||
static char one[] = "-1";
|
||||
pToken->z = one;
|
||||
pToken->n = 1;
|
||||
spanExpr(pLimit, pParse, TK_INTEGER, pToken);
|
||||
return pLimit->pExpr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user