Folks,
please find attached a patch which implements psql command aliases. They
work the same way as on bash, zsh and others, for example:
#= \alias d \dt+
#= \d
List of relations
Schema | Name | Type | Owner | Description
--------+------+-------+-------+-------------
public | foo | table | bernd |
(1 row)
=# \alias current_query SELECT current_query, NOW() - query_start FROM
pg_stat_activity WHERE current_query NOT LIKE 'IDLE%';
#= \current_query
current_query
| ?column?
-------------------------------------------------------------------------------------------------------+----------
SELECT current_query, NOW() - query_start FROM pg_stat_activity WHERE
current_query NOT LIKE 'IDLE%'; | 00:00:00
(1 row)
#= \unalias d
#= \d
List of relations
Schema | Name | Type | Owner
--------+------+-------+-------
public | foo | table | bernd
(1 row)
I hope i broke nothing and maybe we find this useful for 8.4, documentation
included.
--
Thanks
Bernd
Index: doc/src/sgml/ref/psql-ref.sgml
===================================================================
RCS file: /projects/cvsroot/pgsql/doc/src/sgml/ref/psql-ref.sgml,v
retrieving revision 1.199
diff -c -B -r1.199 psql-ref.sgml
*** doc/src/sgml/ref/psql-ref.sgml 30 Mar 2008 18:10:20 -0000 1.199
--- doc/src/sgml/ref/psql-ref.sgml 1 Apr 2008 14:05:05 -0000
***************
*** 685,690 ****
--- 685,708 ----
</varlistentry>
<varlistentry>
+ <term><literal>\alias <replaceable class="parameter">aliasname</replaceable> <replaceable class="parameter">aliascommand</replaceable></literal></term>
+ <listitem>
+ <para>
+ The <literal>\alias</literal> backslash command allows defining your own backslash commands or an alias for an existing built-in command. The alias is allowed to call a SQL command or any other backslash command or aliases already defined. For example:
+ <programlisting>
+ => <userinput>\alias watch_idle_tx SELECT xact_start, datid, datname, procpid, usesysid FROM pg_stat_activity WHERE current_query LIKE '%IDLE%';</userinput>
+ => <userinput>\watch_idle_tx</userinput>
+ xact_start | datid | datname | procpid | usesysid
+ -------------------------------+-------+---------+---------+----------
+ 2008-03-07 14:59:25.618827+01 | 24576 | db | 28864 | 10
+ (1 row)
+ </programlisting>
+ Calling <command>\alias</command> without an <replaceable class="parameter">aliasname</replaceable> just shows a list of all defined aliases, with an existing <replaceable class="parameter">aliasname</replaceable> its assigned <replaceable class="parameter">aliascommand</replaceable> is shown. You can use the <command>\unalias</command> to remove an alias.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><literal>\cd [ <replaceable>directory</replaceable> ]</literal></term>
<listitem>
<para>
***************
*** 1849,1854 ****
--- 1867,1880 ----
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><literal>\unalias <replaceable class="parameter">aliascmd</replaceable></literal></term>
+ <listitem>
+ <para>
+ Removes the specified alias from the list.
+ </para>
+ </listitem>
+ </varlistentry>
<varlistentry>
<term><literal>\w</literal> {<replaceable class="parameter">filename</replaceable> | <replaceable class="parameter">|command</replaceable>}</term>
Index: src/bin/psql/command.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/bin/psql/command.c,v
retrieving revision 1.186
diff -c -B -r1.186 command.c
*** src/bin/psql/command.c 1 Jan 2008 19:45:55 -0000 1.186
--- src/bin/psql/command.c 1 Apr 2008 14:05:06 -0000
***************
*** 199,204 ****
--- 199,251 ----
backslashResult status = PSQL_CMD_SKIP_LINE;
/*
+ * We want to look for aliases first, since we want them to "override" a
+ * built-in command, so our users are able to define their "own" behavior
+ * on their favourite backslash command.
+ */
+ const char *aliascmd = GetVariable(pset.aliases, cmd);
+
+ if (aliascmd)
+ {
+ /* Save the current alias substitution string.
+ * We do this to prevent infinite recursion into the aliases
+ * list.
+ */
+ const char *substalias = GetVariable(pset.substaliases, cmd);
+
+ if (substalias != NULL)
+ {
+ /* already substituted, nothing more to do */
+ DeleteVariable(pset.substaliases, cmd);
+ }
+ else
+ {
+ char *opt;
+ SetVariable(pset.substaliases, cmd, "1");
+
+ /* save the substituted command to the query buffer but save
+ * additional parameter lists also
+ */
+ resetPQExpBuffer(query_buf);
+ appendPQExpBuffer(query_buf, aliascmd);
+
+ if ((opt = psql_scan_slash_option(scan_state,
+ OT_WHOLE_LINE, NULL, false)))
+ {
+ appendPQExpBuffer(query_buf, " ");
+ appendPQExpBuffer(query_buf, opt);
+ }
+
+ success = true;
+ return (status = PSQL_CMD_ALIAS);
+ }
+
+ }
+
+ /* clear recursive alias list */
+ ClearVariableSpace(pset.substaliases);
+
+ /*
* \a -- toggle field alignment This makes little sense but we keep it
* around.
*/
***************
*** 1037,1042 ****
--- 1084,1143 ----
else if (strcmp(cmd, "?") == 0)
slashUsage(pset.popt.topt.pager);
+ else if (strcmp(cmd, "alias") == 0)
+ {
+ char *aliasname = psql_scan_slash_option(scan_state,
+ OT_NORMAL, NULL, false);
+ char *aliascmd = psql_scan_slash_option(scan_state,
+ OT_WHOLE_LINE, NULL, false);
+
+ /* if no aliasname was specified, then print the whole alias list */
+ if (!aliasname)
+ {
+ PrintVariables(pset.aliases);
+ success = true;
+ }
+ else
+ {
+ /* check wether to assign or to display the alias cmd */
+
+ if (!aliascmd)
+ {
+ const char *cmd = GetVariable(pset.aliases, aliasname);
+ if (cmd)
+ {
+ puts(_(cmd));
+ success = true;
+ }
+ else
+ {
+ psql_error(_("Unknown alias: \"%s\"\n"), aliasname);
+ success = false;
+ }
+ }
+ else
+ {
+ success = SetVariable(pset.aliases, aliasname, aliascmd);
+ }
+
+ }
+
+ }
+ else if (strcmp(cmd, "unalias") == 0)
+ {
+ char *aliasname = psql_scan_slash_option(scan_state,
+ OT_NORMAL, NULL, false);
+ if (aliasname)
+ {
+ success = DeleteVariable(pset.aliases, aliasname);
+ }
+ else
+ {
+ psql_error(_("Unknown alias: \"%s\"\n"), aliasname);
+ success = false;
+ }
+ }
+
#if 0
/*
Index: src/bin/psql/command.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/bin/psql/command.h,v
retrieving revision 1.30
diff -c -B -r1.30 command.h
*** src/bin/psql/command.h 1 Jan 2008 19:45:55 -0000 1.30
--- src/bin/psql/command.h 1 Apr 2008 14:05:06 -0000
***************
*** 19,26 ****
PSQL_CMD_SKIP_LINE, /* keep building query */
PSQL_CMD_TERMINATE, /* quit program */
PSQL_CMD_NEWEDIT, /* query buffer was changed (e.g., via \e) */
! PSQL_CMD_ERROR /* the execution of the backslash command
* resulted in an error */
} backslashResult;
--- 19,27 ----
PSQL_CMD_SKIP_LINE, /* keep building query */
PSQL_CMD_TERMINATE, /* quit program */
PSQL_CMD_NEWEDIT, /* query buffer was changed (e.g., via \e) */
! PSQL_CMD_ERROR, /* the execution of the backslash command
* resulted in an error */
+ PSQL_CMD_ALIAS /* query buffer was changed by command alias */
} backslashResult;
Index: src/bin/psql/mainloop.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/bin/psql/mainloop.c,v
retrieving revision 1.87
diff -c -B -r1.87 mainloop.c
*** src/bin/psql/mainloop.c 1 Jan 2008 19:45:56 -0000 1.87
--- src/bin/psql/mainloop.c 1 Apr 2008 14:05:06 -0000
***************
*** 266,273 ****
success = slashCmdStatus != PSQL_CMD_ERROR;
! if ((slashCmdStatus == PSQL_CMD_SEND || slashCmdStatus == PSQL_CMD_NEWEDIT) &&
! query_buf->len == 0)
{
/* copy previous buffer to current for handling */
appendPQExpBufferStr(query_buf, previous_buf->data);
--- 266,273 ----
success = slashCmdStatus != PSQL_CMD_ERROR;
! if ((slashCmdStatus == PSQL_CMD_SEND || slashCmdStatus == PSQL_CMD_NEWEDIT
! || slashCmdStatus == PSQL_CMD_ALIAS) && query_buf->len == 0)
{
/* copy previous buffer to current for handling */
appendPQExpBufferStr(query_buf, previous_buf->data);
***************
*** 284,290 ****
/* flush any paren nesting info after forced send */
psql_scan_reset(scan_state);
}
! else if (slashCmdStatus == PSQL_CMD_NEWEDIT)
{
/* rescan query_buf as new input */
psql_scan_finish(scan_state);
--- 284,291 ----
/* flush any paren nesting info after forced send */
psql_scan_reset(scan_state);
}
! else if ((slashCmdStatus == PSQL_CMD_NEWEDIT)
! || (slashCmdStatus == PSQL_CMD_ALIAS))
{
/* rescan query_buf as new input */
psql_scan_finish(scan_state);
***************
*** 294,300 ****
/* reset parsing state since we are rescanning whole line */
psql_scan_reset(scan_state);
psql_scan_setup(scan_state, line, strlen(line));
! line_saved_in_history = false;
prompt_status = PROMPT_READY;
}
else if (slashCmdStatus == PSQL_CMD_TERMINATE)
--- 295,304 ----
/* reset parsing state since we are rescanning whole line */
psql_scan_reset(scan_state);
psql_scan_setup(scan_state, line, strlen(line));
! if (slashCmdStatus == PSQL_CMD_NEWEDIT)
! line_saved_in_history = false;
! else
! line_saved_in_history = true;
prompt_status = PROMPT_READY;
}
else if (slashCmdStatus == PSQL_CMD_TERMINATE)
Index: src/bin/psql/settings.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/bin/psql/settings.h,v
retrieving revision 1.33
diff -c -B -r1.33 settings.h
*** src/bin/psql/settings.h 1 Jan 2008 19:45:56 -0000 1.33
--- src/bin/psql/settings.h 1 Apr 2008 14:05:06 -0000
***************
*** 85,90 ****
--- 85,92 ----
FILE *logfile; /* session log file handle */
VariableSpace vars; /* "shell variable" repository */
+ VariableSpace aliases; /* "shell aliases" repository */
+ VariableSpace substaliases; /* which aliases were substituted already */
/*
* The remaining fields are set by assign hooks associated with entries in
Index: src/bin/psql/startup.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/bin/psql/startup.c,v
retrieving revision 1.146
diff -c -B -r1.146 startup.c
*** src/bin/psql/startup.c 1 Jan 2008 19:45:56 -0000 1.146
--- src/bin/psql/startup.c 1 Apr 2008 14:05:06 -0000
***************
*** 85,90 ****
--- 85,91 ----
static void process_psqlrc_file(char *filename);
static void showVersion(void);
static void EstablishVariableSpace(void);
+ static void EstablishAliasSpace(void);
#ifdef USE_SSL
static void printSSLInfo(void);
***************
*** 158,163 ****
--- 159,168 ----
#endif
EstablishVariableSpace();
+ /* create associative array for alias cmd values
+ we do this here for now, but i'm not sure how this
+ will play with values coming from a .psqlrc */
+ EstablishAliasSpace();
SetVariable(pset.vars, "VERSION", PG_VERSION_STR);
***************
*** 868,873 ****
--- 873,884 ----
PQsetErrorVerbosity(pset.db, pset.verbosity);
}
+ static void
+ EstablishAliasSpace(void)
+ {
+ pset.aliases = CreateVariableSpace();
+ pset.substaliases = CreateVariableSpace();
+ }
static void
EstablishVariableSpace(void)
Index: src/bin/psql/variables.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/bin/psql/variables.c,v
retrieving revision 1.28
diff -c -B -r1.28 variables.c
*** src/bin/psql/variables.c 1 Jan 2008 19:45:56 -0000 1.28
--- src/bin/psql/variables.c 1 Apr 2008 14:05:06 -0000
***************
*** 241,243 ****
--- 241,264 ----
return true;
}
+
+ int
+ ClearVariableSpace(VariableSpace space)
+ {
+ int count = 0;
+
+ if (!space)
+ return -1;
+
+ /* loop through the list, as long as the root element
+ * contains any remaining pointer to the next element in the
+ * list
+ */
+ while(space->next)
+ {
+ DeleteVariable(space, space->next->name);
+ count++;
+ }
+
+ return count;
+ }
Index: src/bin/psql/variables.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/bin/psql/variables.h,v
retrieving revision 1.22
diff -c -B -r1.22 variables.h
*** src/bin/psql/variables.h 1 Jan 2008 19:45:56 -0000 1.22
--- src/bin/psql/variables.h 1 Apr 2008 14:05:06 -0000
***************
*** 56,60 ****
--- 56,61 ----
bool SetVariableAssignHook(VariableSpace space, const char *name, VariableAssignHook hook);
bool SetVariableBool(VariableSpace space, const char *name);
bool DeleteVariable(VariableSpace space, const char *name);
+ int ClearVariableSpace(VariableSpace space);
#endif /* VARIABLES_H */
--
Sent via pgsql-patches mailing list (pgsql-patches@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-patches