Skip site navigation (1) Skip section navigation (2)

Peripheral Links

Header And Logo

PostgreSQL
| The world's most advanced open source database.

Site Navigation

Search archives
  Advanced Search

TODO item -- Improve psql's handling of multi-line queries



Hello All, 

I'm proposing the small patch for the TODO item -- Improve psql's handling 
of multi-line queries. With this patch the multi-line queries are saved 
by readline as whole and not line by line.

This is my first patch for Postgres but it seems to work and to not break 
anything.

I'm waiting for review, comments, objections, etc...

With Best Regards, 

	Sergey 

*****************************************************
Sergey E. Koposov
Max Planck Institute for Astronomy
Web: http://lnfm1.sai.msu.ru/~math 
E-mail: math(at)sai(dot)msu(dot)ru

--- pgsql_orig/src/bin/psql/input.c	2005-10-15 04:49:40.000000000 +0200
+++ pgsql/src/bin/psql/input.c	2005-10-30 02:30:05.000000000 +0100
@@ -90,17 +90,57 @@
 #ifdef USE_READLINE
 	char	   *s;
 
-	static char *prev_hist = NULL;
-
 	if (useReadline)
 		/* On some platforms, readline is declared as readline(char *) */
 		s = readline((char *) prompt);
 	else
 		s = gets_basic(prompt);
 
-	if (useHistory && s && s[0])
+	return s;
+#else
+	return gets_basic(prompt);
+#endif
+}
+
+/* Put the line in the history buffer and also add the trailing \n */
+char *pgadd_history(char *s, char *history_buf, int *cur_len)
+{
+#ifdef USE_READLINE
+
+	int slen;
+	char *history_buf1;
+	if (useReadline && useHistory && s && s[0])
 	{
+		slen = strlen(s);
+		history_buf1 = history_buf;
+		history_buf1 = realloc(history_buf1, (*cur_len + slen + 2) * sizeof(char));
+		strcpy(history_buf1 + *cur_len, s);
+		*cur_len += (slen + 1);
+		history_buf1[*cur_len - 1] = '\n';
+		history_buf1[*cur_len] = 0;
+	}	
+	return history_buf1;
+#endif	
+}
+
+/* Feed the contents of the history buffer to readline */
+void pgflush_history(char **history_buf, int *cur_len)
+{
+
+#ifdef USE_READLINE
+	
+	char *s;
+	static char *prev_hist;
+	
+	if (useReadline && useHistory && ((*cur_len) > 0))
+	{
+
 		enum histcontrol HC;
+		
+		s = *history_buf;
+		prev_hist = NULL;
+			
+		s[(*cur_len) - 1] = 0;
 
 		HC = GetHistControlConfig();
 
@@ -115,14 +155,14 @@
 			prev_hist = pg_strdup(s);
 			add_history(s);
 		}
+		
+		free(s);
+		*history_buf = 0;
+		*cur_len = 0;
 	}
-
-	return s;
-#else
-	return gets_basic(prompt);
 #endif
-}
 
+}
 
 
 /*
--- pgsql_orig/src/bin/psql/input.h	2005-01-01 06:43:08.000000000 +0100
+++ pgsql/src/bin/psql/input.h	2005-10-30 02:50:08.000000000 +0200
@@ -39,4 +39,7 @@
 void		initializeInput(int flags);
 bool		saveHistory(char *fname);
 
+char *pgadd_history(char *s, char *history_buf, int *cur_len);
+void pgflush_history(char **history_buf, int *cur_len);
+
 #endif   /* INPUT_H */
--- pgsql_orig/src/bin/psql/mainloop.c	2005-10-15 04:49:40.000000000 +0200
+++ pgsql/src/bin/psql/mainloop.c	2005-10-30 02:32:19.000000000 +0100
@@ -38,6 +38,8 @@
 	PQExpBuffer previous_buf;	/* if there isn't anything in the new buffer
 								 * yet, use this one for \e, etc. */
 	char	   *line;			/* current line of input */
+	char		*history_buf = 0;
+	int		history_buf_len = 0;
 	int			added_nl_pos;
 	bool		success;
 	volatile int successResult = EXIT_SUCCESS;
@@ -212,7 +214,13 @@
 		 */
 		psql_scan_setup(scan_state, line, strlen(line));
 		success = true;
-
+		
+		if (pset.cur_cmd_interactive)
+		{
+			/* Put current line in the history buffer */
+			history_buf = pgadd_history(line, history_buf, &history_buf_len);
+		}
+		
 		while (success || !die_on_error)
 		{
 			PsqlScanResult scan_result;
@@ -229,6 +237,7 @@
 				(scan_result == PSCAN_EOL &&
 				 GetVariableBool(pset.vars, "SINGLELINE")))
 			{
+				
 				/* execute query */
 				success = SendQuery(query_buf->data);
 				slashCmdStatus = success ? CMD_SEND : CMD_ERROR;
@@ -249,10 +258,13 @@
 				 * newline again.  This avoids any change to query_buf when a
 				 * line contains only a backslash command.
 				 */
+
+
 				if (query_buf->len == added_nl_pos)
 					query_buf->data[--query_buf->len] = '\0';
 				added_nl_pos = -1;
 
+
 				slashCmdStatus = HandleSlashCmds(scan_state,
 												 query_buf->len > 0 ?
 												 query_buf : previous_buf);
@@ -266,6 +278,7 @@
 					appendPQExpBufferStr(query_buf, previous_buf->data);
 				}
 
+
 				if (slashCmdStatus == CMD_SEND)
 				{
 					success = SendQuery(query_buf->data);
@@ -287,6 +300,14 @@
 				scan_result == PSCAN_EOL)
 				break;
 		}
+		
+		if (pset.cur_cmd_interactive && (prompt_status != PROMPT_CONTINUE))
+		{
+			/* Pass all the contents of history_buf to readline 
+			   and free the history buffer.
+			 */
+			pgflush_history(&history_buf, &history_buf_len);
+		}
 
 		psql_scan_finish(scan_state);
 		free(line);


Home | Main Index | Thread Index

Privacy Policy | PostgreSQL Archives hosted by Command Prompt, Inc. | Designed by tinysofa
Copyright © 1996 – 2008 PostgreSQL Global Development Group