Hello,
On Thu, 17 Aug 2017, Pavel Stehule wrote:
> 2017-08-17 9:23 GMT+02:00 Vesa-Matti J Kari <vmk...@cc.helsinki.fi>:
>
> Bash has HISTIGNORE feature that allows you to exclude certain commands
> from the command history (e.g. shutdown, reboot, rm *).
>
> Would it make any sense to add such a feature to psql (e.g. to ignore
> DROP, DELETE commands)?
>
>
> It is not bad idea.
A quick patch is attached. Not sure about the quality, hacked this
together in about four hours, trying to figure out how to do it correctly
the PostgreSQL way.
Based on a few tests, the patch seems to work.
I do not know how the Bash implementation works, but I chose to disallow
forms such as:
:
:a
a:
a::b
So specifying empty strings seems like a syntax error to me. But I do
not know how to report failures for those, the current patch disallows
them and HISTIGNORE simply does not work with invalid syntax.
Regards,
vmk
--
************************************************************************
Tietotekniikkakeskus / Helsingin yliopisto
IT department / University of Helsinki
************************************************************************
diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c
index b3dbb5946e..1a28a21f26 100644
*** a/src/bin/psql/help.c
--- b/src/bin/psql/help.c
***************
*** 357,362 **** helpVariables(unsigned short int pager)
--- 357,363 ----
" (default:
0=unlimited)\n"));
fprintf(output, _(" HISTCONTROL controls command history
[ignorespace, ignoredups, ignoreboth]\n"));
fprintf(output, _(" HISTFILE file name used to store the
command history\n"));
+ fprintf(output, _(" HISTIGNORE controls command history,
ignores colon separated commands\n"));
fprintf(output, _(" HISTSIZE max number of commands to store
in the command history\n"));
fprintf(output, _(" HOST the currently connected
database server host\n"));
fprintf(output, _(" IGNOREEOF number of EOFs needed to
terminate an interactive session\n"));
diff --git a/src/bin/psql/index 62f5f77383..ffaee397cf 100644
*** a/src/bin/psql/input.c
--- b/src/bin/psql/input.c
***************
*** 147,152 **** pg_send_history(PQExpBuffer history_buf)
--- 147,162 ----
if (useHistory && s[0])
{
+ if (pset.histignore)
+ {
+ for (i = 0; i < histignore.nstr; i++) {
+ if (pg_strncasecmp(s, histignore.str[i],
strlen(histignore.str[i])) == 0) {
+ resetPQExpBuffer(history_buf);
+ return;
+ }
+ }
+ }
+
if (((pset.histcontrol & hctl_ignorespace) &&
s[0] == ' ') ||
((pset.histcontrol & hctl_ignoredups) &&
diff --git a/src/bin/psql/sindex b78f151acd..9c436eeb88 100644
*** a/src/bin/psql/settings.h
--- b/src/bin/psql/settings.h
***************
*** 77,82 **** enum trivalue
--- 77,89 ----
TRI_YES
};
+ typedef struct HistIgnore
+ {
+ char **str;
+ int nstr;
+
+ } HistIgnore;
+
typedef struct _psqlSettings
{
PGconn *db; /* connection to backend */
***************
*** 133,138 **** typedef struct _psqlSettings
--- 140,146 ----
PSQL_ERROR_ROLLBACK on_error_rollback;
PSQL_COMP_CASE comp_case;
HistControl histcontrol;
+ char *histignore;
const char *prompt1;
const char *prompt2;
const char *prompt3;
***************
*** 141,146 **** typedef struct _psqlSettings
--- 149,155 ----
} PsqlSettings;
extern PsqlSettings pset;
+ extern HistIgnore histignore;
#ifndef EXIT_SUCCESS
diff --git a/src/bin/psql/starindex 7f767976a5..b14ce2699e 100644
*** a/src/bin/psql/startup.c
--- b/src/bin/psql/startup.c
***************
*** 31,36 ****
--- 31,37 ----
* Global psql options
*/
PsqlSettings pset;
+ HistIgnore histignore;
#ifndef WIN32
#define SYSPSQLRC "psqlrc"
***************
*** 667,672 **** parse_psql_options(int argc, char *argv[], struct adhoc_opts
*options)
--- 668,726 ----
}
+ static bool
+ parse_histignore(const char *val)
+ {
+ const char *p;
+ char *tokbuf;
+ char *tok;
+ int i;
+ int len;
+ int ncolons;
+
+ len = strlen(val);
+
+ if (len == 0) {
+ histignore.str = NULL;
+ histignore.nstr = 0;
+ return true;
+ }
+
+ /* Validate syntax first. */
+ if (val[0] == ':' || val[len-1] == ':')
+ return false;
+
+ i = 0;
+ while (val[i] && val[i+1]) {
+ if (val[i] == ':' && val[i+1] == ':')
+ return false;
+ i++;
+ }
+
+ p = val;
+ ncolons = 0;
+ while (*p++)
+ if (*p == ':')
+ ncolons++;
+
+ histignore.nstr = ncolons + 1;
+ histignore.str = pg_malloc(histignore.nstr * sizeof(char *));
+
+
+ i = 0;
+ tokbuf = pg_strdup(val);
+
+ tok = strtok(tokbuf, ":");
+ while (tok != NULL) {
+ histignore.str[i] = pg_strdup(tok);
+ tok = strtok(NULL, ":");
+ i++;
+ }
+
+ return true;
+ }
+
+
/*
* Append a new item to the end of the SimpleActionList.
* Note that "val" is copied if it's not NULL.
***************
*** 1024,1029 **** histcontrol_hook(const char *newval)
--- 1078,1101 ----
return true;
}
+ static char *
+ histignore_substitute_hook(char *newval)
+ {
+ if (newval == NULL)
+ newval = pg_strdup("");
+ return newval;
+ }
+
+ static bool
+ histignore_hook(const char *newval)
+ {
+ Assert(newval != NULL);
+ if (parse_histignore(newval) == false)
+ return false;
+ pset.histignore = pg_strdup(newval);
+ return true;
+ }
+
static bool
prompt1_hook(const char *newval)
{
***************
*** 1151,1156 **** EstablishVariableSpace(void)
--- 1223,1231 ----
SetVariableHooks(pset.vars, "HISTCONTROL",
histcontrol_substitute_hook,
histcontrol_hook);
+ SetVariableHooks(pset.vars, "HISTIGNORE",
+ histignore_substitute_hook,
+ histignore_hook);
SetVariableHooks(pset.vars, "PROMPT1",
NULL,
prompt1_hook);
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers