Hello Pavel,
I agree that the existing "SetVariableBool" function is a misnommer, it
should be "SetVariableOn" given what it does, and it is not what we
need.
switching default setting from ON to TRUE requires wider discussion -
Yep.
in this moment I like to have special function "SetVariableON".
I'm fine with this, but this make it a change totally unrelated to this
patch as it would not use the function... Moreover, this function would
not use an hypothetical "set var bool" function because of the debatable
on/off vs true/false change.
Also, a "set var bool" function would be called only twice, which is not
very beneficial for a oneliner, so I left it out.
I agree that there is some common structure, but ISTM that the
AcceptResult function is called in a variety of situation where variables
are not to be set (eg "internal" queries, not user provided queries), so I
thought it best to keep the two apart.
I understand, but It is not nice, really - maybe only switch can be moved
to some inlining function like IsSuccess() - more .. with this function,
the SetResultVariables function will be more cleaner
Indeed. Attached v5 does that.
--
Fabien.
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
index 9faa365..bc9a2e4 100644
--- a/doc/src/sgml/ref/psql-ref.sgml
+++ b/doc/src/sgml/ref/psql-ref.sgml
@@ -3452,6 +3452,35 @@ bar
</varlistentry>
<varlistentry>
+ <term><varname>ERROR</varname></term>
+ <listitem>
+ <para>
+ Whether the last query failed, as a boolean.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>ERROR_CODE</varname></term>
+ <listitem>
+ <para>
+ The error code associated to the last query, or
+ <literal>00000</> if no error occured.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>ERROR_MESSAGE</varname></term>
+ <listitem>
+ <para>
+ If the last query failed, the associated error message,
+ otherwise an empty string.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><varname>FETCH_COUNT</varname></term>
<listitem>
<para>
@@ -3656,6 +3685,24 @@ bar
</varlistentry>
<varlistentry>
+ <term><varname>STATUS</varname></term>
+ <listitem>
+ <para>
+ Text status of the last query.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>ROW_COUNT</varname></term>
+ <listitem>
+ <para>
+ How many rows were returned or affected by the last query.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><varname>QUIET</varname></term>
<listitem>
<para>
diff --git a/src/bin/psql/common.c b/src/bin/psql/common.c
index 044cdb8..02fa89a 100644
--- a/src/bin/psql/common.c
+++ b/src/bin/psql/common.c
@@ -492,6 +492,48 @@ ResetCancelConn(void)
#endif
}
+/*
+ * ResultIsSuccess
+ *
+ * Tell whether query result is a success.
+ */
+static bool
+ResultIsSuccess(const PGresult *result)
+{
+ bool success;
+ if (!result)
+ success = false;
+ else
+ {
+ ExecStatusType restat = PQresultStatus(result);
+
+ /* check all possible PGRES_ */
+ switch (restat)
+ {
+ case PGRES_EMPTY_QUERY:
+ case PGRES_TUPLES_OK:
+ case PGRES_COMMAND_OK:
+ case PGRES_COPY_OUT:
+ case PGRES_COPY_IN:
+ case PGRES_COPY_BOTH:
+ case PGRES_SINGLE_TUPLE:
+ success = true;
+ break;
+ case PGRES_BAD_RESPONSE:
+ case PGRES_NONFATAL_ERROR:
+ case PGRES_FATAL_ERROR:
+ success = false;
+ break;
+ default:
+ /* dead code */
+ success = false;
+ psql_error("unexpected PQresultStatus: %d\n", restat);
+ break;
+ }
+ }
+
+ return success;
+}
/*
* AcceptResult
@@ -504,34 +546,7 @@ ResetCancelConn(void)
static bool
AcceptResult(const PGresult *result)
{
- bool OK;
-
- if (!result)
- OK = false;
- else
- switch (PQresultStatus(result))
- {
- case PGRES_COMMAND_OK:
- case PGRES_TUPLES_OK:
- case PGRES_EMPTY_QUERY:
- case PGRES_COPY_IN:
- case PGRES_COPY_OUT:
- /* Fine, do nothing */
- OK = true;
- break;
-
- case PGRES_BAD_RESPONSE:
- case PGRES_NONFATAL_ERROR:
- case PGRES_FATAL_ERROR:
- OK = false;
- break;
-
- default:
- OK = false;
- psql_error("unexpected PQresultStatus: %d\n",
- PQresultStatus(result));
- break;
- }
+ bool OK = ResultIsSuccess(result);
if (!OK)
{
@@ -1213,6 +1228,38 @@ PrintQueryResults(PGresult *results)
return success;
}
+/*
+ * Set special variables for "front door" queries
+ * - STATUS: last query status
+ * - ERROR: TRUE/FALSE, whether an error occurred
+ * - ERROR_CODE: code if an error occured, or "00000"
+ * - ERROR_MESSAGE: message if an error occured, or ""
+ * - ROW_COUNT: how many rows were returned or affected, or "0"
+ */
+static void
+SetResultVariables(PGresult *results)
+{
+ bool success = ResultIsSuccess(results);
+ ExecStatusType restat = PQresultStatus(results);
+ char *code = PQresultErrorField(results, PG_DIAG_SQLSTATE);
+ char *mesg = PQresultErrorField(results, PG_DIAG_MESSAGE_PRIMARY);
+
+ SetVariable(pset.vars, "STATUS", PQresStatus(restat) + strlen("PGRES_"));
+ SetVariable(pset.vars, "ERROR_CODE", code ? code : "00000");
+ SetVariable(pset.vars, "ERROR_MESSAGE", mesg ? mesg : "");
+
+ if (success)
+ {
+ char *ntuples = PQcmdTuples(results);
+ SetVariable(pset.vars, "ROW_COUNT", *ntuples ? ntuples : "0");
+ SetVariable(pset.vars, "ERROR", "FALSE");
+ }
+ else
+ {
+ SetVariable(pset.vars, "ROW_COUNT", "0");
+ SetVariable(pset.vars, "ERROR", "TRUE");
+ }
+}
/*
* SendQuery: send the query string to the backend
@@ -1346,6 +1393,9 @@ SendQuery(const char *query)
elapsed_msec = INSTR_TIME_GET_MILLISEC(after);
}
+ /* set special variables to reflect the result status */
+ SetResultVariables(results);
+
/* but printing results isn't: */
if (OK && results)
OK = PrintQueryResults(results);
diff --git a/src/test/regress/expected/psql.out b/src/test/regress/expected/psql.out
index d602aee..c3972a6 100644
--- a/src/test/regress/expected/psql.out
+++ b/src/test/regress/expected/psql.out
@@ -2904,6 +2904,69 @@ bar 'bar' "bar"
\echo 'should print #8-1'
should print #8-1
\endif
+-- special result variables
+-- 2 rows select
+SELECT 1 AS stuff UNION SELECT 2;
+ stuff
+-------
+ 1
+ 2
+(2 rows)
+
+\if :ERROR
+ \echo 'MUST NOT SHOW'
+\else
+ \echo 'ERROR is FALSE as expected'
+ERROR is FALSE as expected
+\endif
+\echo 'status:' :STATUS
+status: TUPLES_OK
+\echo 'error code:' :ERROR_CODE
+error code: 00000
+\echo 'error message:' :ERROR_MESSAGE
+error message:
+\echo 'number of rows:' :ROW_COUNT
+number of rows: 2
+-- syntax error
+SELECT 1 UNION;
+ERROR: syntax error at or near ";"
+LINE 1: SELECT 1 UNION;
+ ^
+\echo 'status:' :STATUS
+status: FATAL_ERROR
+\if :ERROR
+ \echo 'ERROR is TRUE as expected'
+ERROR is TRUE as expected
+\else
+ \echo 'MUST NOT SHOW'
+\endif
+\echo 'error code:' :ERROR_CODE
+error code: 42601
+\echo 'error message:' :ERROR_MESSAGE
+error message: syntax error at or near ";"
+\echo 'number of rows:' :ROW_COUNT
+number of rows: 0
+-- empty query
+;
+\echo 'status:' :STATUS
+status: EMPTY_QUERY
+\echo 'error code:' :ERROR_CODE
+error code: 00000
+\echo 'error message:' :ERROR_MESSAGE
+error message:
+\echo 'number of rows:' :ROW_COUNT
+number of rows: 0
+-- other query error
+DROP TABLE this_table_does_not_exist;
+ERROR: table "this_table_does_not_exist" does not exist
+\echo 'status:' :STATUS
+status: FATAL_ERROR
+\echo 'error code:' :ERROR_CODE
+error code: 42P01
+\echo 'error message:' :ERROR_MESSAGE
+error message: table "this_table_does_not_exist" does not exist
+\echo 'number of rows:' :ROW_COUNT
+number of rows: 0
-- SHOW_CONTEXT
\set SHOW_CONTEXT never
do $$
diff --git a/src/test/regress/sql/psql.sql b/src/test/regress/sql/psql.sql
index b56a05f..f83ac70 100644
--- a/src/test/regress/sql/psql.sql
+++ b/src/test/regress/sql/psql.sql
@@ -526,6 +526,46 @@ select \if false \\ (bogus \else \\ 42 \endif \\ forty_two;
\echo 'should print #8-1'
\endif
+-- special result variables
+
+-- 2 rows select
+SELECT 1 AS stuff UNION SELECT 2;
+\if :ERROR
+ \echo 'MUST NOT SHOW'
+\else
+ \echo 'ERROR is FALSE as expected'
+\endif
+\echo 'status:' :STATUS
+\echo 'error code:' :ERROR_CODE
+\echo 'error message:' :ERROR_MESSAGE
+\echo 'number of rows:' :ROW_COUNT
+
+-- syntax error
+SELECT 1 UNION;
+\echo 'status:' :STATUS
+\if :ERROR
+ \echo 'ERROR is TRUE as expected'
+\else
+ \echo 'MUST NOT SHOW'
+\endif
+\echo 'error code:' :ERROR_CODE
+\echo 'error message:' :ERROR_MESSAGE
+\echo 'number of rows:' :ROW_COUNT
+
+-- empty query
+;
+\echo 'status:' :STATUS
+\echo 'error code:' :ERROR_CODE
+\echo 'error message:' :ERROR_MESSAGE
+\echo 'number of rows:' :ROW_COUNT
+
+-- other query error
+DROP TABLE this_table_does_not_exist;
+\echo 'status:' :STATUS
+\echo 'error code:' :ERROR_CODE
+\echo 'error message:' :ERROR_MESSAGE
+\echo 'number of rows:' :ROW_COUNT
+
-- SHOW_CONTEXT
\set SHOW_CONTEXT never
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers