From bc61aef9b1749d503ab9c020f83d48c357f80122 Mon Sep 17 00:00:00 2001
From: Amul Sul <amul.sul@enterprisedb.com>
Date: Fri, 27 Mar 2020 05:05:38 -0400
Subject: [PATCH v2 2/6] Add alter system read only/write syntax

Note that syntax doesn't have any implementation.
---
 src/backend/nodes/copyfuncs.c    | 12 ++++++++++++
 src/backend/nodes/equalfuncs.c   |  9 +++++++++
 src/backend/parser/gram.y        | 13 +++++++++++++
 src/backend/tcop/utility.c       | 20 ++++++++++++++++++++
 src/bin/psql/tab-complete.c      |  6 ++++--
 src/include/nodes/nodes.h        |  1 +
 src/include/nodes/parsenodes.h   | 10 ++++++++++
 src/tools/pgindent/typedefs.list |  1 +
 8 files changed, 70 insertions(+), 2 deletions(-)

diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index d8cf87e6d08..19aa6a2f88b 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -4020,6 +4020,15 @@ _copyAlterSystemStmt(const AlterSystemStmt *from)
 	return newnode;
 }
 
+static AlterSystemWALProhibitState *
+_copyAlterSystemWALProhibitState(const AlterSystemWALProhibitState *from)
+{
+	AlterSystemWALProhibitState *newnode = makeNode(AlterSystemWALProhibitState);
+
+	COPY_SCALAR_FIELD(WALProhibited);
+	return newnode;
+}
+
 static CreateSeqStmt *
 _copyCreateSeqStmt(const CreateSeqStmt *from)
 {
@@ -5406,6 +5415,9 @@ copyObjectImpl(const void *from)
 		case T_AlterSystemStmt:
 			retval = _copyAlterSystemStmt(from);
 			break;
+		case T_AlterSystemWALProhibitState:
+			retval = _copyAlterSystemWALProhibitState(from);
+			break;
 		case T_CreateSeqStmt:
 			retval = _copyCreateSeqStmt(from);
 			break;
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index 627b026b195..01cedb38115 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -1769,6 +1769,12 @@ _equalAlterSystemStmt(const AlterSystemStmt *a, const AlterSystemStmt *b)
 	return true;
 }
 
+static bool
+_equalAlterSystemWALProhibitState(const AlterSystemWALProhibitState *a, const AlterSystemWALProhibitState *b)
+{
+	COMPARE_SCALAR_FIELD(WALProhibited);
+	return true;
+}
 
 static bool
 _equalCreateSeqStmt(const CreateSeqStmt *a, const CreateSeqStmt *b)
@@ -3458,6 +3464,9 @@ equal(const void *a, const void *b)
 		case T_AlterSystemStmt:
 			retval = _equalAlterSystemStmt(a, b);
 			break;
+		case T_AlterSystemWALProhibitState:
+			retval = _equalAlterSystemWALProhibitState(a, b);
+			break;
 		case T_CreateSeqStmt:
 			retval = _equalCreateSeqStmt(a, b);
 			break;
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index e669d75a5af..f97bd6f658e 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -480,6 +480,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
 
 %type <vsetstmt> generic_set set_rest set_rest_more generic_reset reset_rest
 				 SetResetClause FunctionSetResetClause
+%type <boolean> system_readonly_state
 
 %type <node>	TableElement TypedTableElement ConstraintElem TableFuncElement
 %type <node>	columnDef columnOptions
@@ -10173,8 +10174,20 @@ AlterSystemStmt:
 					n->setstmt = $4;
 					$$ = (Node *)n;
 				}
+			| ALTER SYSTEM_P system_readonly_state
+				{
+					AlterSystemWALProhibitState *n = makeNode(AlterSystemWALProhibitState);
+					n->WALProhibited = $3;
+					$$ = (Node *)n;
+				}
 		;
 
