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: [EMAIL PROTECTED]
--- 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);
---------------------------(end of broadcast)--------------------------- TIP 5: don't forget to increase your free space map settings