MXS-2043 Classify SELECT ... FOR UPDATE as QUERY_TYPE_WRITE

SELECT...FOR UPDATE locks the rows for update, but only if
autocommit==0 or a transaction is active, so in principle even if
it were classified as READ it'd still be sent to master when it
actually matters.

However, even if autocommit==1 and/or no transaction is active, a
slave in read only mode will reject the statement if the user is
subject to the read only restriction (a user with super privileges
is not), which might be considered a server bug. By classifying the
statement as a write, it'll be sent to master and always succeed.
This commit is contained in:
Johan Wikman
2018-09-25 18:26:45 +03:00
parent 743daa5755
commit 2aca6226d9
2 changed files with 43 additions and 1 deletions

View File

@ -131,6 +131,7 @@ extern void maxscaleTruncate(Parse*, Token* pDatabase, Token* pName);
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);
// Exposed utility functions
void exposed_sqlite3ExprDelete(sqlite3 *db, Expr *pExpr)
@ -966,6 +967,10 @@ cmd ::= select(X). {
%destructor select {sqlite3SelectDelete(pParse->db, $$);}
%type selectnowith {Select*}
%destructor selectnowith {sqlite3SelectDelete(pParse->db, $$);}
%ifdef MAXSCALE
%type selectnowithsuffix {Select*}
%destructor selectnowithsuffix {sqlite3SelectDelete(pParse->db, $$);}
%endif
%type oneselect {Select*}
%destructor oneselect {sqlite3SelectDelete(pParse->db, $$);}
@ -993,7 +998,12 @@ cmd ::= select(X). {
}
}
%ifdef MAXSCALE
select(A) ::= with(W) selectnowithsuffix(X). {
%endif
%ifndef MAXSCALE
select(A) ::= with(W) selectnowith(X). {
%endif
Select *p = X;
if( p ){
p->pWith = W;
@ -1004,6 +1014,15 @@ select(A) ::= with(W) selectnowith(X). {
A = p;
}
%ifdef MAXSCALE
selectnowithsuffix(A) ::= selectnowith(X). {A = X;}
selectnowithsuffix(A) ::= selectnowith(X) FOR UPDATE. {
A = X;
maxscale_set_type_mask(QUERY_TYPE_WRITE);
}
%endif
selectnowith(A) ::= oneselect(X). {A = X;}
%ifndef SQLITE_OMIT_COMPOUND_SELECT
selectnowith(A) ::= selectnowith(X) multiselect_op(Y) oneselect(Z). {