changeset 12718:1af86934c14e octave-forge

Make compatible with Octaves new exception-based error handling. Retain compatibility with Octaves old error handling based on error_state. * src/error_helpers.[h,cc]: Added. * src/Makefile.in: Integrate error-helpers.[h,cc]. * src/config.h.in: Added. * configure.ac, src/config.h.in: Test presence of 'error_state' and presence of 'verror (octave_execution_exception&, const char *, va_list)'. * src/__pq_connect__.cc, src/command.cc, src/command.h, src/converters.cc, src/converters_arr_comp.cc, src/pq_connection.cc, src/pq_conninfo.cc, src/pq_exec.cc, src/pq_lo.cc, src/pq_update_types.cc: If necessary, include error-helpers.h, replace error() with c_verror(), set and check a different error indicator than error_state, use CHECK_ERROR or SET_ERR, explicitely check for errors instead of relying on Octave checking error_state when returning to the prompt.
author i7tiol
date Sat, 27 Feb 2016 11:11:04 +0000
parents 87989220360f
children 65172e6662d6
files main/database/NEWS main/database/src/Makefile.in main/database/src/__pq_connect__.cc main/database/src/command.cc main/database/src/command.h main/database/src/config.h.in main/database/src/configure.ac main/database/src/converters.cc main/database/src/converters_arr_comp.cc main/database/src/error-helpers.cc main/database/src/error-helpers.h main/database/src/pq_connection.cc main/database/src/pq_conninfo.cc main/database/src/pq_exec.cc main/database/src/pq_lo.cc main/database/src/pq_update_types.cc
diffstat 16 files changed, 924 insertions(+), 523 deletions(-) [+]
line wrap: on
line diff
--- a/main/database/NEWS	Fri Feb 26 15:07:46 2016 +0000
+++ b/main/database/NEWS	Sat Feb 27 11:11:04 2016 +0000
@@ -1,3 +1,7 @@
+ ** Compatible with Octaves new exception-based error
+    handling. Compatibility with old error handling up to Octave-4.0
+    is retained.
+
  ** Fix: remove autoloaded function at package unload.
 
 database 2.3.2
--- a/main/database/src/Makefile.in	Fri Feb 26 15:07:46 2016 +0000
+++ b/main/database/src/Makefile.in	Sat Feb 27 11:11:04 2016 +0000
@@ -8,27 +8,29 @@
 
 ifndef CXXFLAGS
 CXXFLAGS_NSA := "-g -O2 -fno-strict-aliasing"
+CXXFLAGS := "-g -O2"
 else
 CXXFLAGS_NSA := "$(CXXFLAGS) -fno-strict-aliasing"
 endif
 
 OBJECTS := __pq_connect__.o pq_close.o pq_exec.o converters.o \
            converters_arr_comp.o pq_connection.o command.o \
-           pq_update_types.o pq_lo.o pq_conninfo.o __pq_internal_exit__.o
+           pq_update_types.o pq_lo.o pq_conninfo.o __pq_internal_exit__.o \
+           error-helpers.o
 
 pq_interface.oct: $(OBJECTS)
 	@MKOCTFILE@ -o pq_interface.oct -L`@PG_CONFIG@ --libdir` -lpq $(OBJECTS) $(EXTRALIBS)
 
-converters.o: converters.cc converters.h wrap_endian.h
+converters.o: converters.cc converters.h wrap_endian.h config.h error-helpers.h
 	CXX=$(CXX) CXXFLAGS=$(CXXFLAGS_NSA) @MKOCTFILE@ -I`@PG_CONFIG@ --includedir` -c converters.cc
 
 converters_arr_comp.o: converters_arr_comp.cc converters.h wrap_endian.h \
-                       pq_connection.h command.h
+                       pq_connection.h command.h config.h error-helpers.h
 	CXX=$(CXX) CXXFLAGS=$(CXXFLAGS_NSA) @MKOCTFILE@ -I`@PG_CONFIG@ --includedir` -c converters_arr_comp.cc
 
 # be on the safe side with respect to include files
-%.o: %.cc converters.h pq_connection.h command.h
-	CXX=$(CXX) @MKOCTFILE@ -I`@PG_CONFIG@ --includedir` -c $<
+%.o: %.cc converters.h pq_connection.h command.h config.h error-helpers.h
+	CXX=$(CXX) CXXFLAGS=$(CXXFLAGS) @MKOCTFILE@ -I`@PG_CONFIG@ --includedir` -c $<
 
 .PHONY: clean
 clean: ; rm -f *.o *.oct
--- a/main/database/src/__pq_connect__.cc	Fri Feb 26 15:07:46 2016 +0000
+++ b/main/database/src/__pq_connect__.cc	Sat Feb 27 11:11:04 2016 +0000
@@ -20,6 +20,7 @@
 #include <octave/oct.h>
 
 #include "pq_connection.h"
+#include "error-helpers.h"
 
 
 // PKG_ADD: autoload ("__pq_connect__", "pq_interface.oct");
@@ -34,6 +35,8 @@
 {
   std::string fname ("__pq_connect__");
 
+  octave_value retval;
+
   if (args.length () != 1)
     {
       print_usage ();
@@ -41,21 +44,16 @@
       return octave_value_list ();
     }
 
-  std::string opt_string = args(0).string_value ();
+  std::string opt_string;
+  CHECK_ERROR (opt_string = args(0).string_value (), retval,
+               "%s: argument not a string", fname.c_str ());
 
-  if (error_state)
-    {
-      error ("%s: argument not a string", fname.c_str ());
+  octave_pq_connection *oct_pq_conn = new octave_pq_connection (opt_string);
 
-      return octave_value_list ();
-    }
-
-  octave_value retval (new octave_pq_connection (opt_string));
+  if (! oct_pq_conn->get_rep ()->octave_pq_get_conn ())
+    error ("%s failed", fname.c_str ());
+  else
+    retval = oct_pq_conn;
 
-  // We spare checking
-  // bool(octave_pq_connection_rep::octave_pq_get_conn()), since in
-  // case of false there was an error thrown, so destruction of the
-  // octave_pq_connection object will be caused by Octaves reference
-  // counting scheme.
   return retval;
 }
--- a/main/database/src/command.cc	Fri Feb 26 15:07:46 2016 +0000
+++ b/main/database/src/command.cc	Sat Feb 27 11:11:04 2016 +0000
@@ -27,6 +27,7 @@
 
 #include "command.h"
 #include "converters.h"
+#include "error-helpers.h"
 
 #define COPY_HEADER_SIZE 19
 
@@ -40,14 +41,14 @@
   if (! (cptr = conn.octave_pq_get_conn ()))
     {
       valid = 0;
-      error ("%s: connection not open", caller.c_str ());
+      c_verror ("%s: connection not open", caller.c_str ());
     }
 
   if (! PQsendQuery (cptr, cmd.c_str ()))
     {
       valid = 0;
-      error ("%s: could not dispatch command: %s", caller.c_str (),
-             PQerrorMessage (cptr));
+      c_verror ("%s: could not dispatch command: %s", caller.c_str (),
+                PQerrorMessage (cptr));
     }
   else
     {
@@ -64,10 +65,10 @@
   if (! (cptr = conn.octave_pq_get_conn ()))
     {
       valid = 0;
-      error ("%s: connection not open", caller.c_str ());
+      c_verror ("%s: connection not open", caller.c_str ());
     }
 
-  int npars = params.length ();
+  int npars = params.numel ();
 
   char *vals [npars];
   std::vector<oct_pq_dynvec_t> valsvec;
@@ -106,12 +107,14 @@
             }
           else
             {
-              std::string s = ptypes(i).string_value ();
-              if (error_state)
+              bool err;
+              std::string s;
+              SET_ERR (s = ptypes(i).string_value (), err);
+              if (err)
                 {
-                  error ("%s: parameter type specification no string",
-                         caller.c_str ());
                   valid = 0;
+                  c_verror ("%s: parameter type specification no string",
+                            caller.c_str ());
                   break;
                 }
 
@@ -146,10 +149,10 @@
 
             default:
               // should not get here
-              error ("%s: internal error, undefined type identifier",
-                     caller.c_str ());
+              valid = 0;
+              c_verror ("%s: internal error, undefined type identifier",
+                        caller.c_str ());
 
-              valid = 0;
             }
 
           if (! valid) break;
@@ -241,12 +244,12 @@
         {
         case PGRES_BAD_RESPONSE:
           valid = 0;
-          error ("%s: server response not understood", caller.c_str ());
+          c_verror ("%s: server response not understood", caller.c_str ());
           break;
         case PGRES_FATAL_ERROR:
           valid = 0;
-          error ("%s: fatal error: %s", caller.c_str (),
-                 PQresultErrorMessage (res));
+          c_verror ("%s: fatal error: %s", caller.c_str (),
+                    PQresultErrorMessage (res));
           break;
         case PGRES_COMMAND_OK:
           retval = command_ok_handler ();
@@ -264,7 +267,7 @@
           break;
         default:
           valid = 0;
-          error ("internal error, unexpected server response");
+          c_verror ("internal error, unexpected server response");
         }
 
       if (res) // could have been changed by a handler
@@ -294,13 +297,14 @@
   octave_map types (dim_vector (1, nf));
 
   bool rtypes_given;
-  int l = rettypes.length ();
+  int l = rettypes.numel ();
   if (l > 0)
     {
       if (l != nf)
         {
-          error ("%s: wrong number of given returned types", caller.c_str ());
           valid = 0;
+          c_verror ("%s: wrong number of given returned types",
+                    caller.c_str ());
           return octave_value_list ();
         }
       rtypes_given = true;
@@ -324,25 +328,27 @@
 
       if (rtypes_given) // for internal reading of system tables
         {
-          std::string type = rettypes(j).string_value ();
-          if (error_state)
-            error ("%s: could not convert given type to string",
-                   caller.c_str ());
-          else
-            conv = pgtype_from_spec (conn, type, oct_type);
-
-          if (error_state)
+          std::string type;
+          bool err;
+          SET_ERR (type = rettypes(j).string_value (), err);
+          if (err)
+            {
+              valid = 0;
+              c_verror ("%s: could not convert given type to string",
+                        caller.c_str ());
+              break;
+            }
+          else if (! (conv = pgtype_from_spec (conn, type, oct_type)))
             {
               valid = 0;
               break;
             }
         }
-      else
-        if (! (conv = pgtype_from_spec (conn, PQftype (res, j), oct_type)))
-          {
-            valid = 0;
-            break;
-          }
+      else if (! (conv = pgtype_from_spec (conn, PQftype (res, j), oct_type)))
+        {
+          valid = 0;
+          break;
+        }
 
       if (f)
         {
@@ -413,8 +419,8 @@
 
                 default:
                   // should not get here
-                  error ("%s: internal error, undefined type identifier",
-                         caller.c_str ());
+                  c_verror ("%s: internal error, undefined type identifier",
+                            caller.c_str ());
 
                   valid = 0;
                 }
@@ -430,7 +436,7 @@
         break;
     }
 
