From 32ce3f068a96fb8df185c935b11abb254697d7be 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 v5 2/5] 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/nodes/outfuncs.c     | 12 ++++++++++++
 src/backend/nodes/readfuncs.c    | 15 +++++++++++++++
 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 +
 10 files changed, 97 insertions(+), 2 deletions(-)

diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 89c409de664..ba3393b8ccf 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 e3f33c40be5..b09bff458af 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/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index e2f177515da..37f297f39a5 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -1358,6 +1358,15 @@ _outAlternativeSubPlan(StringInfo str, const AlternativeSubPlan *node)
 	WRITE_NODE_FIELD(subplans);
 }
 
+static void
+_outAlterSystemWALProhibitState(StringInfo str,
+								const AlterSystemWALProhibitState *node)
+{
+	WRITE_NODE_TYPE("ALTERSYSTEMWALPROHIBITSTATE");
+
+	WRITE_BOOL_FIELD(WALProhibited);
+}
+
 static void
 _outFieldSelect(StringInfo str, const FieldSelect *node)
 {
@@ -3914,6 +3923,9 @@ outNode(StringInfo str, const void *obj)
 			case T_AlternativeSubPlan:
 				_outAlternativeSubPlan(str, obj);
 				break;
+			case T_AlterSystemWALProhibitState:
+				_outAlterSystemWALProhibitState(str, obj);
+				break;
 			case T_FieldSelect:
 				_outFieldSelect(str, obj);
 				break;
diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c
index 42050ab7195..0ac826d3c2f 100644
--- a/src/backend/nodes/readfuncs.c
+++ b/src/backend/nodes/readfuncs.c
@@ -2552,6 +2552,19 @@ _readAlternativeSubPlan(void)
 	READ_DONE();
 }
 
+/*
+ * _readAlterSystemWALProhibitState
+ */
+static AlterSystemWALProhibitState *
+_readAlterSystemWALProhibitState(void)
+{
+	READ_LOCALS(AlterSystemWALProhibitState);
+
+	READ_BOOL_FIELD(WALProhibited);
+
+	READ_DONE();
+}
+
 /*
  * _readExtensibleNode
  */
@@ -2874,6 +2887,8 @@ parseNodeString(void)
 		return_value = _readSubPlan();
 	else if (MATCH("ALTERNATIVESUBPLAN", 18))
 		return_value = _readAlternativeSubPlan();
+	else if (MATCH("ALTERSYSTEMWALPROHIBITSTATE", 27))
+		return_value = _readAlterSystemWALProhibitState();
 	else if (MATCH("EXTENSIBLENODE", 14))
 		return_value = _readExtensibleNode();
 	else if (MATCH("PARTITIONBOUNDSPEC", 18))
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index dbb47d49829..6090d18ec61 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -479,6 +479,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
@@ -10172,8 +10173,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 9b0c376c8cb..7af96c77082 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 f41785f11c1..408f6260b26 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -1864,9 +1864,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 151bcdb7ef5..f2c1ae8e3fe 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 3d990463ce9..29d6f6c968d 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.22.0

