diff --git a/query_classifier/qc_sqlite/qc_sqlite.c b/query_classifier/qc_sqlite/qc_sqlite.c index 71280297c..62f30dbe3 100644 --- a/query_classifier/qc_sqlite/qc_sqlite.c +++ b/query_classifier/qc_sqlite/qc_sqlite.c @@ -1409,6 +1409,17 @@ void mxs_sqlite3Update(Parse* pParse, SrcList* pTabList, ExprList* pChanges, Exp exposed_sqlite3ExprDelete(pParse->db, pWhere); } +void mxs_sqlite3Savepoint(Parse *pParse, int op, Token *pName) +{ + QC_TRACE(); + + QC_SQLITE_INFO* info = this_thread.info; + ss_dassert(info); + + info->status = QC_QUERY_PARSED; + info->types = QUERY_TYPE_WRITE; +} + void maxscaleCollectInfoFromSelect(Parse* pParse, Select* pSelect) { QC_SQLITE_INFO* info = this_thread.info; diff --git a/query_classifier/qc_sqlite/sqlite-src-3110100/src/parse.y b/query_classifier/qc_sqlite/sqlite-src-3110100/src/parse.y index 5b9f888f0..3b3b08d49 100644 --- a/query_classifier/qc_sqlite/sqlite-src-3110100/src/parse.y +++ b/query_classifier/qc_sqlite/sqlite-src-3110100/src/parse.y @@ -83,6 +83,7 @@ extern void mxs_sqlite3DropTable(Parse*, SrcList*, int, int, int); extern void mxs_sqlite3EndTable(Parse*, Token*, Token*, u8, Select*, SrcList*); extern void mxs_sqlite3Insert(Parse*, SrcList*, Select*, IdList*, int,ExprList*); extern void mxs_sqlite3RollbackTransaction(Parse*); +extern void mxs_sqlite3Savepoint(Parse *pParse, int op, Token *pName); extern int mxs_sqlite3Select(Parse*, Select*, SelectDest*); extern void mxs_sqlite3StartTable(Parse*,Token*,Token*,int,int,int,int); extern void mxs_sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int); @@ -318,6 +319,22 @@ cmd ::= END trans_opt. {sqlite3CommitTransaction(pParse);} cmd ::= ROLLBACK trans_opt. {sqlite3RollbackTransaction(pParse);} %endif +%ifdef MAXSCALE +savepoint_opt ::= SAVEPOINT. +savepoint_opt ::= . +work_opt ::= WORK. +work_opt ::= . +cmd ::= SAVEPOINT nm(X). { + mxs_sqlite3Savepoint(pParse, SAVEPOINT_BEGIN, &X); +} +cmd ::= RELEASE savepoint_opt nm(X). { + mxs_sqlite3Savepoint(pParse, SAVEPOINT_RELEASE, &X); +} +cmd ::= ROLLBACK work_opt TO savepoint_opt nm(X). { + mxs_sqlite3Savepoint(pParse, SAVEPOINT_ROLLBACK, &X); +} +%endif +%ifndef MAXSCALE savepoint_opt ::= SAVEPOINT. savepoint_opt ::= . cmd ::= SAVEPOINT nm(X). { @@ -329,6 +346,7 @@ cmd ::= RELEASE savepoint_opt nm(X). { cmd ::= ROLLBACK trans_opt TO savepoint_opt nm(X). { sqlite3Savepoint(pParse, SAVEPOINT_ROLLBACK, &X); } +%endif ///////////////////// The CREATE TABLE statement //////////////////////////// // @@ -580,6 +598,7 @@ columnid(A) ::= nm(X). { UNSIGNED VALUE VIEW /*VIRTUAL*/ /*WITH*/ + WORK %endif . %wildcard ANY. diff --git a/query_classifier/qc_sqlite/sqlite-src-3110100/tool/mkkeywordhash.c b/query_classifier/qc_sqlite/sqlite-src-3110100/tool/mkkeywordhash.c index 5940f1c4d..7a6ce5782 100644 --- a/query_classifier/qc_sqlite/sqlite-src-3110100/tool/mkkeywordhash.c +++ b/query_classifier/qc_sqlite/sqlite-src-3110100/tool/mkkeywordhash.c @@ -462,6 +462,7 @@ static Keyword aKeywordTable[] = { { "WHEN", "TK_WHEN", ALWAYS }, { "WHERE", "TK_WHERE", ALWAYS }, #ifdef MAXSCALE + { "WORK", "TK_WORK", ALWAYS }, { "WRITE", "TK_WRITE", ALWAYS }, #endif { "ZEROFILL", "TK_ZEROFILL", ALWAYS }, diff --git a/query_classifier/test/maxscale.test b/query_classifier/test/maxscale.test index 48fb14660..3f62a9f7d 100644 --- a/query_classifier/test/maxscale.test +++ b/query_classifier/test/maxscale.test @@ -54,4 +54,11 @@ SET autocommit=true; SET autocommit=FALSE; SET autocommit=Off; -LOAD DATA LOCAL INFILE '/tmp/data.csv' INTO TABLE test.t1; \ No newline at end of file +LOAD DATA LOCAL INFILE '/tmp/data.csv' INTO TABLE test.t1; + +SAVEPOINT id; +ROLLBACK WORK TO SAVEPOINT id; +ROLLBACK TO SAVEPOINT id; +ROLLBACK WORK TO id; +ROLLBACK TO id; +RELEASE SAVEPOINT id;