From ee87e03e479fd920d6aa697e95617c52abc664e2 Mon Sep 17 00:00:00 2001 From: chenxiaobin <1025221611@qq.com> Date: Fri, 19 Mar 2021 15:39:15 +0800 Subject: [PATCH] add HISTSIZE for readline to limit the number of cached commands --- doc/src/sgml/ref/psql-ref.sgmlin | 16 +++++++++++ src/bin/psql/command.cpp | 12 ++++++++ src/bin/psql/input.cpp | 39 ++++++++++++++++++++++++++ src/bin/psql/input.h | 4 ++- src/bin/psql/mainloop.cpp | 5 ++++ src/bin/psql/startup.cpp | 1 + src/bin/psql/tab-complete.cpp | 4 +++ src/test/regress/expected/readline.out | 8 ++++++ src/test/regress/sql/readline.sql | 8 ++++++ 9 files changed, 96 insertions(+), 1 deletion(-) diff --git a/doc/src/sgml/ref/psql-ref.sgmlin b/doc/src/sgml/ref/psql-ref.sgmlin index bfbc6b136..8e387204e 100644 --- a/doc/src/sgml/ref/psql-ref.sgmlin +++ b/doc/src/sgml/ref/psql-ref.sgmlin @@ -2833,6 +2833,22 @@ bar + + HISTSIZE + + + The number of commands to store in the command history. The + default value is 500. + + + + This feature was shamelessly plagiarized from + Bash. + + + + + HOST diff --git a/src/bin/psql/command.cpp b/src/bin/psql/command.cpp index 56a5413a8..f0587febd 100644 --- a/src/bin/psql/command.cpp +++ b/src/bin/psql/command.cpp @@ -1051,6 +1051,12 @@ static backslashResult exec_command(const char* cmd, PsqlScanState scan_state, P success = false; } +#ifdef USE_READLINE + if (useReadline && pset.cur_cmd_interactive) { + setHistSize(opt0, newval, false); + } +#endif + free(newval); newval = NULL; if (temp_opt != NULL) @@ -1255,6 +1261,12 @@ static backslashResult exec_command(const char* cmd, PsqlScanState scan_state, P success = false; } +#ifdef USE_READLINE + if (useReadline && pset.cur_cmd_interactive) { + setHistSize(opt, NULL, true); + } +#endif + if (NULL != opt) { free(opt); opt = NULL; diff --git a/src/bin/psql/input.cpp b/src/bin/psql/input.cpp index aac0ab555..cc48a2559 100644 --- a/src/bin/psql/input.cpp +++ b/src/bin/psql/input.cpp @@ -248,6 +248,45 @@ bool SensitiveStrCheck(const char* target) } } +void setHistSize(const char* targetName, const char* targetValue, bool setToDefault) +{ +#ifndef ENABLE_LLT + char* end = NULL; + long int result; +#define MAXHISTSIZE 500 +#define DEFHISTSIZE 32 + if (targetName == NULL) { + return; + } + if (strcmp(targetName, "HISTSIZE") == 0) { + if (!setToDefault) { + if (targetValue == NULL || strlen(targetValue) == 0) { + fprintf(stderr, "warning:\"HISTSIZE\" is not changed,because its value can not be null\n"); + return; + } else { + errno = 0; + result = strtol(targetValue, &end, 0); + if ((errno == ERANGE && (result == LONG_MAX || result == LONG_MIN)) || (errno != 0 && result == 0)) { + fprintf(stderr, "warning:\"HISTSIZE\" is not changed,because its value overflows\n"); + return; + } + if (*end || result < 0) { + fprintf(stderr, "warning:\"HISTSIZE\" is not changed,because its value must be positive integer\n"); + return; + } + } + if (result > MAXHISTSIZE) { + fprintf(stderr, "warning:\"HISTSIZE\" is set to 500,because its value can not be greater than 500\n"); + result = MAXHISTSIZE; + } + } else { + result = DEFHISTSIZE; + } + stifle_history((int)result); + } +#endif +} + /* * Put any startup stuff related to input in here. It's good to maintain * abstraction this way. diff --git a/src/bin/psql/input.h b/src/bin/psql/input.h index b184f0217..5e871518f 100644 --- a/src/bin/psql/input.h +++ b/src/bin/psql/input.h @@ -8,7 +8,6 @@ #ifndef INPUT_H #define INPUT_H -#ifdef HAVE_LIBREADLINE /* * If some other file needs to have access to readline/history, include this * file and save yourself all this work. @@ -17,6 +16,8 @@ */ #define USE_READLINE 1 +#ifdef HAVE_LIBREADLINE + #if defined(HAVE_READLINE_READLINE_H) #include #include @@ -36,6 +37,7 @@ char* gets_fromFile(FILE* source); void pg_append_history(const char* s, PQExpBuffer history_buf); void pg_send_history(PQExpBuffer history_buf); +void setHistSize(const char* targetName, const char* targetValue, bool setToDefault); extern bool useReadline; extern bool SensitiveStrCheck(const char* target); diff --git a/src/bin/psql/mainloop.cpp b/src/bin/psql/mainloop.cpp index 1931e7c84..ecd7cc09b 100644 --- a/src/bin/psql/mainloop.cpp +++ b/src/bin/psql/mainloop.cpp @@ -148,6 +148,11 @@ int MainLoop(FILE* source, char* querystring) } pset.lineno = 0; + if (pset.cur_cmd_interactive) { + const char* val = GetVariable(pset.vars, "HISTSIZE"); + setHistSize("HISTSIZE", val, val == NULL); + } + /* Create working state */ scan_state = psql_scan_create(); diff --git a/src/bin/psql/startup.cpp b/src/bin/psql/startup.cpp index 288140366..f20c593c4 100755 --- a/src/bin/psql/startup.cpp +++ b/src/bin/psql/startup.cpp @@ -781,6 +781,7 @@ static void parse_psql_options(int argc, char* const argv[], struct adhoc_opts* fprintf(stderr, _("%s: could not set variable \"%s\"\n"), pset.progname, value); exit(EXIT_FAILURE); } + setHistSize(value, equal_loc + 1, false); } free(value); diff --git a/src/bin/psql/tab-complete.cpp b/src/bin/psql/tab-complete.cpp index 5942fdd98..cf854c436 100644 --- a/src/bin/psql/tab-complete.cpp +++ b/src/bin/psql/tab-complete.cpp @@ -754,8 +754,12 @@ void initialize_readline(void) { rl_readline_name = (char *)pset.progname; +#ifdef HAVE_READLINE_READLINE_H /* PsqlCompletion is deleted because it's too complex and not be used at all. */ rl_attempted_completion_function = PsqlCompletion; +#else + rl_attempted_completion_function = NULL; +#endif rl_basic_word_break_characters = WORD_BREAKS; diff --git a/src/test/regress/expected/readline.out b/src/test/regress/expected/readline.out index 048f3b4b6..a2d33fb25 100644 --- a/src/test/regress/expected/readline.out +++ b/src/test/regress/expected/readline.out @@ -7,3 +7,11 @@ select * from 数据库; 1 (1 row) +\set HISTSIZE -1 +\set HISTSIZE 30.5 +\set HISTSIZE 0 +\set HISTSIZE 6 +\set HISTSIZE 500 +\set HISTSIZE 600 +\set HISTSIZE 66666666666666666666666600 +\set HISTSIZE -666666666666666666666666666 diff --git a/src/test/regress/sql/readline.sql b/src/test/regress/sql/readline.sql index de975aab3..0e81f8368 100644 --- a/src/test/regress/sql/readline.sql +++ b/src/test/regress/sql/readline.sql @@ -2,3 +2,11 @@ create table 数据库(f int); insert into 数据库 values (1); select * from 数据库; +\set HISTSIZE -1 +\set HISTSIZE 30.5 +\set HISTSIZE 0 +\set HISTSIZE 6 +\set HISTSIZE 500 +\set HISTSIZE 600 +\set HISTSIZE 66666666666666666666666600 +\set HISTSIZE -666666666666666666666666666