!2336 允许openGauss在B兼容模式下通过autocommit开启、关闭自动提交功能

Merge pull request !2336 from Cross-罗/autocommit
This commit is contained in:
opengauss-bot
2022-11-30 13:32:48 +00:00
committed by Gitee
7 changed files with 415 additions and 5 deletions

View File

@ -170,6 +170,7 @@ static bool check_and_assign_catalog_oids(List* elemlist);
static const char* show_archive_command(void);
bool check_enable_gtm_free(bool* newval, void** extra, GucSource source);
static bool check_phony_autocommit(bool* newval, void** extra, GucSource source);
static void assign_phony_autocommit(bool newval, void* extra);
static bool check_enable_data_replicate(bool* newval, void** extra, GucSource source);
static bool check_adio_debug_guc(bool* newval, void** extra, GucSource source);
static bool check_adio_function_guc(bool* newval, void** extra, GucSource source);
@ -521,13 +522,14 @@ static void InitStorageConfigureNamesBool()
PGC_USERSET,
NODE_ALL,
CLIENT_CONN_STATEMENT,
gettext_noop("This parameter doesn't do anything."),
gettext_noop("It's just here so that we won't choke on SET AUTOCOMMIT TO ON from 7.3-vintage clients."),
gettext_noop("This parameter is only used in B compatibility."),
gettext_noop("Otherwise, it's just here so that we won't choke on SET AUTOCOMMIT TO ON from 7.3-vintage clients.\n"
"This parameter is used to control whether the transactions are committed automatically in B compatibility."),
GUC_NO_SHOW_ALL | GUC_NOT_IN_SAMPLE},
&u_sess->attr.attr_storage.phony_autocommit,
true,
check_phony_autocommit,
NULL,
assign_phony_autocommit,
NULL},
/*
* security requirements: system/ordinary users can not set current transaction to read-only,
@ -4656,7 +4658,7 @@ void InitializeNumLwLockPartitions(void)
static bool check_phony_autocommit(bool* newval, void** extra, GucSource source)
{
if (!*newval) {
if (!*newval && (!OidIsValid(u_sess->proc_cxt.MyDatabaseId) || !DB_IS_CMPT(B_FORMAT))) {
GUC_check_errcode(ERRCODE_FEATURE_NOT_SUPPORTED);
GUC_check_errmsg("SET AUTOCOMMIT TO OFF is no longer supported");
return false;
@ -4665,6 +4667,18 @@ static bool check_phony_autocommit(bool* newval, void** extra, GucSource source)
return true;
}
static void assign_phony_autocommit(bool newval, void* extra)
{
/* change autocommit from false to on */
if (newval && u_sess->attr.attr_storage.phony_autocommit != newval) {
if (!IsTransactionDefaultState() && !EndTransactionBlock()) {
ereport(ERROR, (errmsg("end transaction failed")));
}
}
return;
}
static bool check_enable_data_replicate(bool* newval, void** extra, GucSource source)
{
/* Always disable data replication in multi standbys mode */

View File

@ -2740,6 +2740,9 @@ static void exec_simple_query(const char* query_string, MessageType messageType,
((ReindexStmt*)parsetree)->kind == OBJECT_DATABASE && IsPostmasterEnvironment)
SetForceXidFromGTM(true);
#endif
if (!u_sess->attr.attr_storage.phony_autocommit) {
BeginTxnForAutoCommitOff();
}
/* SQL bypass */
if (runOpfusionCheck && !IsRightRefState(plantree_list)) {
(void)MemoryContextSwitchTo(oldcontext);
@ -9331,6 +9334,9 @@ int PostgresMain(int argc, char* argv[], const char* dbname, const char* usernam
}
}
bool isQueryCompleted = false;
if (!u_sess->attr.attr_storage.phony_autocommit) {
BeginTxnForAutoCommitOff();
}
if (OpFusion::process(FUSION_EXECUTE, &input_message, completionTag, true, &isQueryCompleted)) {
if(isQueryCompleted) {
CommandCounterIncrement();
@ -11249,6 +11255,9 @@ static void exec_batch_bind_execute(StringInfo input_message)
* we are already in one.
*/
start_xact_command();
if (!u_sess->attr.attr_storage.phony_autocommit) {
BeginTxnForAutoCommitOff();
}
if (ENABLE_WORKLOAD_CONTROL && SqlIsValid(t_thrd.postgres_cxt.debug_query_string) &&
(IS_PGXC_COORDINATOR || IS_SINGLE_NODE) &&

View File

@ -8484,3 +8484,23 @@ static void AtEOXact_Proceed_PatchSeq()
u_sess->opt_cxt.xact_modify_sql_patch = false;
}
}
bool IsTransactionDefaultState()
{
TransactionState s = CurrentTransactionState;
return s->blockState == TBLOCK_DEFAULT;
}
bool IsTransactionInProgressState()
{
TransactionState s = CurrentTransactionState;
return s->blockState == TBLOCK_INPROGRESS;
}
void BeginTxnForAutoCommitOff()
{
TransactionState s = CurrentTransactionState;
if (s->blockState == TBLOCK_STARTED) {
s->blockState = TBLOCK_INPROGRESS;
}
}

View File

@ -464,4 +464,7 @@ extern void push_unlink_rel_to_hashtbl(ColFileNode *xnodes, int nrels);
extern void XactCleanExceptionSubTransaction(SubTransactionId head);
extern char* GetCurrentTransactionName();
extern List* GetTransactionList(List *head);
extern void BeginTxnForAutoCommitOff();
extern bool IsTransactionInProgressState();
extern bool IsTransactionDefaultState();
#endif /* XACT_H */

View File

@ -0,0 +1,243 @@
CREATE DATABASE test_db DBCOMPATIBILITY 'B';
\c test_db
SET autocommit = 1;
CREATE TABLE test_table (a text);
CREATE DATABASE test_drop;
INSERT INTO test_table values('aaaaa');
SELECT * FROM test_table;
a
-------
aaaaa
(1 row)
ROLLBACK;
NOTICE: there is no transaction in progress
SELECT * FROM test_table;
a
-------
aaaaa
(1 row)
SET autocommit = 0;
-- DML
-- rollback the insert statement
INSERT INTO test_table values('bbbbb');
SELECT * FROM test_table;
a
-------
aaaaa
bbbbb
(2 rows)
ROLLBACK;
SELECT * FROM test_table;
a
-------
aaaaa
(1 row)
-- commit the insert statement
INSERT INTO test_table values('ccccc');
SELECT * FROM test_table;
a
-------
aaaaa
ccccc
(2 rows)
COMMIT;
SELECT * FROM test_table;
a
-------
aaaaa
ccccc
(2 rows)
-- commit the insert statement auto
INSERT INTO test_table values('ddddd');
SELECT * FROM test_table;
a
-------
aaaaa
ccccc
ddddd
(3 rows)
SET autocommit = 1;
SELECT * FROM test_table;
a
-------
aaaaa
ccccc
ddddd
(3 rows)
SET autocommit = 0;
-- DDL
-- rollback the create table statement
CREATE TABLE test_a (a text);
INSERT INTO test_a values('aaaaa');
SELECT * FROM test_a;
a
-------
aaaaa
(1 row)
ROLLBACK;
SELECT * FROM test_a;
ERROR: relation "test_a" does not exist on datanode1
LINE 1: SELECT * FROM test_a;
^
COMMIT;
-- commit the create table statement
CREATE TABLE test_b (a text);
INSERT INTO test_b values('aaaaa');
SELECT * FROM test_b;
a
-------
aaaaa
(1 row)
COMMIT;
SELECT * FROM test_b;
a
-------
aaaaa
(1 row)
-- commit the create table statement auto
CREATE TABLE test_c (a text);
INSERT INTO test_c values('aaaaa');
SELECT * FROM test_c;
a
-------
aaaaa
(1 row)
SET autocommit = 1;
SELECT * FROM test_c;
a
-------
aaaaa
(1 row)
-- prepare test
SET autocommit = 0;
INSERT INTO test_table values('eeeee');
PREPARE TRANSACTION 'test_id';
SET autocommit = 1;
SELECT * FROM test_table;
a
-------
aaaaa
ccccc
ddddd
(3 rows)
COMMIT PREPARED 'test_id';
SELECT * FROM test_table;
a
-------
aaaaa
ccccc
ddddd
eeeee
(4 rows)
-- truncate the table test_table
TRUNCATE test_table;
SELECT * FROM test_table;
a
---
(0 rows)
ROLLBACK;
NOTICE: there is no transaction in progress
TRUNCATE test_table;
SELECT * FROM test_table;
a
---
(0 rows)
COMMIT;
WARNING: there is no transaction in progress
SELECT * FROM test_table;
a
---
(0 rows)
-- something statement could not execute in the transaction block
SET autocommit = 0;
START TRANSACTION;
WARNING: there is already a transaction in progress
BEGIN;
WARNING: there is already a transaction in progress
CREATE DATABASE test_error;
ERROR: CREATE DATABASE cannot run inside a transaction block
ROLLBACK;
VACUUM;
ERROR: VACUUM cannot run inside a transaction block
ROLLBACK;
DROP DATABASE test_drop;
ERROR: DROP DATABASE cannot run inside a transaction block
ROLLBACK;
CLUSTER test_table;
ERROR: CLUSTER cannot run inside a transaction block
ROLLBACK;
CREATE TABLESPACE gs_basebackup_tablespace relative LOCATION 'gs_basebackup_tablespace';
ERROR: CREATE TABLESPACE cannot run inside a transaction block
ROLLBACK;
CREATE INDEX CONCURRENTLY ON test_table(a);
ERROR: CREATE INDEX CONCURRENTLY cannot run inside a transaction block
ROLLBACK;
REINDEX DATABASE test_db;
ERROR: REINDEX DATABASE cannot run inside a transaction block
ROLLBACK;
DROP DATABASE test_error;
ERROR: DROP DATABASE cannot run inside a transaction block
ROLLBACK;
DROP TABLESPACE test_space;
ERROR: DROP TABLESPACE cannot run inside a transaction block
ROLLBACK;
DROP INDEX test_index;
ERROR: index "test_index" does not exist
ROLLBACK;
REINDEX TABLE CONCURRENTLY test_table;
ERROR: REINDEX CONCURRENTLY cannot run inside a transaction block
-- test about set autocommit = 1 when the transaction is aborted
SET autocommit = 1;
ERROR: current transaction is aborted, commands ignored until end of transaction block, firstChar[Q]
ROLLBACK;
-- set autocommit = 0 in a transaction block
SET autocommit = 1;
TRUNCATE test_table;
BEGIN;
INSERT INTO test_table values('aaaaa');
SET autocommit = 0;
SET autocommit = 1;
SHOW autocommit;
autocommit
------------
on
(1 row)
SELECT * FROM test_table;
a
-------
aaaaa
(1 row)
-- only set autocommit = 1 cannot commit transaction
BEGIN;
INSERT INTO test_table values('bbbbb');
SET autocommit = 1;
ROLLBACK;
SELECT * FROM test_table;
a
-------
aaaaa
(1 row)
\c regression
DROP DATABASE test_db;
DROP DATABASE test_drop;

View File

@ -190,7 +190,7 @@ test: single_node_select_implicit single_node_select_having
test: single_node_union
#test: single_node_case single_node_join single_node_aggregates
#test: single_node_transactions
test: single_node_random transactions_test
test: single_node_random transactions_test autocommit_test
#test: single_node_portals
#test: single_node_arrays
#test: single_node_btree_index single_node_hash_index single_node_update

View File

@ -0,0 +1,121 @@
CREATE DATABASE test_db DBCOMPATIBILITY 'B';
\c test_db
SET autocommit = 1;
CREATE TABLE test_table (a text);
CREATE DATABASE test_drop;
INSERT INTO test_table values('aaaaa');
SELECT * FROM test_table;
ROLLBACK;
SELECT * FROM test_table;
SET autocommit = 0;
-- DML
-- rollback the insert statement
INSERT INTO test_table values('bbbbb');
SELECT * FROM test_table;
ROLLBACK;
SELECT * FROM test_table;
-- commit the insert statement
INSERT INTO test_table values('ccccc');
SELECT * FROM test_table;
COMMIT;
SELECT * FROM test_table;
-- commit the insert statement auto
INSERT INTO test_table values('ddddd');
SELECT * FROM test_table;
SET autocommit = 1;
SELECT * FROM test_table;
SET autocommit = 0;
-- DDL
-- rollback the create table statement
CREATE TABLE test_a (a text);
INSERT INTO test_a values('aaaaa');
SELECT * FROM test_a;
ROLLBACK;
SELECT * FROM test_a;
COMMIT;
-- commit the create table statement
CREATE TABLE test_b (a text);
INSERT INTO test_b values('aaaaa');
SELECT * FROM test_b;
COMMIT;
SELECT * FROM test_b;
-- commit the create table statement auto
CREATE TABLE test_c (a text);
INSERT INTO test_c values('aaaaa');
SELECT * FROM test_c;
SET autocommit = 1;
SELECT * FROM test_c;
-- prepare test
SET autocommit = 0;
INSERT INTO test_table values('eeeee');
PREPARE TRANSACTION 'test_id';
SET autocommit = 1;
SELECT * FROM test_table;
COMMIT PREPARED 'test_id';
SELECT * FROM test_table;
-- truncate the table test_table
TRUNCATE test_table;
SELECT * FROM test_table;
ROLLBACK;
TRUNCATE test_table;
SELECT * FROM test_table;
COMMIT;
SELECT * FROM test_table;
-- something statement could not execute in the transaction block
SET autocommit = 0;
START TRANSACTION;
BEGIN;
CREATE DATABASE test_error;
ROLLBACK;
VACUUM;
ROLLBACK;
DROP DATABASE test_drop;
ROLLBACK;
CLUSTER test_table;
ROLLBACK;
CREATE TABLESPACE gs_basebackup_tablespace relative LOCATION 'gs_basebackup_tablespace';
ROLLBACK;
CREATE INDEX CONCURRENTLY ON test_table(a);
ROLLBACK;
REINDEX DATABASE test_db;
ROLLBACK;
DROP DATABASE test_error;
ROLLBACK;
DROP TABLESPACE test_space;
ROLLBACK;
DROP INDEX test_index;
ROLLBACK;
REINDEX TABLE CONCURRENTLY test_table;
-- test about set autocommit = 1 when the transaction is aborted
SET autocommit = 1;
ROLLBACK;
-- set autocommit = 0 in a transaction block
SET autocommit = 1;
TRUNCATE test_table;
BEGIN;
INSERT INTO test_table values('aaaaa');
SET autocommit = 0;
SET autocommit = 1;
SHOW autocommit;
SELECT * FROM test_table;
-- only set autocommit = 1 cannot commit transaction
BEGIN;
INSERT INTO test_table values('bbbbb');
SET autocommit = 1;
ROLLBACK;
SELECT * FROM test_table;
\c regression
DROP DATABASE test_db;
DROP DATABASE test_drop;