-  if (error_state)
+  if (! valid)
     return octave_value_list ();
   else
     {
@@ -456,19 +462,14 @@
     {
       // store unchecked output in file
 
-      if (outfile.empty ())
+      std::ofstream ostr (outfile.c_str (), std::ios_base::out);
+      if (ostr.fail ())
         {
-          error ("no output file given");
-
           valid = 0;
-
+          c_verror ("could not open output file %s", outfile.c_str ());
           return retval;
         }
 
-      std::ofstream ostr (outfile.c_str (), std::ios_base::out);
-      if (ostr.fail ())
-        error ("could not open output file %s", outfile.c_str ());
-
       char *data;
       int nb;
       while ((nb = PQgetCopyData (cptr, &data, 0)) > 0)
@@ -477,16 +478,19 @@
             {
               ostr.write (data, nb);
               if (ostr.bad ())
-                error ("write to file failed");
+                c_verror ("write to file failed");
             }
           PQfreemem (data);
         }
 
-      if (! error_state)
+      if (! ostr.bad ())
         ostr.close ();
 
       if (nb == -2)
-        error ("server error in copy-out: %s", PQerrorMessage (cptr));
+        {
+          valid = 0;
+          c_verror ("server error in copy-out: %s", PQerrorMessage (cptr));
+        }
       else
         {
           PQclear (res);
@@ -494,17 +498,24 @@
           if ((res = PQgetResult (cptr)))
             {
               if ((state = PQresultStatus (res)) == PGRES_FATAL_ERROR)
-                error ("server error in copy-out: %s", PQerrorMessage (cptr));
+                {
+                  valid = 0;
+                  c_verror ("server error in copy-out: %s",
+                            PQerrorMessage (cptr));
+                }
             }
           else
-            error ("unexpectedly got no result information");
+            {
+              valid = 0;
+              c_verror ("unexpectedly got no result information");
+            }
         }
     }
   else
-    error ("no output file given");
-
-  if (error_state)
-    valid = 0;
+    {
+      valid = 0;
+      c_verror ("no output file given");
+    }
 
   return octave_value (std::string ("copy out"));
 }
@@ -527,9 +538,9 @@
 
       if (infile.empty ())
         {
-          error ("no input file given");
+          valid = 0;
 
-          valid = 0;
+          c_verror ("no input file given");
 
           return retval;
         }
@@ -537,11 +548,11 @@
       std::ifstream istr (infile.c_str (), std::ios_base::in);
       if (istr.fail ())
         {
-          error ("could not open input file %s", infile.c_str ());
+          c_verror ("could not open input file %s", infile.c_str ());
 
           PQputCopyEnd (cptr, "could not open input file");
 
-          error ("server error: %s", PQerrorMessage (cptr));
+          c_verror ("server error: %s", PQerrorMessage (cptr));
 
           valid = 0;
 
@@ -554,7 +565,9 @@
 
           if (istr.bad ())
             {
-              error ("could not read file %s", infile.c_str ());
+              valid = 0;
+
+              c_verror ("could not read file %s", infile.c_str ());
 
               break;
             }
@@ -565,7 +578,9 @@
               if ((nb = istr.gcount ()) > 0)
                 if (PQputCopyData (cptr, buff, nb) == -1)
                   {
-                    error ("%s", PQerrorMessage (cptr));
+                    valid = 0;
+                    
+                    c_verror ("%s", PQerrorMessage (cptr));
 
                     break;
                   }
@@ -575,16 +590,19 @@
 
       istr.close ();
 
-      if (error_state)
+      if (! valid)
         {
           PQputCopyEnd (cptr, "copy-in interrupted");
 
-          error ("%s", PQerrorMessage (cptr));
+          c_verror ("%s", PQerrorMessage (cptr));
         }
       else
         {
           if (PQputCopyEnd (cptr, NULL) == -1)
-            error ("%s", PQerrorMessage (cptr));
+            {
+              valid = 0;
+              c_verror ("%s", PQerrorMessage (cptr));
+            }
           else
             {
               PQclear (res);
@@ -592,10 +610,17 @@
               if ((res = PQgetResult (cptr)))
                 {
                   if ((state = PQresultStatus (res)) == PGRES_FATAL_ERROR)
-                    error ("server error in copy-in: %s", PQerrorMessage (cptr));
+                    {
+                      valid = 0;
+                      c_verror ("server error in copy-in: %s",
+                                PQerrorMessage (cptr));
+                    }
                 }
               else
-                error ("unexpectedly got no result information");
+                {
+                  valid = 0;
+                  c_verror ("unexpectedly got no result information");
+                }
             }
         }
     }
@@ -610,15 +635,19 @@
       octave_idx_type nf = PQnfields (res);
       if (c != nf + oids)
         {
-          error ("variable for copy-in has %i columns, but should have %i",
-                 c, nf + oids);
+          valid = 0;
+
+          c_verror ("variable for copy-in has %i columns, but should have %i",
+                    c, nf + oids);
 
           PQputCopyEnd
             (cptr, "variable for copy-in has wrong number of columns");
         }
       else if (! PQbinaryTuples (res))
         {
-          error ("copy-in from variable must use binary mode");
+          valid = 0;
+
+          c_verror ("copy-in from variable must use binary mode");
 
           PQputCopyEnd (cptr, "copy-in from variable must use binary mode");
         }
@@ -627,7 +656,9 @@
           for (octave_idx_type j = 0; j < nf; j++)
             if (! PQfformat (res, j))
               {
-                error ("copy-in from variable must use binary mode in all columns");
+                valid = 0;
+
+                c_verror ("copy-in from variable must use binary mode in all columns");
 
                 PQputCopyEnd (cptr, "copy-in from variable must use binary mode in all columns");
 
@@ -635,11 +666,9 @@
               }
         }
 
-      if (error_state)
+      if (! valid)
         {
-          error ("server error: %s", PQerrorMessage (cptr));
-
-          valid = 0;
+          c_verror ("server error: %s", PQerrorMessage (cptr));
 
           return retval;
         }
@@ -658,7 +687,9 @@
         {
           PQputCopyEnd (cptr, "could not send header");
 
-          error ("server error: %s", PQerrorMessage (cptr));
+          valid = 0;
+
+          c_verror ("server error: %s", PQerrorMessage (cptr));
         }
       else
         {
@@ -671,11 +702,13 @@
               int16_t fc = htobe16 (int16_t (nf));
               if (PQputCopyData (cptr, (char *) &fc, 2) == -1)
                 {
-                  error ("%s", PQerrorMessage (cptr));
+                  c_verror ("%s", PQerrorMessage (cptr));
 
                   PQputCopyEnd (cptr, "error sending field count");
 
-                  error ("server error: %s", PQerrorMessage (cptr));
+                  c_verror ("server error: %s", PQerrorMessage (cptr));
+
+                  valid = 0;
 
                   break;
                 }
@@ -689,7 +722,9 @@
                       int32_t t = htobe32 (int32_t (-1));
                       if (PQputCopyData (cptr, (char *) &t, 4) == -1)
                         {
-                          error ("could not send NULL in copy-in");
+                          valid = 0;
+
+                          c_verror ("could not send NULL in copy-in");
 
                           break;
                         }
@@ -701,8 +736,14 @@
                           if ((j == 0) && oids)
                             {
                               std::string t ("oid");
-                              convs[0] = pgtype_from_spec (conn, t,
-                                                           oct_types[0]);
+                              if (! (convs[0] =
+                                     pgtype_from_spec (conn, t, oct_types[0])))
+                                {
+                                  valid = 0;
+
+                                  c_verror ("could not get converter for oid in copy-in");
+                                  break;
+                                }
                             }
                           else
                             {
@@ -714,18 +755,25 @@
                                          pgtype_from_octtype (conn,
                                                               data(i, j))))
                                     {
-                                      error ("could not determine type in column %i for copy-in",
-                                             j);
+                                      valid = 0;
+
+                                      c_verror ("could not determine type in column %i for copy-in",
+                                                j);
 
                                       break;
                                     }
                                 }
                               else
                                 {
-                                  std::string s = cin_types(j).string_value ();
-                                  if (error_state)
+                                  bool err;
+                                  std::string s;
+                                  SET_ERR (s = cin_types(j).string_value (),
+                                           err);
+                                  if (err)
                                     {
-                                      error ("column type specification no string");
+                                      valid = 0;
+
+                                      c_verror ("column type specification no string");
 
                                       break;
                                     }
@@ -734,7 +782,9 @@
                                          pgtype_from_spec (conn, s,
                                                            oct_types[j])))
                                     {
-                                      error ("invalid column type specification");
+                                      valid = 0;
+
+                                      c_verror ("invalid column type specification");
 
                                       break;
                                     }
@@ -766,49 +816,64 @@
 
                         default:
                           // should not get here
-                          error ("internal error, undefined type identifier");
+                          c_verror ("internal error, undefined type identifier");
+                          conversion_failed = true;
                         }
 
                       if (conversion_failed)
-                        error ("could not convert data(%i, %i) for copy-in",
-                               i, j);
+                        {
+                          valid = 0;
+                          error ("could not convert data(%i, %i) for copy-in",
+                                 i, j);
+                        }
                       else
                         {
                           uint32_t t = htobe32 (uint32_t (val.size ()));
                           if (PQputCopyData (cptr, (char *) &t, 4) == -1)
-                            error ("could not send data length in copy-in");
+                            {
+                              valid = 0;
+                              c_verror ("could not send data length in copy-in");
+                            }
                           else if (PQputCopyData (cptr, &(val.front ()),
                                                   val.size ()) == -1)
-                            error ("could not send copy-in data");
+                            {
+                              valid = 0;
+                              c_verror ("could not send copy-in data");
+                            }
                         }
 
-                      if (error_state) break;
+                      if (! valid) break;
                     }
                 } // columns of argument data
 
-              if (error_state)
+              if (! valid)
                 {
                   PQputCopyEnd (cptr, "error sending copy-in data");
 
-                  error ("server error: %s", PQerrorMessage (cptr));
+                  c_verror ("server error: %s", PQerrorMessage (cptr));
 
                   break;
                 }
             } // rows of argument data
         }
 
-      if (! error_state)
+      if (valid)
         if (PQputCopyData (cptr, trailer, 2) == -1)
           {
+            valid = 0;
+
             PQputCopyEnd (cptr, "could not send trailer");
 
-            error ("%s", PQerrorMessage (cptr));
+            c_verror ("%s", PQerrorMessage (cptr));
           }
 
-      if (! error_state)
+      if (valid)
         {
           if (PQputCopyEnd (cptr, NULL) == -1)
-            error ("%s", PQerrorMessage (cptr));
+            {
+              valid = 0;
+              c_verror ("%s", PQerrorMessage (cptr));
+            }
           else
             {
               PQclear (res);
@@ -816,17 +881,20 @@
               if ((res = PQgetResult (cptr)))
                 {
                   if ((state = PQresultStatus (res)) == PGRES_FATAL_ERROR)
-                    error ("server error in copy-in: %s",
-                           PQerrorMessage (cptr));
+                    {
+                      valid = 0;
+                      c_verror ("server error in copy-in: %s",
+                                PQerrorMessage (cptr));
+                    }
                 }
               else
-                error ("unexpectedly got no result information");
+                {
+                  valid = 0;
+                  c_verror ("unexpectedly got no result information");
+                }
             }
         }
     } // copy from variable
 
