merge psql ef/ev sf/sv handling functions

Started by Fabien COELHOalmost 9 years ago9 messages
#1Fabien COELHO
coelho@cri.ensmp.fr
1 attachment(s)

Hello,

While reviewing Corey's \if patch, I complained that there was some amount
of copy-paste in "psql/command.c".

Here is an attempt at merging some functions which removes 160 lines of
code.

--
Fabien.

Attachments:

psql-merge-fv-1.patchtext/x-diff; name=psql-merge-fv-1.patchDownload
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 94a3cfc..edf875d 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -75,10 +75,8 @@ static backslashResult exec_command_d(PsqlScanState scan_state, bool active_bran
 			   const char *cmd);
 static backslashResult exec_command_edit(PsqlScanState scan_state, bool active_branch,
 				  PQExpBuffer query_buf, PQExpBuffer previous_buf);
-static backslashResult exec_command_ef(PsqlScanState scan_state, bool active_branch,
-				PQExpBuffer query_buf);
-static backslashResult exec_command_ev(PsqlScanState scan_state, bool active_branch,
-				PQExpBuffer query_buf);
+static backslashResult exec_command_ef_ev(PsqlScanState scan_state, bool active_branch,
+										  PQExpBuffer query_buf, bool is_func);
 static backslashResult exec_command_echo(PsqlScanState scan_state, bool active_branch,
 				  const char *cmd);
 static backslashResult exec_command_elif(PsqlScanState scan_state, ConditionalStack cstack,
@@ -118,10 +116,8 @@ static backslashResult exec_command_s(PsqlScanState scan_state, bool active_bran
 static backslashResult exec_command_set(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_setenv(PsqlScanState scan_state, bool active_branch,
 					const char *cmd);
-static backslashResult exec_command_sf(PsqlScanState scan_state, bool active_branch,
-				const char *cmd);
-static backslashResult exec_command_sv(PsqlScanState scan_state, bool active_branch,
-				const char *cmd);
+static backslashResult exec_command_sf_sv(PsqlScanState scan_state, bool active_branch,
+										  const char *cmd, bool is_func);
 static backslashResult exec_command_t(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_T(PsqlScanState scan_state, bool active_branch);
 static backslashResult exec_command_timing(PsqlScanState scan_state, bool active_branch);
@@ -322,9 +318,9 @@ exec_command(const char *cmd,
 		status = exec_command_edit(scan_state, active_branch,
 								   query_buf, previous_buf);
 	else if (strcmp(cmd, "ef") == 0)
-		status = exec_command_ef(scan_state, active_branch, query_buf);
+		status = exec_command_ef_ev(scan_state, active_branch, query_buf, true);
 	else if (strcmp(cmd, "ev") == 0)
-		status = exec_command_ev(scan_state, active_branch, query_buf);
+		status = exec_command_ef_ev(scan_state, active_branch, query_buf, false);
 	else if (strcmp(cmd, "echo") == 0 || strcmp(cmd, "qecho") == 0)
 		status = exec_command_echo(scan_state, active_branch, cmd);
 	else if (strcmp(cmd, "elif") == 0)
@@ -380,9 +376,9 @@ exec_command(const char *cmd,
 	else if (strcmp(cmd, "setenv") == 0)
 		status = exec_command_setenv(scan_state, active_branch, cmd);
 	else if (strcmp(cmd, "sf") == 0 || strcmp(cmd, "sf+") == 0)
-		status = exec_command_sf(scan_state, active_branch, cmd);
+		status = exec_command_sf_sv(scan_state, active_branch, cmd, true);
 	else if (strcmp(cmd, "sv") == 0 || strcmp(cmd, "sv+") == 0)
-		status = exec_command_sv(scan_state, active_branch, cmd);
+		status = exec_command_sf_sv(scan_state, active_branch, cmd, false);
 	else if (strcmp(cmd, "t") == 0)
 		status = exec_command_t(scan_state, active_branch);
 	else if (strcmp(cmd, "T") == 0)
@@ -976,28 +972,29 @@ exec_command_edit(PsqlScanState scan_state, bool active_branch,
 }
 
 /*
- * \ef -- edit the named function, or present a blank CREATE FUNCTION
- * template if no argument is given
+ * \ef/\ev -- edit the named function/view, or
+ * present a blank CREATE FUNCTION/VIEW template if no argument is given
  */
 static backslashResult
-exec_command_ef(PsqlScanState scan_state, bool active_branch,
-				PQExpBuffer query_buf)
+exec_command_ef_ev(PsqlScanState scan_state, bool active_branch,
+					  PQExpBuffer query_buf, bool is_func)
 {
 	backslashResult status = PSQL_CMD_SKIP_LINE;
 
 	if (active_branch)
 	{
-		char	   *func = psql_scan_slash_option(scan_state,
-												  OT_WHOLE_LINE, NULL, true);
+		char	   *stuff = psql_scan_slash_option(scan_state,
+													OT_WHOLE_LINE, NULL, true);
 		int			lineno = -1;
 
-		if (pset.sversion < 80400)
+		if (pset.sversion < (is_func ? 80400 : 70400))
 		{
 			char		sverbuf[32];
 
-			psql_error("The server (version %s) does not support editing function source.\n",
+			psql_error("The server (version %s) does not support editing %s.\n",
 					   formatPGVersionNumber(pset.sversion, false,
-											 sverbuf, sizeof(sverbuf)));
+											 sverbuf, sizeof(sverbuf)),
+					   is_func ? "function source" : "view definitions");
 			status = PSQL_CMD_ERROR;
 		}
 		else if (!query_buf)
@@ -1007,36 +1004,43 @@ exec_command_ef(PsqlScanState scan_state, bool active_branch,
 		}
 		else
 		{
-			Oid			foid = InvalidOid;
+			Oid			stuff_oid = InvalidOid;
+			EditableObjectType	eot = is_func ? EditableFunction : EditableView;
 
-			lineno = strip_lineno_from_objdesc(func);
+			lineno = strip_lineno_from_objdesc(stuff);
 			if (lineno == 0)
 			{
 				/* error already reported */
 				status = PSQL_CMD_ERROR;
 			}
-			else if (!func)
+			else if (!stuff)
 			{
 				/* set up an empty command to fill in */
-				printfPQExpBuffer(query_buf,
-								  "CREATE FUNCTION ( )\n"
-								  " RETURNS \n"
-								  " LANGUAGE \n"
-								  " -- common options:  IMMUTABLE  STABLE  STRICT  SECURITY DEFINER\n"
-								  "AS $function$\n"
-								  "\n$function$\n");
+				resetPQExpBuffer(query_buf);
+				appendPQExpBufferStr(query_buf,
+									 is_func ?
+									 "CREATE FUNCTION ( )\n"
+									 " RETURNS \n"
+									 " LANGUAGE \n"
+									 " -- common options:  IMMUTABLE  STABLE  STRICT  SECURITY DEFINER\n"
+									 "AS $function$\n"
+									 "\n$function$\n"
+									 :
+									 "CREATE VIEW  AS\n"
+									 " SELECT \n"
+									 "  -- something...\n");
 			}
-			else if (!lookup_object_oid(EditableFunction, func, &foid))
+			else if (!lookup_object_oid(eot, stuff, &stuff_oid))
 			{
 				/* error already reported */
 				status = PSQL_CMD_ERROR;
 			}
-			else if (!get_create_object_cmd(EditableFunction, foid, query_buf))
+			else if (!get_create_object_cmd(eot, stuff_oid, query_buf))
 			{
 				/* error already reported */
 				status = PSQL_CMD_ERROR;
 			}
-			else if (lineno > 0)
+			else if (is_func && lineno > 0)
 			{
 				/*
 				 * lineno "1" should correspond to the first line of the
@@ -1075,89 +1079,8 @@ exec_command_ef(PsqlScanState scan_state, bool active_branch,
 				status = PSQL_CMD_NEWEDIT;
 		}
 
-		if (func)
-			free(func);
-	}
-	else
-		ignore_slash_whole_line(scan_state);
-
-	return status;
-}
-
-/*
- * \ev -- edit the named view, or present a blank CREATE VIEW
- * template if no argument is given
- */
-static backslashResult
-exec_command_ev(PsqlScanState scan_state, bool active_branch,
-				PQExpBuffer query_buf)
-{
-	backslashResult status = PSQL_CMD_SKIP_LINE;
-
-	if (active_branch)
-	{
-		char	   *view = psql_scan_slash_option(scan_state,
-												  OT_WHOLE_LINE, NULL, true);
-		int			lineno = -1;
-
-		if (pset.sversion < 70400)
-		{
-			char		sverbuf[32];
-
-			psql_error("The server (version %s) does not support editing view definitions.\n",
-					   formatPGVersionNumber(pset.sversion, false,
-											 sverbuf, sizeof(sverbuf)));
-			status = PSQL_CMD_ERROR;
-		}
-		else if (!query_buf)
-		{
-			psql_error("no query buffer\n");
-			status = PSQL_CMD_ERROR;
-		}
-		else
-		{
-			Oid			view_oid = InvalidOid;
-
-			lineno = strip_lineno_from_objdesc(view);
-			if (lineno == 0)
-			{
-				/* error already reported */
-				status = PSQL_CMD_ERROR;
-			}
-			else if (!view)
-			{
-				/* set up an empty command to fill in */
-				printfPQExpBuffer(query_buf,
-								  "CREATE VIEW  AS\n"
-								  " SELECT \n"
-								  "  -- something...\n");
-			}
-			else if (!lookup_object_oid(EditableView, view, &view_oid))
-			{
-				/* error already reported */
-				status = PSQL_CMD_ERROR;
-			}
-			else if (!get_create_object_cmd(EditableView, view_oid, query_buf))
-			{
-				/* error already reported */
-				status = PSQL_CMD_ERROR;
-			}
-		}
-
-		if (status != PSQL_CMD_ERROR)
-		{
-			bool		edited = false;
-
-			if (!do_edit(NULL, query_buf, lineno, &edited))
-				status = PSQL_CMD_ERROR;
-			else if (!edited)
-				puts(_("No changes"));
-			else
-				status = PSQL_CMD_NEWEDIT;
-		}
-
-		if (view)
-			free(view);
+		if (stuff)
+			free(stuff);
 	}
 	else
 		ignore_slash_whole_line(scan_state);
@@ -2207,43 +2130,47 @@ exec_command_setenv(PsqlScanState scan_state, bool active_branch,
 }
 
 /*
- * \sf -- show a function's source code
+ * \sf \sv -- show a function/views's source code
  */
 static backslashResult
-exec_command_sf(PsqlScanState scan_state, bool active_branch, const char *cmd)
+exec_command_sf_sv(PsqlScanState scan_state, bool active_branch,
+				   const char *cmd, bool is_func)
 {
 	backslashResult status = PSQL_CMD_SKIP_LINE;
 
 	if (active_branch)
 	{
-		bool		show_linenumbers = (strcmp(cmd, "sf+") == 0);
-		PQExpBuffer func_buf;
-		char	   *func;
-		Oid			foid = InvalidOid;
+		bool		show_linenumbers = strcmp(cmd, is_func ? "sf+" : "sv+") == 0;
+		PQExpBuffer buf;
+		char	   *stuff;
+		Oid			stuff_oid = InvalidOid;
+		EditableObjectType	eot = is_func ? EditableFunction : EditableView;
 
-		func_buf = createPQExpBuffer();
-		func = psql_scan_slash_option(scan_state,
-									  OT_WHOLE_LINE, NULL, true);
-		if (pset.sversion < 80400)
+
+		buf = createPQExpBuffer();
+		stuff = psql_scan_slash_option(scan_state,
+									   OT_WHOLE_LINE, NULL, true);
+		if (pset.sversion < (is_func ? 80400 : 70400))
 		{
 			char		sverbuf[32];
 
-			psql_error("The server (version %s) does not support showing function source.\n",
+			psql_error("The server (version %s) does not support showing %s.\n",
 					   formatPGVersionNumber(pset.sversion, false,
-											 sverbuf, sizeof(sverbuf)));
+											 sverbuf, sizeof(sverbuf)),
+					   is_func ? "function source" : "view definitions");
 			status = PSQL_CMD_ERROR;
 		}
-		else if (!func)
+		else if (!stuff)
 		{
-			psql_error("function name is required\n");
+			psql_error("%s name is required\n", is_func ? "function" : "view");
 			status = PSQL_CMD_ERROR;
 		}
-		else if (!lookup_object_oid(EditableFunction, func, &foid))
+		else if (!lookup_object_oid(eot, stuff, &stuff_oid))
 		{
 			/* error already reported */
 			status = PSQL_CMD_ERROR;
 		}
-		else if (!get_create_object_cmd(EditableFunction, foid, func_buf))
+		else if (!get_create_object_cmd(eot, stuff_oid, buf))
 		{
 			/* error already reported */
 			status = PSQL_CMD_ERROR;
@@ -2257,7 +2184,7 @@ exec_command_sf(PsqlScanState scan_state, bool active_branch, const char *cmd)
 			if (pset.queryFout == stdout)
 			{
 				/* count lines in function to see if pager is needed */
-				int			lineno = count_lines_in_buf(func_buf);
+				int			lineno = count_lines_in_buf(buf);
 
 				output = PageOutput(lineno, &(pset.popt.topt));
 				is_pager = true;
@@ -2278,109 +2205,22 @@ exec_command_sf(PsqlScanState scan_state, bool active_branch, const char *cmd)
 				 * can be no such line before the real start of the function
 				 * body.
 				 */
-				print_with_linenumbers(output, func_buf->data, "AS ");
+				print_with_linenumbers(output, buf->data,
+									   is_func ? "AS " : NULL);
 			}
 			else
 			{
-				/* just send the function definition to output */
-				fputs(func_buf->data, output);
+				/* just send the definition to output */
+				fputs(buf->data, output);
 			}
 
 			if (is_pager)
 				ClosePager(output);
 		}
 
-		if (func)
-			free(func);
-		destroyPQExpBuffer(func_buf);
-	}
-	else
-		ignore_slash_whole_line(scan_state);
-
-	return status;
-}
-
-/*
- * \sv -- show a view's source code
- */
-static backslashResult
-exec_command_sv(PsqlScanState scan_state, bool active_branch, const char *cmd)
-{
-	backslashResult status = PSQL_CMD_SKIP_LINE;
-
-	if (active_branch)
-	{
-		bool		show_linenumbers = (strcmp(cmd, "sv+") == 0);
-		PQExpBuffer view_buf;
-		char	   *view;
-		Oid			view_oid = InvalidOid;
-
-		view_buf = createPQExpBuffer();
-		view = psql_scan_slash_option(scan_state,
-									  OT_WHOLE_LINE, NULL, true);
-		if (pset.sversion < 70400)
-		{
-			char		sverbuf[32];
-
-			psql_error("The server (version %s) does not support showing view definitions.\n",
-					   formatPGVersionNumber(pset.sversion, false,
-											 sverbuf, sizeof(sverbuf)));
-			status = PSQL_CMD_ERROR;
-		}
-		else if (!view)
-		{
-			psql_error("view name is required\n");
-			status = PSQL_CMD_ERROR;
-		}
-		else if (!lookup_object_oid(EditableView, view, &view_oid))
-		{
-			/* error already reported */
-			status = PSQL_CMD_ERROR;
-		}
-		else if (!get_create_object_cmd(EditableView, view_oid, view_buf))
-		{
-			/* error already reported */
-			status = PSQL_CMD_ERROR;
-		}
-		else
-		{
-			FILE	   *output;
-			bool		is_pager;
-
-			/* Select output stream: stdout, pager, or file */
-			if (pset.queryFout == stdout)
-			{
-				/* count lines in view to see if pager is needed */
-				int			lineno = count_lines_in_buf(view_buf);
-
-				output = PageOutput(lineno, &(pset.popt.topt));
-				is_pager = true;
-			}
-			else
-			{
-				/* use previously set output file, without pager */
-				output = pset.queryFout;
-				is_pager = false;
-			}
-
-			if (show_linenumbers)
-			{
-				/* add line numbers, numbering all lines */
-				print_with_linenumbers(output, view_buf->data, NULL);
-			}
-			else
-			{
-				/* just send the view definition to output */
-				fputs(view_buf->data, output);
-			}
-
-			if (is_pager)
-				ClosePager(output);
-		}
-
-		if (view)
-			free(view);
-		destroyPQExpBuffer(view_buf);
+		if (stuff)
+			free(stuff);
+		destroyPQExpBuffer(buf);
 	}
 	else
 		ignore_slash_whole_line(scan_state);
#2Victor Drobny
v.drobny@postgrespro.ru
In reply to: Fabien COELHO (#1)
Re: merge psql ef/ev sf/sv handling functions

On 2017-03-31 21:04, Fabien COELHO wrote:

Hello,

While reviewing Corey's \if patch, I complained that there was some
amount of copy-paste in "psql/command.c".

Here is an attempt at merging some functions which removes 160 lines of
code.

Hello,

I was looking through your patch. It seems good, the of the functions
was very similar.
I have a question for you. What was the reason to replace
"printfPQExpBuffer" by "resetPQExpBuffer" and "appendPQExpBufferStr"?

Thank you for attention!

--
------
Victor Drobny
Postgres Professional: http://www.postgrespro.com
The Russian Postgres Company

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#3Fabien COELHO
coelho@cri.ensmp.fr
In reply to: Victor Drobny (#2)
Re: merge psql ef/ev sf/sv handling functions

Hello Victor,

While reviewing Corey's \if patch, I complained that there was some
amount of copy-paste in "psql/command.c".

Here is an attempt at merging some functions which removes 160 lines of
code.

I was looking through your patch. It seems good, the of the functions was
very similar.

Indeed. I guess that it was initially a copy paste.

I have a question for you. What was the reason to replace "printfPQExpBuffer"
by "resetPQExpBuffer" and "appendPQExpBufferStr"?

Because the "printf" version implies interpreting the format layer which
does not add significant value compared to just appending the string.

--
Fabien.

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#4Masahiko Sawada
sawada.mshk@gmail.com
In reply to: Fabien COELHO (#1)
Re: merge psql ef/ev sf/sv handling functions

On Sat, Apr 1, 2017 at 3:04 AM, Fabien COELHO <coelho@cri.ensmp.fr> wrote:

Hello,

While reviewing Corey's \if patch, I complained that there was some amount
of copy-paste in "psql/command.c".

Here is an attempt at merging some functions which removes 160 lines of
code.

Thank you for the patch. Is this an item for PG11?

Regards,

--
Masahiko Sawada
NIPPON TELEGRAPH AND TELEPHONE CORPORATION
NTT Open Source Software Center

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#5Fabien COELHO
fabien.coelho@mines-paristech.fr
In reply to: Masahiko Sawada (#4)
Re: merge psql ef/ev sf/sv handling functions

While reviewing Corey's \if patch, I complained that there was some amount
of copy-paste in "psql/command.c".

Here is an attempt at merging some functions which removes 160 lines of
code.

Thank you for the patch. Is this an item for PG11?

Yep.

--
Fabien.

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#6Fabien COELHO
coelho@cri.ensmp.fr
In reply to: Masahiko Sawada (#4)
Re: merge psql ef/ev sf/sv handling functions

While reviewing Corey's \if patch, I complained that there was some amount
of copy-paste in "psql/command.c".

Here is an attempt at merging some functions which removes 160 lines of
code.

Thank you for the patch. Is this an item for PG11?

Yes, as it is submitted to CF 2017-09.

--
Fabien.

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#7Masahiko Sawada
sawada.mshk@gmail.com
In reply to: Fabien COELHO (#6)
Re: merge psql ef/ev sf/sv handling functions

On Wed, Jul 19, 2017 at 2:41 PM, Fabien COELHO <coelho@cri.ensmp.fr> wrote:

While reviewing Corey's \if patch, I complained that there was some
amount
of copy-paste in "psql/command.c".

Here is an attempt at merging some functions which removes 160 lines of
code.

Thank you for the patch. Is this an item for PG11?

Yes, as it is submitted to CF 2017-09.

Thank!
It is already registered to next CF. I missed it, sorry.

Regards,

--
Masahiko Sawada
NIPPON TELEGRAPH AND TELEPHONE CORPORATION
NTT Open Source Software Center

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#8Tom Lane
tgl@sss.pgh.pa.us
In reply to: Fabien COELHO (#1)
Re: merge psql ef/ev sf/sv handling functions

Fabien COELHO <coelho@cri.ensmp.fr> writes:

Here is an attempt at merging some functions which removes 160 lines of
code.

Pushed with minor adjustments. I thought a couple of variable names
could be better chosen, but mostly, you can't do this sort of thing:

-            psql_error("The server (version %s) does not support editing function source.\n",
+            psql_error("The server (version %s) does not support editing %s.\n",
                        formatPGVersionNumber(pset.sversion, false,
-                                             sverbuf, sizeof(sverbuf)));
+                                             sverbuf, sizeof(sverbuf)),
+                       is_func ? "function source" : "view definitions");

It's too much of a pain in the rear for translators. See
https://www.postgresql.org/docs/devel/static/nls-programmer.html#nls-guidelines
Usually we just use two independent messages, and that's what I did.

regards, tom lane

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#9Fabien COELHO
coelho@cri.ensmp.fr
In reply to: Tom Lane (#8)
Re: merge psql ef/ev sf/sv handling functions

you can't do this sort of thing:

-            psql_error("The server (version %s) does not support editing function source.\n",
+            psql_error("The server (version %s) does not support editing %s.\n",
formatPGVersionNumber(pset.sversion, false,
-                                             sverbuf, sizeof(sverbuf)));
+                                             sverbuf, sizeof(sverbuf)),
+                       is_func ? "function source" : "view definitions");

It's too much of a pain in the rear for translators.

Argh, indeed, I totally forgot about translations. Usually there is a _()
hint for gettext.

See
https://www.postgresql.org/docs/devel/static/nls-programmer.html#nls-guidelines
Usually we just use two independent messages, and that's what I did.

Yep, makes sense. Thanks for the fix.

--
Fabien.

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers