diff --git a/src/common/pl/plpgsql/src/gram.y b/src/common/pl/plpgsql/src/gram.y index 60768d0aadf7bde7f86f8b1ba0fbfec32a5b6d38..b5ac29babe72f525385986497813f03a90368d4f 100755 --- a/src/common/pl/plpgsql/src/gram.y +++ b/src/common/pl/plpgsql/src/gram.y @@ -263,6 +263,7 @@ static List *read_raise_options(void); %type stmt_return stmt_raise stmt_execsql %type stmt_dynexecute stmt_for stmt_perform stmt_getdiag %type stmt_open stmt_fetch stmt_move stmt_close stmt_null +%type stmt_commit stmt_rollback %type stmt_case stmt_foreach_a %type proc_exceptions @@ -338,6 +339,7 @@ static List *read_raise_options(void); %token K_CASE %token K_CLOSE %token K_COLLATE +%token K_COMMIT %token K_CONSTANT %token K_CONTINUE %token K_CURRENT @@ -405,6 +407,7 @@ static List *read_raise_options(void); %token K_RETURN %token K_RETURNED_SQLSTATE %token K_REVERSE +%token K_ROLLBACK %token K_ROWTYPE %token K_ROW_COUNT %token K_SAVEPOINT @@ -1079,6 +1082,10 @@ label_stmt : stmt_assign { $$ = $1; } | stmt_null { $$ = $1; } + | stmt_commit + { $$ = $1; } + | stmt_rollback + { $$ = $1; } ; stmt_perform : K_PERFORM expr_until_semi @@ -2619,6 +2626,32 @@ stmt_null : K_NULL ';' } ; +stmt_commit : K_COMMIT ';' + { + /* We do building a node for NULL for GOTO */ + PLpgSQL_stmt_commit *newp; + + newp = (PLpgSQL_stmt_commit *)palloc(sizeof(PLpgSQL_stmt_commit)); + newp->cmd_type = PLPGSQL_STMT_COMMIT; + newp->lineno = plpgsql_location_to_lineno(@1); + + $$ = (PLpgSQL_stmt *)newp; + } + ; + +stmt_rollback : K_ROLLBACK ';' + { + /* We do building a node for NULL for GOTO */ + PLpgSQL_stmt_rollback *newp; + + newp = (PLpgSQL_stmt_rollback *)palloc(sizeof(PLpgSQL_stmt_rollback)); + newp->cmd_type = PLPGSQL_STMT_ROLLBACK; + newp->lineno = plpgsql_location_to_lineno(@1); + + $$ = (PLpgSQL_stmt *)newp; + } + ; + cursor_variable : T_DATUM { if ($1.datum->dtype != PLPGSQL_DTYPE_VAR) @@ -2896,6 +2929,7 @@ unreserved_keyword : | K_BACKWARD | K_CONSTANT | K_CONTINUE + | K_COMMIT | K_CURRENT | K_DEBUG | K_DETAIL @@ -2926,6 +2960,7 @@ unreserved_keyword : | K_RESULT_OID | K_RETURNED_SQLSTATE | K_REVERSE + | K_ROLLBACK | K_ROW_COUNT | K_ROWTYPE | K_SCROLL diff --git a/src/common/pl/plpgsql/src/pl_exec.cpp b/src/common/pl/plpgsql/src/pl_exec.cpp index 5886dff31e0d807d4cb63585e51f05c6525c9ea7..8d03a997c90ce76f58d1de15ca060091449299bb 100755 --- a/src/common/pl/plpgsql/src/pl_exec.cpp +++ b/src/common/pl/plpgsql/src/pl_exec.cpp @@ -122,6 +122,8 @@ static int exec_stmt_return_query(PLpgSQL_execstate* estate, PLpgSQL_stmt_return static int exec_stmt_raise(PLpgSQL_execstate* estate, PLpgSQL_stmt_raise* stmt); static int exec_stmt_execsql(PLpgSQL_execstate* estate, PLpgSQL_stmt_execsql* stmt); static int exec_stmt_dynexecute(PLpgSQL_execstate* estate, PLpgSQL_stmt_dynexecute* stmt); +static int exec_stmt_commit(PLpgSQL_execstate* estate, PLpgSQL_stmt_commit* stmt); +static int exec_stmt_rollback(PLpgSQL_execstate* estate, PLpgSQL_stmt_rollback* stmt); static int exchange_parameters( PLpgSQL_execstate* estate, PLpgSQL_stmt_dynexecute* dynstmt, List* stmts, int* ppdindex, int* datumindex); static bool is_anonymous_block(const char* query); @@ -2002,6 +2004,14 @@ static int exec_stmt(PLpgSQL_execstate* estate, PLpgSQL_stmt* stmt) rc = exec_stmt_null(estate, (PLpgSQL_stmt*)stmt); break; + case PLPGSQL_STMT_COMMIT: + rc = exec_stmt_commit(estate, (PLpgSQL_stmt_commit*)stmt); + break; + + case PLPGSQL_STMT_ROLLBACK: + rc = exec_stmt_rollback(estate, (PLpgSQL_stmt_rollback*)stmt); + break; + default: estate->err_stmt = save_estmt; ereport(ERROR, @@ -4878,6 +4888,26 @@ static int exec_stmt_null(PLpgSQL_execstate* estate, PLpgSQL_stmt* stmt) return PLPGSQL_RC_OK; } +/* + * exec_stmt_commit + * + * Commit the transaction. + */ +static int exec_stmt_commit(PLpgSQL_execstate* estate, PLpgSQL_stmt_commit* stmt) +{ + return PLPGSQL_RC_OK; +} + +/* + * exec_stmt_rollback + * + * Abort the transaction. + */ +static int exec_stmt_rollback(PLpgSQL_execstate* estate, PLpgSQL_stmt_rollback* stmt) +{ + return PLPGSQL_RC_OK; +} + /* * @Description: copy cursor data from estate->datums to estate->datums * @in estate - estate diff --git a/src/common/pl/plpgsql/src/pl_funcs.cpp b/src/common/pl/plpgsql/src/pl_funcs.cpp index 0cb428355a29e4c263eea802c7f7de97f94bc10c..97fa537ef795014dc8b6c2198fc1355dbbb7348b 100755 --- a/src/common/pl/plpgsql/src/pl_funcs.cpp +++ b/src/common/pl/plpgsql/src/pl_funcs.cpp @@ -222,6 +222,10 @@ const char* plpgsql_stmt_typename(PLpgSQL_stmt* stmt) return "PERFORM"; case PLPGSQL_STMT_NULL: return "NULL"; + case PLPGSQL_STMT_COMMIT: + return "COMMIT"; + case PLPGSQL_STMT_ROLLBACK: + return "ROLLBACK"; default: break; } @@ -291,6 +295,8 @@ static void free_fetch(PLpgSQL_stmt_fetch* stmt); static void free_close(PLpgSQL_stmt_close* stmt); static void free_null(PLpgSQL_stmt* stmt); static void free_perform(PLpgSQL_stmt_perform* stmt); +static void free_commit(PLpgSQL_stmt_commit* stmt); +static void free_rollback(PLpgSQL_stmt_rollback* stmt); static void free_stmt(PLpgSQL_stmt* stmt) { @@ -370,6 +376,12 @@ static void free_stmt(PLpgSQL_stmt* stmt) case PLPGSQL_STMT_NULL: free_null((PLpgSQL_stmt*)stmt); break; + case PLPGSQL_STMT_COMMIT: + free_commit((PLpgSQL_stmt_commit*)stmt); + break; + case PLPGSQL_STMT_ROLLBACK: + free_rollback((PLpgSQL_stmt_rollback*)stmt); + break; default: ereport(ERROR, (errmodule(MOD_PLSQL), @@ -509,6 +521,13 @@ static void free_perform(PLpgSQL_stmt_perform* stmt) free_expr(stmt->expr); } +static void free_commit(PLpgSQL_stmt_commit* stmt) +{ +} + +static void free_rollback(PLpgSQL_stmt_rollback* stmt) +{ +} static void free_exit(PLpgSQL_stmt_exit* stmt) { free_expr(stmt->cond); @@ -687,6 +706,8 @@ static void dump_cursor_direction(PLpgSQL_stmt_fetch* stmt); static void dump_close(PLpgSQL_stmt_close* stmt); static void dump_perform(PLpgSQL_stmt_perform* stmt); static void dump_null(PLpgSQL_stmt* stmt); +static void dump_commit(PLpgSQL_stmt_commit* stmt); +static void dump_rollback(PLpgSQL_stmt_rollback* stmt); static void dump_expr(PLpgSQL_expr* expr); static void dump_ind(void) @@ -777,6 +798,12 @@ static void dump_stmt(PLpgSQL_stmt* stmt) case PLPGSQL_STMT_NULL: dump_null((PLpgSQL_stmt*)stmt); break; + case PLPGSQL_STMT_COMMIT: + dump_commit((PLpgSQL_stmt_commit*)stmt); + break; + case PLPGSQL_STMT_ROLLBACK: + dump_rollback((PLpgSQL_stmt_rollback*)stmt); + break; default: ereport(ERROR, (errmodule(MOD_PLSQL), @@ -1137,6 +1164,18 @@ static void dump_null(PLpgSQL_stmt* stmt) printf("NULL\n"); } +static void dump_commit(PLpgSQL_stmt_commit* stmt) +{ + dump_ind(); + printf("COMMIT\n"); +} + +static void dump_rollback(PLpgSQL_stmt_rollback* stmt) +{ + dump_ind(); + printf("ROLLBACK\n"); +} + static void dump_exit(PLpgSQL_stmt_exit* stmt) { dump_ind(); diff --git a/src/common/pl/plpgsql/src/pl_scanner.cpp b/src/common/pl/plpgsql/src/pl_scanner.cpp index af72d785308f1172632c175146ea7b96b8ffd981..0e79839cab7997e013e39ca38da5c0de3e76002d 100755 --- a/src/common/pl/plpgsql/src/pl_scanner.cpp +++ b/src/common/pl/plpgsql/src/pl_scanner.cpp @@ -86,8 +86,8 @@ static const int num_reserved_keywords = lengthof(reserved_keywords); static const ScanKeyword unreserved_keywords[] = { PG_KEYWORD("absolute", K_ABSOLUTE, UNRESERVED_KEYWORD) PG_KEYWORD("alias", K_ALIAS, UNRESERVED_KEYWORD) PG_KEYWORD( "alter", K_ALTER, UNRESERVED_KEYWORD) PG_KEYWORD("array", K_ARRAY, UNRESERVED_KEYWORD) PG_KEYWORD("backward", - K_BACKWARD, UNRESERVED_KEYWORD) PG_KEYWORD("constant", K_CONSTANT, UNRESERVED_KEYWORD) PG_KEYWORD("continue", - K_CONTINUE, UNRESERVED_KEYWORD) PG_KEYWORD("current", K_CURRENT, UNRESERVED_KEYWORD) PG_KEYWORD("cursor", + K_BACKWARD, UNRESERVED_KEYWORD) PG_KEYWORD("constant", K_CONSTANT, UNRESERVED_KEYWORD) PG_KEYWORD("commit", K_COMMIT, UNRESERVED_KEYWORD) + PG_KEYWORD("continue", K_CONTINUE, UNRESERVED_KEYWORD) PG_KEYWORD("current", K_CURRENT, UNRESERVED_KEYWORD) PG_KEYWORD("cursor", K_CURSOR, UNRESERVED_KEYWORD) PG_KEYWORD("debug", K_DEBUG, UNRESERVED_KEYWORD) PG_KEYWORD("detail", K_DETAIL, UNRESERVED_KEYWORD) PG_KEYWORD("dump", K_DUMP, UNRESERVED_KEYWORD) PG_KEYWORD("errcode", K_ERRCODE, UNRESERVED_KEYWORD) PG_KEYWORD("error", K_ERROR, UNRESERVED_KEYWORD) PG_KEYWORD("first", K_FIRST, @@ -104,7 +104,7 @@ static const ScanKeyword unreserved_keywords[] = { PG_KEYWORD("query", K_QUERY, UNRESERVED_KEYWORD) PG_KEYWORD("record", K_RECORD, UNRESERVED_KEYWORD) PG_KEYWORD("relative", K_RELATIVE, UNRESERVED_KEYWORD) PG_KEYWORD("result_oid", K_RESULT_OID, UNRESERVED_KEYWORD) PG_KEYWORD("returned_sqlstate", K_RETURNED_SQLSTATE, UNRESERVED_KEYWORD) - PG_KEYWORD("reverse", K_REVERSE, UNRESERVED_KEYWORD) PG_KEYWORD("row_count", K_ROW_COUNT, + PG_KEYWORD("reverse", K_REVERSE, UNRESERVED_KEYWORD) PG_KEYWORD("rollback", K_ROLLBACK, UNRESERVED_KEYWORD) PG_KEYWORD("row_count", K_ROW_COUNT, UNRESERVED_KEYWORD) PG_KEYWORD("rowtype", K_ROWTYPE, UNRESERVED_KEYWORD) PG_KEYWORD("savepoint", K_SAVEPOINT, UNRESERVED_KEYWORD) PG_KEYWORD( "scroll", K_SCROLL, UNRESERVED_KEYWORD) PG_KEYWORD("slice", K_SLICE, UNRESERVED_KEYWORD) diff --git a/src/common/pl/plpgsql/src/plpgsql.h b/src/common/pl/plpgsql/src/plpgsql.h index c2d696e07a38c8f7b66a1f3f64069a7e3f069aab..cc9d19f6432e9fab14fee80df4756dee7b58f490 100755 --- a/src/common/pl/plpgsql/src/plpgsql.h +++ b/src/common/pl/plpgsql/src/plpgsql.h @@ -116,7 +116,9 @@ enum PLpgSQL_stmt_types { PLPGSQL_STMT_FETCH, PLPGSQL_STMT_CLOSE, PLPGSQL_STMT_PERFORM, - PLPGSQL_STMT_NULL + PLPGSQL_STMT_NULL, + PLPGSQL_STMT_COMMIT, + PLPGSQL_STMT_ROLLBACK }; /* ---------- @@ -399,6 +401,23 @@ typedef struct { /* PERFORM statement */ PLpgSQL_expr* expr; } PLpgSQL_stmt_perform; +/* + * COMMIT statement + */ +typedef struct PLpgSQL_stmt_commit { + int cmd_type; + int lineno; +} PLpgSQL_stmt_commit; + +/* + * ROLLBACK statement + */ +typedef struct PLpgSQL_stmt_rollback { + int cmd_type; + int lineno; +} PLpgSQL_stmt_rollback; + + typedef struct { /* Get Diagnostics item */ int kind; /* id for diagnostic value desired */ int target; /* where to assign it */ diff --git a/src/include/utils/plpgsql.h b/src/include/utils/plpgsql.h index 773a8fb5f14ab0ed2eeea509e41dd777fec90043..898ad986d1ea853ee049c8ba1a82296c94b7a4b5 100755 --- a/src/include/utils/plpgsql.h +++ b/src/include/utils/plpgsql.h @@ -114,7 +114,9 @@ enum PLpgSQL_stmt_types { PLPGSQL_STMT_FETCH, PLPGSQL_STMT_CLOSE, PLPGSQL_STMT_PERFORM, - PLPGSQL_STMT_NULL + PLPGSQL_STMT_NULL, + PLPGSQL_STMT_COMMIT, + PLPGSQL_STMT_ROLLBACK }; /* ---------- @@ -397,6 +399,22 @@ typedef struct { /* PERFORM statement */ PLpgSQL_expr* expr; } PLpgSQL_stmt_perform; +/* + * COMMIT statement + */ +typedef struct PLpgSQL_stmt_commit { + int cmd_type; + int lineno; +} PLpgSQL_stmt_commit; + +/* + * ROLLBACK statement + */ +typedef struct PLpgSQL_stmt_rollback { + int cmd_type; + int lineno; +} PLpgSQL_stmt_rollback; + typedef struct { /* Get Diagnostics item */ int kind; /* id for diagnostic value desired */ int target; /* where to assign it */ diff --git a/src/test/regress/expected/hw_procedure_define.out b/src/test/regress/expected/hw_procedure_define.out index 63a6142036e534757fc39b2d26ef666f8180da0c..f3cd66f9f5f5df88b8acf92a810e009016be0dcf 100644 --- a/src/test/regress/expected/hw_procedure_define.out +++ b/src/test/regress/expected/hw_procedure_define.out @@ -369,6 +369,25 @@ BEGIN END; / --CREATE USER USER2 PASSWORD 'ttest@123'; +------------------------------------------------------- +-- Test COMMIT/ROLLBACK +------------------------------------------------------- +CREATE TABLE t_transaction(id INTEGER); +CREATE OR REPLACE PROCEDURE proc_callas_transaction +AS +BEGIN + INSERT INTO t_transaction VALUES(1); + COMMIT; + INSERT INTO t_transaction VALUES(10); + ROLLBACK; +END; +/ +CALL proc_callas_transaction(); + proc_callas_transaction +------------------------- + +(1 row) + ------------------------------------------------------- -- Clean up Test envirment ------------------------------------------------------- @@ -377,7 +396,9 @@ DROP FUNCTION func_def_arg; DROP PROCEDURE test_multi_level; DROP PROCEDURE proc_callas_definer; DROP PROCEDURE proc_callas_curr_user; +DROP PROCEDURE proc_callas_transaction; DROP TABLE t_priv; +DROP TABLE t_transaction; create or replace procedure test_blank (a int) as diff --git a/src/test/regress/sql/hw_procedure_define.sql b/src/test/regress/sql/hw_procedure_define.sql index 96aec65bd858caa313720c76af5bd9e619ea9a6b..1b7b98e1ecb4b683f4b7879438e2d4ecf775446e 100644 --- a/src/test/regress/sql/hw_procedure_define.sql +++ b/src/test/regress/sql/hw_procedure_define.sql @@ -266,6 +266,20 @@ END; / --CREATE USER USER2 PASSWORD 'ttest@123'; +------------------------------------------------------- +-- Test COMMIT/ROLLBACK +------------------------------------------------------- +CREATE TABLE t_transaction(id INTEGER); +CREATE OR REPLACE PROCEDURE proc_callas_transaction +AS +BEGIN + INSERT INTO t_transaction VALUES(1); + COMMIT; + INSERT INTO t_transaction VALUES(10); + ROLLBACK; +END; +/ +CALL proc_callas_transaction(); ------------------------------------------------------- -- Clean up Test envirment ------------------------------------------------------- @@ -274,7 +288,9 @@ DROP FUNCTION func_def_arg; DROP PROCEDURE test_multi_level; DROP PROCEDURE proc_callas_definer; DROP PROCEDURE proc_callas_curr_user; +DROP PROCEDURE proc_callas_transaction; DROP TABLE t_priv; +DROP TABLE t_transaction; create or replace procedure test_blank (a int)