+system_readonly_state:
+			 READ ONLY
+					{ $$ = true; }
+			| READ WRITE
+					{ $$ = false; }
+		;
 
 /*****************************************************************************
  *
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 97cbaa3072b..900088a2209 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -85,6 +85,7 @@ static void ProcessUtilitySlow(ParseState *pstate,
 							   DestReceiver *dest,
 							   QueryCompletion *qc);
 static void ExecDropStmt(DropStmt *stmt, bool isTopLevel);
+static void AlterSystemSetWALProhibitState(AlterSystemWALProhibitState *stmt);
 
 /*
  * CommandIsReadOnly: is an executable query read-only?
@@ -219,6 +220,7 @@ ClassifyUtilityCommandAsReadOnly(Node *parsetree)
 				return COMMAND_IS_NOT_READ_ONLY;
 			}
 
+		case T_AlterSystemWALProhibitState:
 		case T_AlterSystemStmt:
 			{
 				/*
@@ -834,6 +836,11 @@ standard_ProcessUtility(PlannedStmt *pstmt,
 			AlterSystemSetConfigFile((AlterSystemStmt *) parsetree);
 			break;
 
+		case T_AlterSystemWALProhibitState:
+			PreventInTransactionBlock(isTopLevel, "ALTER SYSTEM");
+			AlterSystemSetWALProhibitState((AlterSystemWALProhibitState *) parsetree);
+			break;
+
 		case T_VariableSetStmt:
 			ExecSetVariableStmt((VariableSetStmt *) parsetree, isTopLevel);
 			break;
@@ -2772,6 +2779,7 @@ CreateCommandTag(Node *parsetree)
 			tag = CMDTAG_REFRESH_MATERIALIZED_VIEW;
 			break;
 
+		case T_AlterSystemWALProhibitState:
 		case T_AlterSystemStmt:
 			tag = CMDTAG_ALTER_SYSTEM;
 			break;
@@ -3636,3 +3644,15 @@ GetCommandLogLevel(Node *parsetree)
 
 	return lev;
 }
+
+/*
+ * AlterSystemSetWALProhibitState
+ *
+ * Execute ALTER SYSTEM READ { ONLY | WRITE } statement.
+ */
+static void
+AlterSystemSetWALProhibitState(AlterSystemWALProhibitState *stmt)
+{
+	/* some code */
+	elog(INFO, "AlterSystemSetWALProhibitState() called");
+}
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index eb018854a5c..d586cf74816 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -1858,9 +1858,11 @@ psql_completion(const char *text, int start, int end)
 	/* ALTER SERVER <name> VERSION <version> */
 	else if (Matches("ALTER", "SERVER", MatchAny, "VERSION", MatchAny))
 		COMPLETE_WITH("OPTIONS");
-	/* ALTER SYSTEM SET, RESET, RESET ALL */
+	/* ALTER SYSTEM READ, SET, RESET, RESET ALL */
 	else if (Matches("ALTER", "SYSTEM"))
-		COMPLETE_WITH("SET", "RESET");
+		COMPLETE_WITH("SET", "RESET", "READ");
+	else if (Matches("ALTER", "SYSTEM", "READ"))
+		COMPLETE_WITH("ONLY", "WRITE");
 	else if (Matches("ALTER", "SYSTEM", "SET|RESET"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_alter_system_set_vars);
 	else if (Matches("ALTER", "SYSTEM", "SET", MatchAny))
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
index 381d84b4e4f..17d6942c734 100644
--- a/src/include/nodes/nodes.h
+++ b/src/include/nodes/nodes.h
@@ -412,6 +412,7 @@ typedef enum NodeTag
 	T_RefreshMatViewStmt,
 	T_ReplicaIdentityStmt,
 	T_AlterSystemStmt,
+	T_AlterSystemWALProhibitState,
 	T_CreatePolicyStmt,
 	T_AlterPolicyStmt,
 	T_CreateTransformStmt,
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 5e1ffafb91b..636654bb450 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -3194,6 +3194,16 @@ typedef struct AlterSystemStmt
 	VariableSetStmt *setstmt;	/* SET subcommand */
 } AlterSystemStmt;
 
+/* ----------------------
+ *		Alter System Read Statement
+ * ----------------------
+ */
+typedef struct AlterSystemWALProhibitState
+{
+	NodeTag		type;
+	bool		WALProhibited;
+} AlterSystemWALProhibitState;
+
 /* ----------------------
  *		Cluster Statement (support pbrown's cluster index implementation)
  * ----------------------
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index c65a55257dd..eb48b29828e 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -87,6 +87,7 @@ AlterStatsStmt
 AlterSubscriptionStmt
 AlterSubscriptionType
 AlterSystemStmt
+AlterSystemWALProhibitState
 AlterTSConfigType
 AlterTSConfigurationStmt
 AlterTSDictionaryStmt
-- 
2.18.0

