@@ -148,11 +148,11 @@ static void save_query_text_state(PsqlScanState scan_state, ConditionalStack cst
148148 PQExpBuffer query_buf );
149149static void discard_query_text (PsqlScanState scan_state , ConditionalStack cstack ,
150150 PQExpBuffer query_buf );
151- static void copy_previous_query (PQExpBuffer query_buf , PQExpBuffer previous_buf );
151+ static bool copy_previous_query (PQExpBuffer query_buf , PQExpBuffer previous_buf );
152152static bool do_connect (enum trivalue reuse_previous_specification ,
153153 char * dbname , char * user , char * host , char * port );
154154static bool do_edit (const char * filename_arg , PQExpBuffer query_buf ,
155- int lineno , bool * edited );
155+ int lineno , bool discard_on_quit , bool * edited );
156156static bool do_shell (const char * command );
157157static bool do_watch (PQExpBuffer query_buf , double sleep );
158158static bool lookup_object_oid (EditableObjectType obj_type , const char * desc ,
@@ -418,7 +418,7 @@ exec_command(const char *cmd,
418418 * the individual command subroutines.
419419 */
420420 if (status == PSQL_CMD_SEND )
421- copy_previous_query (query_buf , previous_buf );
421+ ( void ) copy_previous_query (query_buf , previous_buf );
422422
423423 return status ;
424424}
@@ -1004,14 +1004,27 @@ exec_command_edit(PsqlScanState scan_state, bool active_branch,
10041004 }
10051005 if (status != PSQL_CMD_ERROR )
10061006 {
1007+ bool discard_on_quit ;
1008+
10071009 expand_tilde (& fname );
10081010 if (fname )
1011+ {
10091012 canonicalize_path (fname );
1013+ /* Always clear buffer if the file isn't modified */
1014+ discard_on_quit = true;
1015+ }
1016+ else
1017+ {
1018+ /*
1019+ * If query_buf is empty, recall previous query for
1020+ * editing. But in that case, the query buffer should be
1021+ * emptied if editing doesn't modify the file.
1022+ */
1023+ discard_on_quit = copy_previous_query (query_buf ,
1024+ previous_buf );
1025+ }
10101026
1011- /* If query_buf is empty, recall previous query for editing */
1012- copy_previous_query (query_buf , previous_buf );
1013-
1014- if (do_edit (fname , query_buf , lineno , NULL ))
1027+ if (do_edit (fname , query_buf , lineno , discard_on_quit , NULL ))
10151028 status = PSQL_CMD_NEWEDIT ;
10161029 else
10171030 status = PSQL_CMD_ERROR ;
@@ -1134,7 +1147,7 @@ exec_command_ef_ev(PsqlScanState scan_state, bool active_branch,
11341147 {
11351148 bool edited = false;
11361149
1137- if (!do_edit (NULL , query_buf , lineno , & edited ))
1150+ if (!do_edit (NULL , query_buf , lineno , true, & edited ))
11381151 status = PSQL_CMD_ERROR ;
11391152 else if (!edited )
11401153 puts (_ ("No changes" ));
@@ -2637,7 +2650,7 @@ exec_command_watch(PsqlScanState scan_state, bool active_branch,
26372650 }
26382651
26392652 /* If query_buf is empty, recall and execute previous query */
2640- copy_previous_query (query_buf , previous_buf );
2653+ ( void ) copy_previous_query (query_buf , previous_buf );
26412654
26422655 success = do_watch (query_buf , sleep );
26432656
@@ -2961,12 +2974,19 @@ discard_query_text(PsqlScanState scan_state, ConditionalStack cstack,
29612974 * This is used by various slash commands for which re-execution of a
29622975 * previous query is a common usage. For convenience, we allow the
29632976 * case of query_buf == NULL (and do nothing).
2977+ *
2978+ * Returns "true" if the previous query was copied into the query
2979+ * buffer, else "false".
29642980 */
2965- static void
2981+ static bool
29662982copy_previous_query (PQExpBuffer query_buf , PQExpBuffer previous_buf )
29672983{
29682984 if (query_buf && query_buf -> len == 0 )
2985+ {
29692986 appendPQExpBufferStr (query_buf , previous_buf -> data );
2987+ return true;
2988+ }
2989+ return false;
29702990}
29712991
29722992/*
@@ -3647,10 +3667,11 @@ UnsyncVariables(void)
36473667
36483668
36493669/*
3650- * do_edit -- handler for \e
3670+ * helper for do_edit(): actually invoke the editor
36513671 *
3652- * If you do not specify a filename, the current query buffer will be copied
3653- * into a temporary one.
3672+ * Returns true on success, false if we failed to invoke the editor or
3673+ * it returned nonzero status. (An error message is printed for failed-
3674+ * to-invoke cases, but not if the editor returns nonzero status.)
36543675 */
36553676static bool
36563677editFile (const char * fname , int lineno )
@@ -3719,10 +3740,23 @@ editFile(const char *fname, int lineno)
37193740}
37203741
37213742
3722- /* call this one */
3743+ /*
3744+ * do_edit -- handler for \e
3745+ *
3746+ * If you do not specify a filename, the current query buffer will be copied
3747+ * into a temporary file.
3748+ *
3749+ * After this function is done, the resulting file will be copied back into the
3750+ * query buffer. As an exception to this, the query buffer will be emptied
3751+ * if the file was not modified (or the editor failed) and the caller passes
3752+ * "discard_on_quit" = true.
3753+ *
3754+ * If "edited" isn't NULL, *edited will be set to true if the query buffer
3755+ * is successfully replaced.
3756+ */
37233757static bool
37243758do_edit (const char * filename_arg , PQExpBuffer query_buf ,
3725- int lineno , bool * edited )
3759+ int lineno , bool discard_on_quit , bool * edited )
37263760{
37273761 char fnametmp [MAXPGPATH ];
37283762 FILE * stream = NULL ;
@@ -3870,6 +3904,7 @@ do_edit(const char *filename_arg, PQExpBuffer query_buf,
38703904 {
38713905 pg_log_error ("%s: %m" , fname );
38723906 error = true;
3907+ resetPQExpBuffer (query_buf );
38733908 }
38743909 else if (edited )
38753910 {
@@ -3879,6 +3914,15 @@ do_edit(const char *filename_arg, PQExpBuffer query_buf,
38793914 fclose (stream );
38803915 }
38813916 }
3917+ else
3918+ {
3919+ /*
3920+ * If the file was not modified, and the caller requested it, discard
3921+ * the query buffer.
3922+ */
3923+ if (discard_on_quit )
3924+ resetPQExpBuffer (query_buf );
3925+ }
38823926
38833927 /* remove temp file */
38843928 if (!filename_arg )
0 commit comments