-  if (error_state)
-    valid = 0;
-
   return octave_value (std::string ("copy in"));
 }
--- a/main/database/src/command.h	Fri Feb 26 15:07:46 2016 +0000
+++ b/main/database/src/command.h	Sat Feb 27 11:11:04 2016 +0000
@@ -26,6 +26,7 @@
 #include <octave/Cell.h>
 
 #include "pq_connection.h"
+#include "error-helpers.h"
 
 class
 command
@@ -87,14 +88,14 @@
       if (! res)
         {
           valid = 0;
-          error ("%s: could not execute command: %s", caller.c_str (),
-                 PQerrorMessage (cptr));
+          c_verror ("%s: could not execute command: %s", caller.c_str (),
+                    PQerrorMessage (cptr));
 
         }
       else if ((state = PQresultStatus (res)) == PGRES_EMPTY_QUERY)
         {
           valid = 0;
-          error ("%s: empty command", caller.c_str ());
+          c_verror ("%s: empty command", caller.c_str ());
         }
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main/database/src/config.h.in	Sat Feb 27 11:11:04 2016 +0000
@@ -0,0 +1,6 @@
+/* Define as 1 if liboctinterp is old enough to provide error_state. */
+#undef HAVE_OCTAVE_ERROR_STATE
+
+/* Define as 1 if liboctinterp has
+'verror (octave_execution_exception&, const char *, va_list)'. */
+#undef HAVE_OCTAVE_VERROR_ARG_EXC
--- a/main/database/src/configure.ac	Fri Feb 26 15:07:46 2016 +0000
+++ b/main/database/src/configure.ac	Sat Feb 27 11:11:04 2016 +0000
@@ -4,6 +4,7 @@
 AC_PREREQ([2.67])
 AC_INIT([database], [2.2.0], [i7tiol@t-online.de])
 AC_CONFIG_SRCDIR([__pq_connect__.cc])
+AC_CONFIG_HEADERS([config.h])
 
 # Checks for programs.
 AC_PROG_CXX
@@ -13,6 +14,7 @@
   
 AC_CHECK_PROG(OCTAVE, octave, octave)
 AC_CHECK_PROG(MKOCTFILE, mkoctfile, mkoctfile)
+AC_CHECK_PROG(OCTAVE_CONFIG, octave-config, octave-config)
 AC_CHECK_PROG(PG_CONFIG, pg_config, pg_config)
 if test -z "$PG_CONFIG"; then
 AC_MSG_ERROR([pg_config not found], 1);
@@ -38,5 +40,39 @@
    AC_MSG_RESULT(yes)
 fi
 
