This patch adds two very simple psql commands: \quit_if and \quit_unless.

Each takes an optional string parameter and evaluates it for truthiness via
ParseVariableBool().

If a true-ish value is passed to \quit_if, psql will behave as if the user
had input \quit.

\quit_unless will do nothing if the value given was true-ish, and will
\quit in any other circumstances.

Examples below show the behavior:

$ psql postgres
psql (10devel)
Type "help" for help.

# \quit_if
# \quit_unless
$ psql postgres
psql (10devel)
Type "help" for help.

# \quit_if f
# \quit_if 0
# \quit_if false
# \quit_if 2
unrecognized value "2" for "\quit_if"; assuming "on"
$ psql postgres
psql (10devel)
Type "help" for help.

# \quit_unless 2
unrecognized value "2" for "\quit_unless"; assuming "on"
# \quit_unless f
$


The need for this patch has arisen from several scripts I've written
recently that were about 97% psql and 3% bash or similar glue language. In
those scripts, there's often a test that says "there is no work to do here,
and that is not an error". I could engineer an optional SELECT 1/0 to
generate an error, but then I have to make the bash script determine
whether that was an error-error or a no-everything-is-ok-error. I also
don't want to wrap hundreds of lines of SQL inside python docstrings (thus
losing syntax highlighting, etc) just to handle one if/then.

Many thanks to Pavel Stehule for brainstorming this one with me.
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
index 2410bee..a9b0732 100644
--- a/doc/src/sgml/ref/psql-ref.sgml
+++ b/doc/src/sgml/ref/psql-ref.sgml
@@ -2616,6 +2616,23 @@ lo_import 152801
         </listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><literal>\quit_if <replaceable 
class="parameter">string</replaceable> </literal></term>
+        <listitem>
+        <para>
+        Quits the <application>psql</application> program if the string 
evaluates to true.
+        </para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><literal>\quit_unless <replaceable 
class="parameter">string</replaceable> </literal></term>
+        <listitem>
+        <para>
+        Quits the <application>psql</application> program unless the string 
evaluates to true.
+        </para>
+        </listitem>
+      </varlistentry>
 
       <varlistentry>
         <term><literal>\qecho <replaceable 
class="parameter">text</replaceable> [ ... ] </literal></term>
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index a9a2fdb..7b46fbd 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -1251,6 +1251,29 @@ exec_command(const char *cmd,
        else if (strcmp(cmd, "q") == 0 || strcmp(cmd, "quit") == 0)
                status = PSQL_CMD_TERMINATE;
 
+       /* \quit_if */
+       else if (strcmp(cmd, "quit_if") == 0)
+       {
+               char       *opt = psql_scan_slash_option(scan_state,
+                                                                               
                 OT_NORMAL, NULL, false);
+
+               if (opt)
+                       if (ParseVariableBool(opt, "\\quit_if"))
+                               status = PSQL_CMD_TERMINATE;
+       }
+
+       /* \quit_unless */
+       else if (strcmp(cmd, "quit_unless") == 0)
+       {
+               char       *opt = psql_scan_slash_option(scan_state,
+                                                                               
                 OT_NORMAL, NULL, false);
+
+               if (!opt)
+                       status = PSQL_CMD_TERMINATE;
+               else if (! ParseVariableBool(opt, "\\quit_unless"))
+                       status = PSQL_CMD_TERMINATE;
+       }
+
        /* reset(clear) the buffer */
        else if (strcmp(cmd, "r") == 0 || strcmp(cmd, "reset") == 0)
        {
diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c
index a69c4dd..db29650 100644
--- a/src/bin/psql/help.c
+++ b/src/bin/psql/help.c
@@ -177,6 +177,8 @@ slashUsage(unsigned short int pager)
        fprintf(output, _("  \\gexec                 execute query, then 
execute each value in its result\n"));
        fprintf(output, _("  \\gset [PREFIX]         execute query and store 
results in psql variables\n"));
        fprintf(output, _("  \\q                     quit psql\n"));
+       fprintf(output, _("  \\quit_if [STRING]      quit psql if STRING 
evaluates to true\n"));
+       fprintf(output, _("  \\quit_unless [STRING]  quit psql if STRING does 
not evaluate to true\n"));
        fprintf(output, _("  \\crosstabview [COLUMNS] execute query and display 
results in crosstab\n"));
        fprintf(output, _("  \\watch [SEC]           execute query every SEC 
seconds\n"));
        fprintf(output, "\n");
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to