+# Start of checks for Octave features, preparations for checks.
+OCTLIBDIR=${OCTLIBDIR:-`$OCTAVE_CONFIG -p OCTLIBDIR`}
+OCTINCLUDEDIR=${OCTINCLUDEDIR:-`$OCTAVE_CONFIG -p OCTINCLUDEDIR`}
+AC_LANG_PUSH([C++])
+TCXXFLAGS=$CXXFLAGS
+TLDFLAGS=$LDFLAGS
+TLIBS=$LIBS
+LDFLAGS="-L$OCTLIBDIR $LDFLAGS"
+LIBS="-loctinterp $LIBS"
+CXXFLAGS="-I$OCTINCLUDEDIR $CXXFLAGS"
+
+## Presence of 'error_state' -- does _not_ indicate no exceptions are
+## used.
+AC_LINK_IFELSE(
+  [AC_LANG_PROGRAM([[#include <oct.h>]
+                    [#include <stdio.h>]],
+                   [[printf ("%i", error_state);]])],
+  [AC_DEFINE([HAVE_OCTAVE_ERROR_STATE], 1)])
+
+## Presence of 'verror (octave_execution_exception&, const char *,
+## va_list)'
+AC_LINK_IFELSE(
+  [AC_LANG_PROGRAM([[#include <oct.h>]],
+                   [[octave_execution_exception e;]
+                    [va_list args;]
+                    [verror (e, "test", args);]])],
+  [AC_DEFINE([HAVE_OCTAVE_VERROR_ARG_EXC], 1)])
+
+LIBS=$TLIBS
+LDFLAGS=$TLDFLAGS
+CXXFLAGS=$TCXXFLAGS
+AC_LANG_POP([C++])
+# End of checks for Octave features.
+
 AC_CONFIG_FILES([Makefile])
 AC_OUTPUT
--- a/main/database/src/converters.cc	Fri Feb 26 15:07:46 2016 +0000
+++ b/main/database/src/converters.cc	Sat Feb 27 11:11:04 2016 +0000
@@ -33,6 +33,7 @@
 
 #include "converters.h"
 #include "pq_connection.h"
+#include "error-helpers.h"
 
 // remember to adjust OCT_PQ_NUM_CONVERTERS in converters.h
 
@@ -75,11 +76,12 @@
 int from_octave_str_bool (const octave_pq_connection_rep &conn,
                           const octave_value &ov, oct_pq_dynvec_t &val)
 {
-  bool b = ov.bool_value ();
-
-  if (error_state)
+  bool b, err;
+  SET_ERR (b = ov.bool_value (), err);
+
+  if (err)
     {
-      error ("can not convert octave_value to bool value");
+      c_verror ("can not convert octave_value to bool value");
       return 1;
     }
 
@@ -92,11 +94,12 @@
 int from_octave_bin_bool (const octave_pq_connection_rep &conn,
                           const octave_value &ov, oct_pq_dynvec_t &val)
 {
-  bool b = ov.bool_value ();
-
-  if (error_state)
+  bool b, err;
+  SET_ERR (b = ov.bool_value (), err);
+
+  if (err)
     {
-      error ("can not convert octave_value to bool value");
+      c_verror ("can not convert octave_value to bool value");
       return 1;
     }
 
@@ -145,11 +148,13 @@
 int from_octave_bin_oid (const octave_pq_connection_rep &conn,
                          const octave_value &ov, oct_pq_dynvec_t &val)
 {
-  uint32_t oid = ov.uint_value ();
-
-  if (error_state)
+  uint32_t oid;
+  bool err;
+  SET_ERR (oid = ov.uint_value (), err);
+
+  if (err)
     {
-      error ("can not convert octave_value to oid value");
+      c_verror ("can not convert octave_value to oid value");
       return 1;
     }
 
@@ -218,11 +223,12 @@
   }
   swap;
 
-  swap.d = ov.double_value ();
-
-  if (error_state)
+  bool err;
+  SET_ERR (swap.d = ov.double_value (), err);
+
+  if (err)
     {
-      error ("can not convert octave_value to float8 value");
+      c_verror ("can not convert octave_value to float8 value");
       return 1;
     }
 
@@ -291,11 +297,12 @@
   }
   swap;
 
-  swap.f = ov.float_value ();
-
-  if (error_state)
+  bool err;
+  SET_ERR (swap.f = ov.float_value (), err);
+
+  if (err)
     {
-      error ("can not convert octave_value to float4 value");
+      c_verror ("can not convert octave_value to float4 value");
       return 1;
     }
 
@@ -350,11 +357,13 @@
 int from_octave_bin_bytea (const octave_pq_connection_rep &conn,
                            const octave_value &ov, oct_pq_dynvec_t &val)
 {
-  uint8NDArray b = ov.uint8_array_value ();
-
-  if (error_state)
+  uint8NDArray b;
+  bool err;
+  SET_ERR (b = ov.uint8_array_value (), err);
+
+  if (err)
     {
-      error ("can not convert octave_value to bytea representation");
+      c_verror ("can not convert octave_value to bytea representation");
       return 1;
     }
 
@@ -408,11 +417,13 @@
 int from_octave_bin_text (const octave_pq_connection_rep &conn,
                           const octave_value &ov, oct_pq_dynvec_t &val)
 {
-  std::string s = ov.string_value ();
-
-  if (error_state)
+  std::string s;
+  bool err;
+  SET_ERR (s = ov.string_value (), err);
+
+  if (err)
     {
-      error ("can not convert octave_value to string");
+      c_verror ("can not convert octave_value to string");
       return 1;
     }
 
@@ -515,11 +526,13 @@
 int from_octave_bin_int2 (const octave_pq_connection_rep &conn,
                           const octave_value &ov, oct_pq_dynvec_t &val)
 {
-  int16_t i2 = ov.int_value ();
-
-  if (error_state)
+  int16_t i2;
+  bool err;
+  SET_ERR (i2 = ov.int_value (), err);
+
+  if (err)
     {
-      error ("can not convert octave_value to int2 value");
+      c_verror ("can not convert octave_value to int2 value");
       return 1;
     }
 
@@ -569,11 +582,13 @@
 int from_octave_bin_int4 (const octave_pq_connection_rep &conn,
                           const octave_value &ov, oct_pq_dynvec_t &val)
 {
-  int32_t i4 = ov.int_value ();
-
-  if (error_state)
+  int32_t i4;
+  bool err;
+  SET_ERR (i4 = ov.int_value (), err);
+
+  if (err)
     {
-      error ("can not convert octave_value to int4 value");
+      c_verror ("can not convert octave_value to int4 value");
       return 1;
     }
 
@@ -623,11 +638,13 @@
 int from_octave_bin_int8 (const octave_pq_connection_rep &conn,
                           const octave_value &ov, oct_pq_dynvec_t &val)
 {
-  int64_t i8 = ov.int64_scalar_value ();
-
-  if (error_state)
+  int64_t i8;
+  bool err;
+  SET_ERR (i8 = ov.int64_scalar_value (), err);
+
+  if (err)
     {
-      error ("can not convert octave_value to int8 value");
+      c_verror ("can not convert octave_value to int8 value");
       return 1;
     }
 
@@ -702,15 +719,17 @@
       // don't convert automatically because of possible overflow
       if (ov.is_float_type ())
         {
-          error ("floating point octave_value provided for 8-byte time value, but postgresql is configured for int64");
+          c_verror ("floating point octave_value provided for 8-byte time value, but postgresql is configured for int64");
           return 1;
         }
 
-      int64_t i8 = ov.int64_scalar_value ();
-
-      if (error_state)
+      int64_t i8;
+      bool err;
+      SET_ERR (i8 = ov.int64_scalar_value (), err);
+
+      if (err)
         {
-          error ("can not convert octave_value to int64 time value");
+          c_verror ("can not convert octave_value to int64 time value");
           return 1;
         }
 
@@ -723,7 +742,7 @@
       // don't convert automatically because of possible loss of accuracy
       if (ov.is_integer_type ())
         {
-          error ("integer type octave_value provided for 8-byte time value, but postgresql is configured for double");
+          c_verror ("integer type octave_value provided for 8-byte time value, but postgresql is configured for double");
           return 1;
         }
 
@@ -734,11 +753,12 @@
       }
       swap;
 
-      swap.d = ov.double_value ();
-
-      if (error_state)
+      bool err;
+      SET_ERR (swap.d = ov.double_value (), err);
+
+      if (err)
         {
-          error ("can not convert octave_value to double time value");
+          c_verror ("can not convert octave_value to double time value");
           return 1;
         }
 
@@ -847,10 +867,12 @@
 int from_octave_bin_interval (const octave_pq_connection_rep &conn,
                               const octave_value &ov, oct_pq_dynvec_t &val)
 {
-  Cell iv = ov.cell_value ();
-  if (error_state || iv.numel () != 3)
+  Cell iv;
+  bool err;
+  SET_ERR (iv = ov.cell_value (), err);
+  if (err || iv.numel () != 3)
     {
-      error ("interval: can not convert octave_value to cell with 3 elements");
+      c_verror ("interval: can not convert octave_value to cell with 3 elements");
       return 1;
     }
 
@@ -859,11 +881,13 @@
 
   for (int id = 1; id < 3; id++)
     {
-      int32_t i4 = iv(id).int_value ();
-
-      if (error_state)
+      int32_t i4;
+      bool err;
+      SET_ERR (i4 = iv(id).int_value (), err);
+
+      if (err)
         {
-          error ("interval: can not convert octave_value to int4 value");
+          c_verror ("interval: can not convert octave_value to int4 value");
           return 1;
         }
 
@@ -964,21 +988,24 @@
 int from_octave_bin_timetz (const octave_pq_connection_rep &conn,
                             const octave_value &ov, oct_pq_dynvec_t &val)
 {
-  Cell iv = ov.cell_value ();
-  if (error_state || iv.numel () != 2)
+  Cell iv;
+  bool err;
+  SET_ERR (iv = ov.cell_value (), err);
+  if (err || iv.numel () != 2)
     {
-      error ("timetz: can not convert octave_value to cell with 2 elements");
+      c_verror ("timetz: can not convert octave_value to cell with 2 elements");
       return 1;
     }
 
   if (time_8byte_from_octave (iv(0), val, conn.get_integer_datetimes ()))
     return 1;
 
-  int32_t i4 = iv(1).int_value ();
-
-  if (error_state)
+  int32_t i4;
+  SET_ERR (i4 = iv(1).int_value (), err);
+
+  if (err)
     {
-      error ("timetz: can not convert octave_value to int4 value");
+      c_verror ("timetz: can not convert octave_value to int4 value");
       return 1;
     }
 
@@ -1027,11 +1054,13 @@
 int from_octave_bin_date (const octave_pq_connection_rep &conn,
                           const octave_value &ov, oct_pq_dynvec_t &val)
 {
-  int32_t i4 = ov.int_value ();
-
-  if (error_state)
+  int32_t i4;
+  bool err;
+  SET_ERR (i4 = ov.int_value (), err);
+
+  if (err)
     {
-      error ("date: can not convert octave_value to int4 value");
+      c_verror ("date: can not convert octave_value to int4 value");
       return 1;
     }
 
@@ -1096,11 +1125,13 @@
 int from_octave_bin_point (const octave_pq_connection_rep &conn,
                            const octave_value &ov, oct_pq_dynvec_t &val)
 {
-  NDArray m = ov.array_value ();
-
-  if (error_state || m.numel () != 2)
+  NDArray m;
+  bool err;
+  SET_ERR (m = ov.array_value (), err);
+
+  if (err || m.numel () != 2)
     {
-      error ("can not convert octave_value to point representation");
+      c_verror ("can not convert octave_value to point representation");
       return 1;
     }
 
@@ -1177,11 +1208,13 @@
 int from_octave_bin_lseg (const octave_pq_connection_rep &conn,
                           const octave_value &ov, oct_pq_dynvec_t &val)
 {
-  NDArray m = ov.array_value ();
-
-  if (error_state || m.numel () != 4)
+  NDArray m;
+  bool err;
+  SET_ERR (m = ov.array_value (), err);
+
+  if (err || m.numel () != 4)
     {
-      error ("can not convert octave_value to 4 doubles");
+      c_verror ("can not convert octave_value to 4 doubles");
       return 1;
     }
 
@@ -1292,11 +1325,13 @@
 int from_octave_bin_circle (const octave_pq_connection_rep &conn,
                             const octave_value &ov, oct_pq_dynvec_t &val)
 {
-  NDArray m = ov.array_value ();
-
-  if (error_state || m.numel () != 3)
+  NDArray m;
+  bool err;
+  SET_ERR (m = ov.array_value (), err);
+
+  if (err || m.numel () != 3)
     {
-      error ("can not convert octave_value to circle representation");
+      c_verror ("can not convert octave_value to circle representation");
       return 1;
     }
 
@@ -1379,11 +1414,13 @@
 {
   octave_idx_type nel;
 
-  NDArray m = ov.array_value ();
-
-  if (error_state || (nel = m.numel ()) % 2)
+  NDArray m;
+  bool err;
+  SET_ERR (m = ov.array_value (), err);
+
+  if (err || (nel = m.numel ()) % 2)
     {
-      error ("can not convert octave_value to polygon representation");
+      c_verror ("can not convert octave_value to polygon representation");
       return 1;
     }
 
@@ -1474,22 +1511,29 @@
 int from_octave_bin_path (const octave_pq_connection_rep &conn,
                           const octave_value &ov, oct_pq_dynvec_t &val)
 {
-  octave_scalar_map tp = ov.scalar_map_value ();
-  if (error_state || ! tp.isfield ("closed") || ! tp.isfield ("path"))
+  octave_scalar_map tp;
+  bool err;
+  SET_ERR (tp = ov.scalar_map_value (), err);
+  if (err || ! tp.isfield ("closed") || ! tp.isfield ("path"))
     {
-      error ("can not convert octave_value to path representation");
+      c_verror ("can not convert octave_value to path representation");
       return 1;
     }
 
   octave_idx_type nel;
 
-  char closed = char (tp.contents ("closed").bool_value ());
-
-  NDArray m = tp.contents ("path").array_value ();
-
-  if (error_state || (nel = m.numel ()) % 2)
+  char closed;
+  SET_ERR (closed = char (tp.contents ("closed").bool_value ()), err);
+
+  NDArray m;
+  if (! err)
     {
-      error ("can not convert octave_value to path representation");
+      SET_ERR (m = tp.contents ("path").array_value (), err);
+    }
+
+  if (err || (nel = m.numel ()) % 2)
+    {
+      c_verror ("can not convert octave_value to path representation");
       return 1;
     }
 
@@ -1542,7 +1586,7 @@
 int to_octave_str_unknown (const octave_pq_connection_rep &conn,
                            const char *c, octave_value &ov, int nb)
 {
-  error ("can not convert postgresql type 'unknown'");
+  c_verror ("can not convert postgresql type 'unknown'");
 
   return 1;
 }
@@ -1550,7 +1594,7 @@
 int to_octave_bin_unknown (const octave_pq_connection_rep &conn,
                            const char *c, octave_value &ov, int nb)
 {
-  error ("can not convert postgresql type 'unknown'");
+  c_verror ("can not convert postgresql type 'unknown'");
 
   return 1;
 }
@@ -1558,7 +1602,7 @@
 int from_octave_str_unknown (const octave_pq_connection_rep &conn,
                              const octave_value &ov, oct_pq_dynvec_t &val)
 {
-  error ("can not convert postgresql type 'unknown'");
+  c_verror ("can not convert postgresql type 'unknown'");
 
   return 1;
 }
@@ -1566,7 +1610,7 @@
 int from_octave_bin_unknown (const octave_pq_connection_rep &conn,
                              const octave_value &ov, oct_pq_dynvec_t &val)
 {
-  error ("can not convert postgresql type 'unknown'");
+  c_verror ("can not convert postgresql type 'unknown'");
 
   return 1;
 }
@@ -1608,7 +1652,7 @@
 
       if (nb > 4)
         {
-          error ("internal error: received too many bytes for AF_INET type");
+          c_verror ("internal error: received too many bytes for AF_INET type");
 
           return 1;
         }
@@ -1633,7 +1677,7 @@
 
       if (nb > 16)
         {
-          error ("internal error: received too many bytes for AF_INET6 type");
+          c_verror ("internal error: received too many bytes for AF_INET6 type");
 
           return 1;
         }
@@ -1665,13 +1709,16 @@
 
   uint8_t n_mbits;
 
+  bool err;
+
   if (nl == 4 || nl == 5)
     {
-      uint8NDArray a = ov.uint8_array_value ();
-
-      if (error_state)
+      uint8NDArray a;
+      SET_ERR (a = ov.uint8_array_value (), err);
+
+      if (err)
         {
-          error ("can not convert octave_value to network type representation");
+          c_verror ("can not convert octave_value to network type representation");
           return 1;
         }
 
@@ -1689,11 +1736,12 @@
     }
   else if (nl == 8 || nl == 9)
     {
-      uint16NDArray a = ov.uint16_array_value ();
-
-      if (error_state)
+      uint16NDArray a;
+      SET_ERR (a = ov.uint16_array_value (), err);
+
+      if (err)
         {
-          error ("can not convert octave_value to network type representation");
+          c_verror ("can not convert octave_value to network type representation");
           return 1;
         }
 
@@ -1713,7 +1761,7 @@
     }
   else
     {
-      error ("invalid network type representation");
+      c_verror ("invalid network type representation");
       return 1;
     }
 
@@ -1740,7 +1788,7 @@
 
   if (! cidr)
     {
-      error ("internal error: unexpected flag in cidr type");
+      c_verror ("internal error: unexpected flag in cidr type");
 
       return 1;
     }
@@ -1793,7 +1841,7 @@
 
   if (cidr)
     {
-      error ("internal error: unexpected flag in inet type");
+      c_verror ("internal error: unexpected flag in inet type");
 
       return 1;
     }
@@ -1858,17 +1906,19 @@
 int from_octave_bin_macaddr (const octave_pq_connection_rep &conn,
                              const octave_value &ov, oct_pq_dynvec_t &val)
 {
-  uint8NDArray a = ov.uint8_array_value ();
-
-  if (error_state)
+  uint8NDArray a;
+  bool err;
+  SET_ERR (a = ov.uint8_array_value (), err);
+
+  if (err)
     {
-      error ("can not convert octave_value to macaddr representation");
+      c_verror ("can not convert octave_value to macaddr representation");
       return 1;
     }
 
   if (a.numel () != 6)
     {
-      error ("macaddr representation must have 6 elements");
+      c_verror ("macaddr representation must have 6 elements");
       return 1;
     }
 
@@ -1933,20 +1983,27 @@
 int from_octave_bin_bit (const octave_pq_connection_rep &conn,
                          const octave_value &ov, oct_pq_dynvec_t &val)
 {
-  octave_scalar_map tp = ov.scalar_map_value ();
-  if (error_state || ! tp.isfield ("bitlen") || ! tp.isfield ("bits"))
+  octave_scalar_map tp;
+  bool err;
+  SET_ERR (tp = ov.scalar_map_value (), err);
+  if (err || ! tp.isfield ("bitlen") || ! tp.isfield ("bits"))
     {
-      error ("can not convert octave_value to bitstring representation");
+      c_verror ("can not convert octave_value to bitstring representation");
       return 1;
     }
 
-  int32_t nbits = tp.contents ("bitlen").int_value ();
-
-  uint8NDArray a = tp.contents ("bits").uint8_array_value ();
-
-  if (error_state || nbits < 0)
+  int32_t nbits;
+  SET_ERR (nbits = tp.contents ("bitlen").int_value (), err);
+
+  uint8NDArray a;
+  if (! err)
     {
-      error ("can not convert octave_value to bitstring representation");
+      SET_ERR (a = tp.contents ("bits").uint8_array_value (), err);
+    }
+
+  if (err || nbits < 0)
+    {
+      c_verror ("can not convert octave_value to bitstring representation");
       return 1;
     }
 
@@ -1954,7 +2011,7 @@
 
   if (a.numel () != nbytes)
     {
-      error ("wrong number of elements in bitstring representation");
+      c_verror ("wrong number of elements in bitstring representation");
       return 1;
     }
 
@@ -2029,17 +2086,19 @@
 int from_octave_bin_uuid (const octave_pq_connection_rep &conn,
                           const octave_value &ov, oct_pq_dynvec_t &val)
 {
-  uint8NDArray b = ov.uint8_array_value ();
-
-  if (error_state)
+  uint8NDArray b;
+  bool err;
+  SET_ERR (b = ov.uint8_array_value (), err);
+
+  if (err)
     {
-      error ("can not convert octave_value to uuid representation");
+      c_verror ("can not convert octave_value to uuid representation");
       return 1;
     }
 
   if (b.numel () != 16)
     {
-      error ("uuid representation must have 16 elements");
+      c_verror ("uuid representation must have 16 elements");
       return 1;
     }
 
@@ -2091,11 +2150,13 @@
 int from_octave_bin_xml (const octave_pq_connection_rep &conn,
                          const octave_value &ov, oct_pq_dynvec_t &val)
 {
-  std::string s = ov.string_value ();
-
-  if (error_state)
+  std::string s;
+  bool err;
+  SET_ERR (s = ov.string_value (), err);
+
+  if (err)
     {
-      error ("can not convert octave_value to string");
+      c_verror ("can not convert octave_value to string");
       return 1;
     }
 
@@ -2180,7 +2241,7 @@
 
             default:
               // should not get here
-              error ("'record' converter: internal error, undefined type identifier");
+              c_verror ("'record' converter: internal error, undefined type identifier");
               return 1;
             }
 
@@ -2204,7 +2265,7 @@
 int from_octave_bin_record (const octave_pq_connection_rep &conn,
                             const octave_value &ov, oct_pq_dynvec_t &val)
 {
-  error ("Type 'record' can't be sent to postgresql.");
+  c_verror ("Type 'record' can't be sent to postgresql.");
 
   return 1;
 }
--- a/main/database/src/converters_arr_comp.cc	Fri Feb 26 15:07:46 2016 +0000
+++ b/main/database/src/converters_arr_comp.cc	Sat Feb 27 11:11:04 2016 +0000
@@ -26,10 +26,11 @@
 
 #include "converters.h"
 #include "pq_connection.h"
+#include "error-helpers.h"
 
 #define ERROR_RETURN_NO_PG_TYPE                                         \
  {                                                                      \
-   error ("could not determine postgresql type for Octave parameter");  \
+   c_verror ("could not determine postgresql type for Octave parameter"); \
    return NULL;                                                         \
  }
 
@@ -55,8 +56,11 @@
 
   if ((iter = conn.name_conv_map.find (name.c_str ())) ==
       conn.name_conv_map.end ())
-    error ("no converter found for type %s",
-           name.c_str ());
+    {
+      c_verror ("no converter found for type %s",
+                name.c_str ());
+      return NULL;
+    }
   else
     {
       // printf ("(looked up in name map) ");
@@ -65,8 +69,8 @@
 
       if (oct_type == array && ! conv->aoid)
         {
-          error ("%s: internal error, type %s, specified as array, has no array type in system catalog", name.c_str ());
-          return conv;
+          c_verror ("%s: internal error, type %s, specified as array, has no array type in system catalog", name.c_str ());
+          return NULL;
         }
 
       if (! (oct_type == array) && conv->is_composite)
@@ -93,8 +97,8 @@
   
   if ((iter = conn.conv_map.find (oid)) == conn.conv_map.end ())
     {
-      error ("no converter found for element oid %u", oid);
-      return conv;
+      c_verror ("no converter found for element oid %u", oid);
+      return NULL;
     }
   conv = iter->second.get_copy ();
   // printf ("(looked up %s in oid map) ", conv->name.c_str ());
@@ -273,24 +277,32 @@
                            const octave_value &oct_arr,
                            oct_pq_dynvec_t &val, oct_pq_conv_t *conv)
 {
-  octave_scalar_map m = oct_arr.scalar_map_value ();
-  if (error_state)
+  octave_scalar_map m;
+  bool err;
+  SET_ERR (m= oct_arr.scalar_map_value (), err);
+  if (err)
     {
-      error ("Postgresql array parameter no Octave structure");
+      c_verror ("Postgresql array parameter no Octave structure");
       return 1;
     }
 
   if (! m.isfield ("ndims") || ! m.isfield ("data"))
     {
-      error ("field 'ndims' or 'data' missing in parameter for Postgresql array");
+      c_verror ("field 'ndims' or 'data' missing in parameter for Postgresql array");
       return 1;
     }
 
-  octave_idx_type nd_pq = m.contents ("ndims").int_value ();
-  Cell arr = m.contents ("data").cell_value ();
-  if (error_state || nd_pq < 0)
+  octave_idx_type nd_pq;
+  SET_ERR (nd_pq = m.contents ("ndims").int_value (), err);
+
+  Cell arr;
+  if (! err)
     {
-      error ("'ndims' and 'data' could not be converted to non-negative integer and cell-array in parameter for Postgresql array");
+      SET_ERR (arr = m.contents ("data").cell_value (), err);
+    }
+  if (err || nd_pq < 0)
+    {
+      c_verror ("'ndims' and 'data' could not be converted to non-negative integer and cell-array in parameter for Postgresql array");
       return 1;
     }
 
@@ -299,10 +311,10 @@
   // Are lbounds given?
   if (m.isfield ("lbounds"))
     {
-      lb = m.contents ("lbounds").row_vector_value ();
-      if (error_state)
+      SET_ERR (lb = m.contents ("lbounds").row_vector_value (), err);
+      if (err)
         {
-          error ("could not convert given enumeration bases for array to row vector");
+          c_verror ("could not convert given enumeration bases for array to row vector");
           return 1;
         }
     }
@@ -319,16 +331,16 @@
   // check dimensions
   if (nd_oct > nd_pq)
     {
-      error ("given representation of postgresql array has more dimensions than specified");
+      c_verror ("given representation of postgresql array has more dimensions than specified");
       return 1;
     }
 
   // check lbounds
   if (nd_pq > 0 && lb.is_empty ())
     lb.resize (nd_pq, 1); // fill with 1
-  else if (lb.length () != nd_pq)
+  else if (lb.numel () != nd_pq)
     {
-      error ("number of specified enumeration bases for array does not match specified number of dimensions");
+      c_verror ("number of specified enumeration bases for array does not match specified number of dimensions");
       return 1;
     }
 
@@ -382,10 +394,12 @@
                                oct_pq_dynvec_t &val,
                                oct_pq_conv_t *conv)
 {
-  Cell rec (oct_comp.cell_value ());
-  if (error_state)
+  Cell rec;
+  bool err;
+  SET_ERR (rec = oct_comp.cell_value (), err);
+  if (err)
     {
-      error ("Octaves representation of a composite type could not be converted to cell-array");
+      c_verror ("Octaves representation of a composite type could not be converted to cell-array");
       return 1;
     }
 
@@ -393,7 +407,7 @@
 
   if (size_t (nl) != conv->el_oids.size ())
     {
-      error ("Octaves representation of a composite type has incorrect number of elements (%i, should have %i)",
+      c_verror ("Octaves representation of a composite type has incorrect number of elements (%i, should have %i)",
              nl, conv->el_oids.size ());
 
       return 1;
@@ -442,7 +456,7 @@
 
             default:
               // should not get here
-              error ("internal error, undefined type identifier");
+              c_verror ("internal error, undefined type identifier");
               return 1;
             }
 
@@ -458,7 +472,7 @@
                            oct_pq_dynvec_t &val, octave_value &type)
 {
   // not implemented
-  error ("not implemented");
+  c_verror ("not implemented");
   return 1;
 
   return 0;
@@ -470,7 +484,7 @@
                                octave_value &type)
 {
   // not implemented
-  error ("not implemented");
+  c_verror ("not implemented");
   return 1;
 
   return 0;
@@ -496,7 +510,7 @@
   // check element OID
   if (oid != conv->oid)
     {
-      error ("element oid %i sent by server does not match element oid %i expected for array with oid %i",
+      c_verror ("element oid %i sent by server does not match element oid %i expected for array with oid %i",
              oid, conv->oid, conv->aoid);
       return 1;
     }
@@ -613,7 +627,7 @@
 
             default:
               // should not get here
-              error ("internal error, undefined type identifier");
+              c_verror ("internal error, undefined type identifier");
               return 1;
             }
 
@@ -634,7 +648,7 @@
                          oct_pq_conv_t *conv)
 {
   // not implemented
-  error ("not implemented");
+  c_verror ("not implemented");
   return 1;
 
   return 0;
@@ -645,7 +659,7 @@
                              oct_pq_conv_t *conv)
 {
   // not implemented
-  error ("not implemented");
+  c_verror ("not implemented");
   return 1;
 
   return 0;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main/database/src/error-helpers.cc	Sat Feb 27 11:11:04 2016 +0000
@@ -0,0 +1,53 @@
+/*
+
+Copyright (C) 2016 Olaf Till <i7tiol@t-online.de>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include <octave/oct.h>
+
+#include "error-helpers.h"
+
+// call verror
+#ifdef HAVE_OCTAVE_VERROR_ARG_EXC
+void
+c_verror (octave_execution_exception& e, const char *fmt, ...)
+{
+  va_list args;
+  va_start (args, fmt);
+  verror (e, fmt, args);
+  va_end (args);
+}
+#else
+void
+c_verror (const octave_execution_exception&, const char *fmt, ...)
+{
+  va_list args;
+  va_start (args, fmt);
+  verror (fmt, args);
+  va_end (args);
+}
+#endif
+
+// call verror
+void
+c_verror (const char *fmt, ...)
+{
+  va_list args;
+  va_start (args, fmt);
+  verror (fmt, args);
+  va_end (args);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main/database/src/error-helpers.h	Sat Feb 27 11:11:04 2016 +0000
@@ -0,0 +1,137 @@
+/*
+
+Copyright (C) 2016 Olaf Till <i7tiol@t-online.de>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "config.h"
+
+// call verror
+#ifdef HAVE_OCTAVE_VERROR_ARG_EXC
+void c_verror (octave_execution_exception&, const char *, ...);
+#else
+void c_verror (const octave_execution_exception&, const char *, ...);
+#endif
+
+// call verror
+void c_verror (const char *fmt, ...);
+
+// Print a message if 'code' causes an error and raise an error again,
+// both if Octave uses exceptions for errors and if it still uses
+// error_state. In the latter case return 'retval'.
+#ifdef HAVE_OCTAVE_ERROR_STATE
+  // can throw octave_execution_exception despite of this
+  #define CHECK_ERROR(code, retval, ...)      \
+    try \
+      { \
+        code ; \
+ \
+        if (error_state) \
+          { \
+            error (__VA_ARGS__); \
+ \
+            return retval; \
+          } \
+      } \
+    catch (octave_execution_exception& e) \
+      { \
+        c_verror (e, __VA_ARGS__); \
+ \
+        throw e; \
+      }
+#else
+  #define CHECK_ERROR(code, retval, ...) \
+    try \
+      { \
+        code ; \
+      } \
+    catch (octave_execution_exception& e) \
+      { \
+        c_verror (e, __VA_ARGS__); \
+ \
+        throw e; \
+      }
+#endif
+
+// If 'code' causes an error, print a message and call exit(1) if
+// Octave doesn't throw exceptions for errors but still uses
+// error_state.
+#ifdef HAVE_OCTAVE_ERROR_STATE
+  // can throw octave_execution_exception despite of this
+  #define CHECK_ERROR_EXIT1(code, ...) \
+    try \
+      { \
+        code ; \
+ \
+        if (error_state) \
+          { \
+            c_verror (__VA_ARGS__); \
+ \
+            exit (1); \
+          } \
+      } \
+    catch (octave_execution_exception& e) \
+      { \
+        c_verror (e, __VA_ARGS__); \
+ \
+        exit (1); \
+      }
+#else
+  #define CHECK_ERROR_EXIT1(code, ...) \
+    try \
+      { \
+        code ; \
+      } \
+    catch (octave_execution_exception& e) \
+      { \
+        c_verror (e, __VA_ARGS__); \
+ \
+        exit (1); \
+      }
+#endif
+
+// Set 'err' to true if 'code' causes an error, else to false; both if
+// Octave uses exceptions for errors and if it still uses
+// error_state. In the latter case reset error_state to 0.
+#ifdef HAVE_OCTAVE_ERROR_STATE
+  // can throw octave_execution_exception despite of this
+  #define SET_ERR(code, err) \
+    err = false; \
+ \
+    try \
+      { \
+        code ; \
+        if (error_state) \
+          { \
+            error_state = 0; \
+            err = true; \
+          } \
+      } \
+    catch (octave_execution_exception&) \
+      { \
+        err = true; \
+      }
+#else
+  #define SET_ERR(code, err) \
+    try \
+      { \
+        code ; \
+      } \
+    catch (octave_execution_exception&) \
+      { \
+        err = true; \
+      }
+#endif
--- a/main/database/src/pq_connection.cc	Fri Feb 26 15:07:46 2016 +0000
+++ b/main/database/src/pq_connection.cc	Sat Feb 27 11:11:04 2016 +0000
@@ -19,6 +19,7 @@
 
 #include "pq_connection.h"
 #include "command.h"
+#include "error-helpers.h"
 
 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_pq_connection, "PGconn", "PGconn")
 
@@ -57,7 +58,7 @@
     {
       if (conn)
         {
-          error ("%s", PQerrorMessage (conn));
+          c_verror ("%s", PQerrorMessage (conn));
 
           PGconn *t_conn = conn;
 
@@ -68,7 +69,7 @@
           END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
         }
 
-      error ("PQ connection attempt failed");
+      c_verror ("PQ connection attempt failed");
     }
   else
     {
@@ -94,7 +95,7 @@
           PQfinish (t_conn);
           END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
 
-          error ("could not read types");
+          c_verror ("could not read types");
         }
       else
         {
@@ -133,6 +134,9 @@
       octave_pq_delete_non_constant_types ();
     }
   else
+    // deliberately left the 'error' call here, since
+    // 'octave_pq_close()' is only called by 'pq_close' immediately
+    // before returning
     error ("PGconn object not open");
 }
 
@@ -189,17 +193,17 @@
   command c (*this, cmd, p, pt, rt, caller);
   if (! c.good ())
     {
-      error ("could not read pg_roles");
+      c_verror ("could not read pg_roles");
       return 1;
     }
 
   octave_value res = c.process_single_result ();
-  if (error_state)
+  if (! c.good ())
     return 1;
 
-  postgres = res.scalar_map_value ().contents ("data").cell_value ()(0).
-    int_value ();
-  if (error_state)
+  bool err;
+  SET_ERR (postgres = res.scalar_map_value ().contents ("data").cell_value ()(0).int_value (), err);
+  if (err)
     return 1;
 
   return 0;
@@ -223,18 +227,21 @@
   command c (*this, cmd, p, pt, rt, caller);
   if (! c.good ())
     {
-      error ("octave_pq_fill_base_types: could not read pg_type");
+      c_verror ("octave_pq_fill_base_types: could not read pg_type");
       return 1;
     }
 
   octave_value res = c.process_single_result ();
-  if (error_state)
+  if (! c.good ())
     return 1;
 
-  Cell tpls = res.scalar_map_value ().contents ("data").cell_value ();
-  if (error_state)
+  Cell tpls;
+  bool err;
+  SET_ERR (tpls = res.scalar_map_value ().contents ("data").cell_value (),
+           err);
+  if (err)
     {
-      error
+      c_verror
         ("octave_pq_fill_base_types: could not convert result data to cell");
       return 1;
     }
@@ -245,10 +252,14 @@
     bt_map_t;
   bt_map_t bt_map (&map_string_cmp);
   for (int i = 0; i < tpls.rows (); i++)
-    bt_map[tpls(i, 1).string_value ()] = i;
-  if (error_state)
     {
-      error ("octave_pq_fill_base_types: could not read returned result");
+      SET_ERR (bt_map[tpls(i, 1).string_value ()] = i, err);
+      if (err)
+        break;
+    }
+  if (err)
+    {
+      c_verror ("octave_pq_fill_base_types: could not read returned result");
       return 1;
     }
 
@@ -258,13 +269,19 @@
       if ((bt_it = bt_map.find (conv_ptrs[i]->name.c_str () + pq_bpl)) ==
           bt_map.end ())
         {
-          error ("octave_pq_fill_base_types: type %s not found in pg_type",
-                 conv_ptrs[i]->name.c_str () + pq_bpl);
+          c_verror ("octave_pq_fill_base_types: type %s not found in pg_type",
+                    conv_ptrs[i]->name.c_str () + pq_bpl);
           return 1;
         }
       // fill in oid and aoid into static records of converters
-      conv_ptrs[i]->oid = tpls(bt_it->second, 0).int_value ();
-      conv_ptrs[i]->aoid = tpls(bt_it->second, 2).int_value ();
+      SET_ERR (conv_ptrs[i]->oid = tpls(bt_it->second, 0).int_value (), err);
+      if (! err)
+        {
+          SET_ERR (conv_ptrs[i]->aoid = tpls(bt_it->second, 2).int_value (),
+                   err);
+        }
+      if (err)
+        break;
 
       // fill in map of converters over oid with oid and, if not zero,
       // also with aoid
@@ -272,9 +289,9 @@
       if (conv_ptrs[i]->aoid != 0)
         conv_map[conv_ptrs[i]->aoid] = conv_ptrs[i];
     }
-  if (error_state)
+  if (err)
     {
-      error ("octave_pq_fill_base_types: could not read returned result");
+      c_verror ("octave_pq_fill_base_types: could not read returned result");
       return 1;
     }
 
@@ -291,41 +308,69 @@
   command c (*this, cmd, p, pt, rt, caller);
   if (! c.good ())
     {
-      error ("octave_pq_get_composite_types: could not read pg_type");
+      c_verror ("octave_pq_get_composite_types: could not read pg_type");
       return 1;
     }
 
   octave_value res = c.process_single_result ();
-  if (error_state)
+  if (! c.good ())
     return 1;
 
-  Cell tpls = res.scalar_map_value ().contents ("data").cell_value ();
-  if (error_state)
+  Cell tpls;
+  bool err;
+  SET_ERR (tpls = res.scalar_map_value ().contents ("data").cell_value (),
+           err)
+  if (err)
     {
-      error ("octave_pq_get_composite_types: could not convert result data to cell");
+      c_verror ("octave_pq_get_composite_types: could not convert result data to cell");
       return 1;
     }
 
   for (int i = 0; i < tpls.rows (); i++)
     {
-      Oid oid = tpls(i, 0).uint_value ();
-      Oid aoid = tpls(i, 2).uint_value ();
-      std::string name = tpls(i, 1).string_value ();
-      std::string nspace = tpls(i, 3).string_value ();
-      bool visible = tpls(i, 4).bool_value ();
-      Cell r_el_oids =
-        tpls(i, 5).scalar_map_value ().contents ("data").cell_value ();
-      Cell r_el_pos =
-        tpls(i, 6).scalar_map_value ().contents ("data").cell_value ();
-      if (error_state)
+      Oid oid;
+      SET_ERR (oid = tpls(i, 0).uint_value (), err);
+      Oid aoid;
+      if (! err)
+        {
+          SET_ERR (aoid = tpls(i, 2).uint_value (), err);
+        }
+      std::string name;
+      if (! err)
+        {
+          SET_ERR (name = tpls(i, 1).string_value (), err);
+        }
+      std::string nspace;
+      if (! err)
         {
-          error ("octave_pq_get_composite_types: could not read returned result");
+          SET_ERR (nspace = tpls(i, 3).string_value (), err);
+        }
+      bool visible;
+      if (! err)
+        {
+          SET_ERR (visible = tpls(i, 4).bool_value (), err);
+        }
+      Cell r_el_oids;
+      if (! err)
+        {
+          SET_ERR (r_el_oids = tpls(i, 5).scalar_map_value ()
+                   .contents ("data").cell_value (), err);
+        }
+      Cell r_el_pos;
+      if (! err)
+        {
+          SET_ERR (r_el_pos = tpls(i, 6).scalar_map_value ()
+                   .contents ("data").cell_value (), err);
+        }
+      if (err)
+        {
+          c_verror ("octave_pq_get_composite_types: could not read returned result");
           return 1;
         }
       octave_idx_type nel = r_el_oids.numel ();
       if (nel != r_el_pos.numel ())
         {
-          error ("octave_pq_get_composite_types: internal error, inconsistent content of pg_attribute?");
+          c_verror ("octave_pq_get_composite_types: internal error, inconsistent content of pg_attribute?");
 
           return 1;
         }
@@ -335,27 +380,28 @@
       conv_cache.resize (nel);
       for (octave_idx_type i = 0; i < nel; i++)
         {
+          octave_idx_type pos;
           // "column" number (attnum) is one-based, so subtract 1
-          octave_idx_type pos = r_el_pos(i).idx_type_value () - 1;
-          if (! error_state)
+          SET_ERR (pos = r_el_pos(i).idx_type_value () - 1, err);
+          if (! err)
             {
               if (pos >= nel)
                 {
-                  error ("octave_pq_get_composite_types: internal error (?system catalog erroneous?): column position %i greater than ncols %i for type %s, namespace %s",
+                  c_verror ("octave_pq_get_composite_types: internal error (?system catalog erroneous?): column position %i greater than ncols %i for type %s, namespace %s",
                          pos, nel, name.c_str (), nspace.c_str ());
                   return 1;
                 }
 
-              el_oids[pos] = r_el_oids(i).uint_value ();
+              SET_ERR (el_oids[pos] = r_el_oids(i).uint_value (), err);
 
               conv_cache[pos] = NULL;
             }
-        }
-      if (error_state)
-        {
-          error ("octave_pq_get_composite_types: could not fill in element oids.");
+          if (err)
+            {
+              c_verror ("octave_pq_get_composite_types: could not fill in element oids.");
 
-          return 1;
+              return 1;
+            }
         }
 
       // must be allocated and filled before creating the name map
@@ -379,7 +425,7 @@
         *&by_name = name_conv_map[t_conv->name.c_str ()];
       if (by_oid || by_name)
         {
-          error ("octave_pq_get_composite_types: internal error, key already in typemap (by_oid: %u/%li, by name: %s/%li)",
+          c_verror ("octave_pq_get_composite_types: internal error, key already in typemap (by_oid: %u/%li, by name: %s/%li)",
                  oid, by_oid, t_conv->name.c_str (), by_name);
           if (! by_oid) conv_map.erase (oid);
           if (! by_name) name_conv_map.erase (t_conv->name.c_str ());
@@ -410,7 +456,7 @@
           oct_pq_conv_t *&by_aoid = conv_map[aoid];
           if (by_aoid)
             {
-              error ("octave_pq_get_composite_types: internal error, aoid key %u already in typemap", aoid);
+              c_verror ("octave_pq_get_composite_types: internal error, aoid key %u already in typemap", aoid);
               conv_map.erase (oid);
               name_conv_map.erase (t_conv->name.c_str ());
               delete t_conv;
@@ -440,31 +486,51 @@
   command c (*this, cmd, p, pt, rt, caller);
   if (! c.good ())
     {
-      error ("octave_pq_get_enum_types: could not read pg_type");
+      c_verror ("octave_pq_get_enum_types: could not read pg_type");
       return 1;
     }
  
   octave_value res = c.process_single_result ();
-  if (error_state)
+  if (! c.good ())
     return 1;
 
-  Cell tpls = res.scalar_map_value ().contents ("data").cell_value ();
-  if (error_state)
+  Cell tpls;
+  bool err;
+  SET_ERR (tpls = res.scalar_map_value ().contents ("data").cell_value (),
+           err);
+  if (err)
     {
-      error ("octave_pq_get_enum_types: could not convert result data to cell");
+      c_verror ("octave_pq_get_enum_types: could not convert result data to cell");
       return 1;
     }
 
   for (int i = 0; i < tpls.rows (); i++)
     {
-      Oid oid = tpls(i, 0).uint_value ();
-      Oid aoid = tpls(i, 2).uint_value ();
-      std::string name = tpls(i, 1).string_value ();
-      std::string nspace = tpls(i, 3).string_value ();
-      bool visible = tpls(i, 4).bool_value ();
-      if (error_state)
+      Oid oid;
+      SET_ERR (oid = tpls(i, 0).uint_value (), err);
+      Oid aoid;
+      if (! err)
+        {
+          SET_ERR (aoid = tpls(i, 2).uint_value (), err);
+        }      
+      std::string name;
+      if (! err)
         {
-          error ("octave_pq_get_enum_types: could not read returned result");
+          SET_ERR (name = tpls(i, 1).string_value (), err);
+        }
+      std::string nspace;
+      if (! err)
+        {
+          SET_ERR (nspace = tpls(i, 3).string_value (), err);
+        }
+      bool visible;
+      if (! err)
+        {
+          SET_ERR (visible = tpls(i, 4).bool_value (), err);
+        }
+      if (err)
+        {
+          c_verror ("octave_pq_get_enum_types: could not read returned result");
           return 1;
         }
 
@@ -490,7 +556,7 @@
         *&by_name = name_conv_map[t_conv->name.c_str ()];
       if (by_oid || by_aoid || by_name)
         {
-          error ("octave_pq_get_enum_types: internal error, key already in typemap");
+          c_verror ("octave_pq_get_enum_types: internal error, key already in typemap");
           if (! by_oid) conv_map.erase (oid);
           if (! by_aoid) conv_map.erase (aoid);
           if (! by_name) name_conv_map.erase (t_conv->name.c_str ());
@@ -539,7 +605,7 @@
           END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE;
         }
 
-      error ("octave_pq_refresh_types: could not read types");
+      c_verror ("octave_pq_refresh_types: could not read types");
       return 1;
     }
   else
--- a/main/database/src/pq_conninfo.cc	Fri Feb 26 15:07:46 2016 +0000
+++ b/main/database/src/pq_conninfo.cc	Sat Feb 27 11:11:04 2016 +0000
@@ -20,6 +20,7 @@
 #include <octave/oct.h>
 
 #include "pq_connection.h"
+#include "error-helpers.h"
 
 // PKG_ADD: autoload ("pq_conninfo", "pq_interface.oct");
 // PKG_DEL: autoload ("pq_conninfo", "pq_interface.oct", "remove");
@@ -42,15 +43,10 @@
       return retval;
     }
 
-  std::string label (args(1).string_value ());
-
-  if (error_state)
-    {
-      error ("%s: second argument can not be converted to a string",
-             fname.c_str ());
-
-      return retval;
-    }
+  std::string label;
+  CHECK_ERROR (label = args(1).string_value (), retval,
+               "%s: second argument can not be converted to a string",
+               fname.c_str ());
 
   if (label.compare ("integer_datetimes"))
     {
--- a/main/database/src/pq_exec.cc	Fri Feb 26 15:07:46 2016 +0000
+++ b/main/database/src/pq_exec.cc	Sat Feb 27 11:11:04 2016 +0000
@@ -23,6 +23,7 @@
 #include <octave/Cell.h>
 
 #include "command.h"
+#include "error-helpers.h"
 
 // PKG_disabled_ADD: autoload ("pq_exec", "pq_interface.oct");
 // PKG_disabled_DEL: autoload ("pq_exec", "pq_interface.oct", "remove");
@@ -122,14 +123,10 @@
       return retval;
     }
 
-  std::string cmd (args(1).string_value ());
-
-  if (error_state)
-    {
-      error ("%s: second argument can not be converted to a string", fname.c_str ());
-
-      return retval;
-    }
+  std::string cmd;
+  CHECK_ERROR (cmd = args(1).string_value (), retval,
+               "%s: second argument can not be converted to a string",
+               fname.c_str ());
 
   const octave_base_value &rep = args(0).get_rep ();
 
@@ -162,14 +159,20 @@
 
   octave_scalar_map settings;
 
+  bool err;
+
   if (nargs == 3)
     {
       if (args(2).is_cell ())
-        params = args(2).cell_value ();
+        {
+          SET_ERR (params = args(2).cell_value (), err);
+        }
       else
-        settings = args(2).scalar_map_value ();
+        {
+          SET_ERR (settings = args(2).scalar_map_value (), err);
+        }
 
-      if (error_state)
+      if (err)
         {
           error ("%s: third argument neither cell-array nor scalar structure",
                  fname.c_str ());
@@ -179,24 +182,14 @@
     }
   else if (nargs == 4)
     {
-      params = args(2).cell_value ();
-      if (error_state)
-        {
-          error ("%s: could not convert third argument to cell-array",
-                 fname.c_str ());
-
-          return retval;
-        }
-      settings = args(3).scalar_map_value ();
-      if (error_state)
-        {
-          error ("%s: could not convert fourth argument to scalar structure");
-
-          return retval;
-        }
+      CHECK_ERROR (params = args(2).cell_value (), retval,
+                   "%s: could not convert third argument to cell-array",
+                   fname.c_str ());
+      CHECK_ERROR (settings = args(3).scalar_map_value (), retval,
+                   "%s: could not convert fourth argument to scalar structure");
     }
 
-  int nparams = params.length ();
+  int nparams = params.numel ();
 
   dim_vector pdims = params.dims ();
 
@@ -218,97 +211,72 @@
   f_args(1) = octave_value ("param_types");
   f_args(2) = octave_value (Cell (1, nparams));
 
-  f_ret = feval ("getdbopts", f_args, 1);
-  Cell ptypes = f_ret(0).cell_value ();
-  if (error_state)
-    {
-      error ("%s: could not convert param_types to cell",
-             fname.c_str ());
-
-      return retval;
-    }
+  CHECK_ERROR (f_ret = feval ("getdbopts", f_args, 1), retval,
+               "%s: error calling getdbopts",
+               fname.c_str ());
+  Cell ptypes;
+  CHECK_ERROR (ptypes = f_ret(0).cell_value (), retval,
+               "%s: could not convert param_types to cell", fname.c_str ());
 
   f_args(1) = octave_value ("copy_in_path");
   f_args(2) = octave_value ("");
 
-  f_ret = feval ("getdbopts", f_args, 1);
-  std::string cin_path = f_ret(0).string_value ();
-  if (error_state)
-    {
-      error ("%s: could not convert copy_in_path to string",
-             fname.c_str ());
-
-      return retval;
-    }
+  CHECK_ERROR (f_ret = feval ("getdbopts", f_args, 1), retval,
+               "%s: error calling getdbopts", fname.c_str ());
+  std::string cin_path;
+  CHECK_ERROR (cin_path = f_ret(0).string_value (), retval,
+               "%s: could not convert copy_in_path to string", fname.c_str ());
 
   f_args(1) = octave_value ("copy_out_path");
   f_args(2) = octave_value ("");
 
-  f_ret = feval ("getdbopts", f_args, 1);
-  std::string cout_path = f_ret(0).string_value ();
-  if (error_state)
-    {
-      error ("%s: could not convert copy_out_path to string",
-             fname.c_str ());
-
-      return retval;
-    }
+  CHECK_ERROR (f_ret = feval ("getdbopts", f_args, 1), retval,
+               "%s: error calling getdbopts", fname.c_str ());
+  std::string cout_path;
+  CHECK_ERROR (cout_path = f_ret(0).string_value (), retval,
+               "%s: could not convert copy_out_path to string", fname.c_str ());
 
   f_args(1) = octave_value ("copy_in_data");
   f_args(2) = octave_value (Cell ());
 
-  f_ret = feval ("getdbopts", f_args, 1);
-  Cell cin_data = f_ret(0).cell_value ();
-  if (error_state)
-    {
-      error ("%s: could not convert copy_in_data to cell",
-             fname.c_str ());
-
-      return retval;
-    }
+  CHECK_ERROR (f_ret = feval ("getdbopts", f_args, 1), retval,
+               "%s: error calling getdbopts", fname.c_str ());
+  Cell cin_data;
+  CHECK_ERROR (cin_data = f_ret(0).cell_value (), retval,
+               "%s: could not convert copy_in_data to cell", fname.c_str ());
 
   f_args(1) = octave_value ("copy_in_with_oids");
   f_args(2) = octave_value (false);
 
-  f_ret = feval ("getdbopts", f_args, 1);
-  bool cin_with_oids = f_ret(0).bool_value ();
-  if (error_state)
-    {
-      error ("%s: could not convert copy_in_with_oids to bool",
-             fname.c_str ());
-
-      return retval;
-    }
+  CHECK_ERROR (f_ret = feval ("getdbopts", f_args, 1), retval,
+               "%s: error calling getdbopts", fname.c_str ());
+  bool cin_with_oids;
+  CHECK_ERROR (cin_with_oids = f_ret(0).bool_value (), retval,
+               "%s: could not convert copy_in_with_oids to bool",
+               fname.c_str ());
 
   f_args(1) = octave_value ("copy_in_types");
   f_args(2) = octave_value (Cell ());
 
-  f_ret = feval ("getdbopts", f_args, 1);
-  Cell cin_types = f_ret(0).cell_value ();
-  if (error_state)
-    {
-      error ("%s: could not convert copy_in_types to cell",
-             fname.c_str ());
-
-      return retval;
-    }
+  CHECK_ERROR (f_ret = feval ("getdbopts", f_args, 1), retval,
+               "%s: error calling getdbopts", fname.c_str ());
+  Cell cin_types;
+  CHECK_ERROR (cin_types = f_ret(0).cell_value (), retval,
+               "%s: could not convert copy_in_types to cell", fname.c_str ());
 
   f_args(1) = octave_value ("copy_in_from_variable");
   f_args(2) = octave_value (false);
 
-  f_ret = feval ("getdbopts", f_args, 1);
-  bool cin_from_variable = f_ret(0).bool_value ();
-  if (error_state)
-    {
-      error ("%s: could not convert copy_in_from_variable to bool",
-             fname.c_str ());
-
-      return retval;
-    }
+  CHECK_ERROR (f_ret = feval ("getdbopts", f_args, 1), retval,
+               "%s: error calling getdbopts", fname.c_str ());
+  bool cin_from_variable;
+  CHECK_ERROR (cin_from_variable = f_ret(0).bool_value (), retval,
+               "%s: could not convert copy_in_from_variable to bool",
+               fname.c_str ());
 
   // check option settings
 
-  if (ptypes.length () != nparams)
+  if (ptypes.numel () != nparams)
     {
       error ("%s: if given, cell-array of parameter types must have same length as cell-array of parameters",
              fname.c_str ());
@@ -345,5 +313,8 @@
       (cin_path, cout_path, cin_data, cin_types, cin_with_oids,
        cin_from_variable);
 
+  if (! c.good ())
+    error ("%s: error processing result", fname.c_str ());
+
   return retval;
 }
--- a/main/database/src/pq_lo.cc	Fri Feb 26 15:07:46 2016 +0000
+++ b/main/database/src/pq_lo.cc	Sat Feb 27 11:11:04 2016 +0000
@@ -24,6 +24,7 @@
 #include <stdio.h>
 
 #include "command.h"
+#include "error-helpers.h"
 #include <libpq/libpq-fs.h>
 
 // PKG_ADD: autoload ("pq_lo_import", "pq_interface.oct");
@@ -128,7 +129,7 @@
   if (nb) return;
 
   if (pclose (fp) == -1)
-    error ("error closing pipe");
+    c_verror ("error closing pipe");
 
   fp = NULL;
 
@@ -145,7 +146,7 @@
   if (lod != -1)
     {
       if (lo_close (conn, lod))
-        error ("%s", PQerrorMessage (conn));
+        c_verror ("%s", PQerrorMessage (conn));
 
       lod = -1;
     }
@@ -153,7 +154,7 @@
   if (oid && ! oid_valid)
     {
       if (lo_unlink (conn, oid) == -1)
-        error ("error unlinking new large object with oid %i", oid);
+        c_verror ("error unlinking new large object with oid %i", oid);
     }
   else
     oid = 0;
@@ -161,7 +162,7 @@
   if (fp)
     {
       if (pclose (fp) == -1)
-        error ("error closing pipe");
+        c_verror ("error closing pipe");
 
       fp = NULL;
     }
@@ -179,7 +180,7 @@
         c.process_single_result ();
 
       if (! c.good ())
-        error ("pq_lo_import: could not commit");
+        c_verror ("%s: could not commit", caller.c_str ());
     }
 }
 
@@ -269,7 +270,7 @@
   if (pnb) return;
 
   if (pclose (fp) == -1)
-    error ("error closing pipe");
+    c_verror ("error closing pipe");
 
   fp = NULL;
 
@@ -286,7 +287,7 @@
   if (lod != -1)
     {
       if (lo_close (conn, lod))
-        error ("%s", PQerrorMessage (conn));
+        c_verror ("%s", PQerrorMessage (conn));
 
       lod = -1;
     }
@@ -294,7 +295,7 @@
   if (fp)
     {
       if (pclose (fp) == -1)
-        error ("error closing pipe");
+        c_verror ("error closing pipe");
 
       fp = NULL;
     }
@@ -312,7 +313,7 @@
         c.process_single_result ();
 
       if (! c.good ())
-        error ("pq_lo_export: could not commit");
+        c_verror ("%s: could not commit", caller.c_str ());
     }
 }
 
@@ -334,15 +335,10 @@
       return retval;
     }
 
-  std::string path (args(1).string_value ());
-
-  if (error_state)
-    {
-      error ("%s: second argument can not be converted to a string",
-             fname.c_str ());
-
-      return retval;
-    }
+  std::string path;
+  CHECK_ERROR (path = args(1).string_value (), retval,
+               "%s: second argument can not be converted to a string",
+               fname.c_str ());
 
   bool from_pipe = false;
   unsigned int l = path.size ();
@@ -389,17 +385,15 @@
     case PQTRANS_INERROR:
       error ("%s: can't manipulate large objects within a failed transaction block",
              fname.c_str ());
-      break;
+      return retval;
     case PQTRANS_UNKNOWN:
       error ("%s: connection is bad", fname.c_str ());
-      break;
+      return retval;
     default: // includes PQTRANS_ACTIVE
       error ("%s: unexpected connection state", fname.c_str ());
+      return retval;
     }
 
-  if (error_state)
-    return retval;
-
   if (make_tblock)
     {
       std::string cmd ("begin;");
@@ -459,13 +453,17 @@
     }
 
   if (import_error)
-    error ("%s: large object import failed: %s", fname.c_str (), msg.c_str ());
+    c_verror ("%s: large object import failed: %s",
+              fname.c_str (), msg.c_str ());
 
   if (commit_error)
-    error ("%s: could not commit transaction", fname.c_str ());
+    c_verror ("%s: could not commit transaction", fname.c_str ());
 
-  if (error_state)
-    return retval;
+  if (import_error || commit_error)
+    {
+      error ("%s failed", fname.c_str ());
+      return retval;
+    }
 
   retval = octave_value (octave_uint32 (oid));
 
@@ -491,15 +489,10 @@
       return retval;
     }
 
-  std::string path (args(2).string_value ());
-
-  if (error_state)
-    {
-      error ("%s: third argument can not be converted to a string",
-             fname.c_str ());
-
-      return retval;
-    }
+  std::string path;
+  CHECK_ERROR (path = args(2).string_value (), retval,
+               "%s: third argument can not be converted to a string",
+               fname.c_str ());
 
   bool to_pipe = false;
   if (! path.empty () && path[0] == '|')
@@ -517,15 +510,10 @@
       to_pipe = true;
     }
 
-  Oid oid = args(1).uint_value ();
-
-  if (error_state)
-    {
-      error ("%s: second argument can not be converted to an oid",
-             fname.c_str ());
-
-      return retval;
-    }
+  Oid oid;
+  CHECK_ERROR (oid = args(1).uint_value (), retval,
+               "%s: second argument can not be converted to an oid",
+               fname.c_str ());
 
   const octave_base_value& rep = (args(0).get_rep ());
 
@@ -551,17 +539,15 @@
     case PQTRANS_INERROR:
       error ("%s: can't manipulate large objects within a failed transaction block",
              fname.c_str ());
-      break;
+      return retval;
     case PQTRANS_UNKNOWN:
       error ("%s: connection is bad", fname.c_str ());
-      break;
+      return retval;
     default: // includes PQTRANS_ACTIVE
       error ("%s: unexpected connection state", fname.c_str ());
+      return retval;
     }
 
-  if (error_state)
-    return retval;
-
   if (make_tblock)
     {
       std::string cmd ("begin;");
@@ -617,10 +603,14 @@
     }
 
   if (export_error)
-    error ("%s: large object export failed: %s", fname.c_str (), msg.c_str ());
+    c_verror ("%s: large object export failed: %s",
+              fname.c_str (), msg.c_str ());
 
   if (commit_error)
-    error ("%s: could not commit transaction", fname.c_str ());
+    c_verror ("%s: could not commit transaction", fname.c_str ());
+
+  if (export_error || commit_error)
+    error ("%s failed", fname.c_str ());
 
   return retval;
 }
@@ -644,15 +634,10 @@
       return retval;
     }
 
-  Oid oid = args(1).uint_value ();
-
-  if (error_state)
-    {
-      error ("%s: second argument can not be converted to an oid",
-             fname.c_str ());
-
-      return retval;
-    }
+  Oid oid;
+  CHECK_ERROR (oid = args(1).uint_value (), retval,
+               "%s: second argument can not be converted to an oid",
+               fname.c_str ());
 
   const octave_base_value& rep = (args(0).get_rep ());
 
@@ -678,17 +663,15 @@
     case PQTRANS_INERROR:
       error ("%s: can't manipulate large objects within a failed transaction block",
              fname.c_str ());
-      break;
+      return retval;
     case PQTRANS_UNKNOWN:
       error ("%s: connection is bad", fname.c_str ());
-      break;
+      return retval;
     default: // includes PQTRANS_ACTIVE
       error ("%s: unexpected connection state", fname.c_str ());
+      return retval;
     }
 
-  if (error_state)
-    return retval;
-
   if (make_tblock)
     {
       std::string cmd ("begin;");
@@ -734,10 +717,14 @@
     }
 
   if (unlink_error)
-    error ("%s: large object unlink failed: %s", fname.c_str (), msg.c_str ());
+    c_verror ("%s: large object unlink failed: %s",
+              fname.c_str (), msg.c_str ());
 
   if (commit_error)
-    error ("%s: could not commit transaction", fname.c_str ());
+    c_verror ("%s: could not commit transaction", fname.c_str ());
+
+  if (unlink_error || commit_error)
+    error ("%s failed", fname.c_str ());      
 
   return retval;
 }
--- a/main/database/src/pq_update_types.cc	Fri Feb 26 15:07:46 2016 +0000
+++ b/main/database/src/pq_update_types.cc	Sat Feb 27 11:11:04 2016 +0000
@@ -48,7 +48,8 @@
   const octave_pq_connection &oct_pq_conn =
     dynamic_cast<const octave_pq_connection&> (rep);
 
-  oct_pq_conn.get_rep ()->octave_pq_refresh_types ();
+  if (oct_pq_conn.get_rep ()->octave_pq_refresh_types ())
+    error ("%s failed", fname.c_str ());
 
   return retval;
 }