changeset 11398:913ac5491db1 octave-forge

Copy in/out from/to local file hacked in. Doc change waits till copy in/out from/to variable.
author i7tiol
date Thu, 17 Jan 2013 19:34:11 +0000
parents 8979fcae5e7d
children bd929f2c00ec
files main/database/src/command.cc main/database/src/command.h main/database/src/pq_exec.cc
diffstat 3 files changed, 247 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/main/database/src/command.cc	Wed Jan 16 16:27:46 2013 +0000
+++ b/main/database/src/command.cc	Thu Jan 17 19:34:11 2013 +0000
@@ -22,6 +22,9 @@
 #include <octave/Cell.h>
 #include <octave/lo-ieee.h>
 
+#include <iostream>
+#include <fstream>
+
 #include "command.h"
 
 #define ERROR_RETURN_NO_PG_TYPE                                         \
@@ -244,7 +247,10 @@
   return conv;
 }
 
-octave_value command::process_single_result (void)
+octave_value command::process_single_result (const std::string &infile,
+                                             const std::string &outfile,
+                                             int nargout,
+                                             const Cell &data)
 {
   octave_value retval;
 
@@ -274,15 +280,18 @@
           retval = tuples_ok_handler ();
           break;
         case PGRES_COPY_OUT:
-          retval = copy_out_handler ();
+          retval = copy_out_handler (outfile, nargout);
           break;
         case PGRES_COPY_IN:
-          retval = copy_in_handler ();
+          retval = copy_in_handler (infile, data);
           break;
         }
 
-      PQclear (res);
-      res = NULL;
+      if (res) // could have been changed by a handler
+        {
+          PQclear (res);
+          res = NULL;
+        }
     }
 
   return retval;
@@ -433,24 +442,170 @@
     }
 }
 
-octave_value command::copy_out_handler (void)
+octave_value command::copy_out_handler (const std::string &outfile, int nargout)
 {
   octave_value retval;
 
-  valid = 0;
+  if (! outfile.empty ())
+    {
+      // store unchecked output in file
+
+      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)
+        {
+          if (! (ostr.fail () || ostr.bad ()))
+            {
+              ostr.write (data, nb);
+              if (ostr.bad ())
+                error ("write to file failed");
+            }
+          PQfreemem (data);
+        }
+
+      if (! error_state)
+        ostr.close ();
 
-  error ("copy-out not yet implemented");
+      if (nb == -2)
+        error ("server error in copy-out: %s", PQerrorMessage (cptr));
+      else
+        {
+          PQclear (res);
+
+          if (res = PQgetResult (cptr))
+            {
+              if ((state = PQresultStatus (res)) == PGRES_FATAL_ERROR)
+                error ("server error in copy-out: %s", PQerrorMessage (cptr));
+            }
+          else
+            error ("unexpectedly got no result information");
+        }
+
+      if (error_state)
+        valid = 0;
+    }
+  else if (nargout)
+    {
+      // return output data
+
+      error ("copy-out to variable not yet implemented");
+
+      valid = 0;
+    }
+  else
+    {
+      error ("neither output argument nor filename given for copy-out");
+
+      valid = 0;
+    }
 
   return retval;
 }
 
-octave_value command::copy_in_handler (void)
+octave_value command::copy_in_handler (const std::string &infile,
+                                       const Cell &data)
 {
   octave_value retval;
 
-  valid = 0;
+#define OCT_PQ_READSIZE 4096
+
+  char buff [OCT_PQ_READSIZE];
+
+  if (! infile.empty ())
+    {
+      // read unchecked input from file
+
+      std::ifstream istr (infile.c_str (), std::ios_base::in);
+      if (istr.fail ())
+        {
+          error ("could not open input file %s", infile.c_str ());
+
+          PQputCopyEnd (cptr, "could not open input file");
+
+          error ("%s", PQerrorMessage (cptr));
+
+          valid = 0;
+
+          return retval;
+        }
+
+      do
+        {
+          istr.read (buff, OCT_PQ_READSIZE);
+
+          if (istr.bad ())
+            {
+              error ("could not read file %s", infile.c_str ());
+
+              break;
+            }
+          else
+            {
+              int nb;
+
+              if ((nb = istr.gcount ()) > 0)
+                if (PQputCopyData (cptr, buff, nb) == -1)
+                  {
+                    error ("%s", PQerrorMessage (cptr));
+
+                    break;
+                  }
+            }
+        }
+      while (! istr.eof ());
 
-  error ("copy-in not yet implemented");
+      istr.close ();
+
+      if (error_state)
+        {
+          PQputCopyEnd (cptr, "copy-in interrupted");
+
+          error ("%s", PQerrorMessage (cptr));
+        }
+      else
+        {
+          if (PQputCopyEnd (cptr, NULL) == -1)
+            error ("%s", PQerrorMessage (cptr));
+          else
+            {
+              PQclear (res);
+
+              if (res = PQgetResult (cptr))
+                {
+                  if ((state = PQresultStatus (res)) == PGRES_FATAL_ERROR)
+                    error ("server error in copy-in: %s", PQerrorMessage (cptr));
+                }
+              else
+                error ("unexpectedly got no result information");
+            }
+        }
+
+      if (error_state)
+        valid = 0;
+    }
+  else if (! data.is_empty ())
+    {
+      // read input from argument
+
+      error ("copy in from argument not yet implemented");
+
+      if (data.dims ().length () > 2)
+        {
+          error ("copy-in data must not be more than two-dimensional");
+
+          valid = 0;
+
+          return retval;
+        }
+
+      valid = 0;
+    }
+  else
+    error ("neither data nor filename given for copy-in");
 
   return retval;
 }
--- a/main/database/src/command.h	Wed Jan 16 16:27:46 2013 +0000
+++ b/main/database/src/command.h	Thu Jan 17 19:34:11 2013 +0000
@@ -68,7 +68,17 @@
     return all_fetched;
   }
 
-  octave_value process_single_result (void);
+  octave_value process_single_result (void)
+  {
+    Cell c;
+    // inlining should prevent the additional copy
+    return process_single_result ("", "", 0, c);
+  }
+
+  octave_value process_single_result (const std::string &infile,
+                                      const std::string &outfile,
+                                      int nargout,
+                                      const Cell &data);
 
   int good (void) {return valid;}
 
@@ -101,9 +111,9 @@
 
   octave_value tuples_ok_handler (void);
 
-  octave_value copy_out_handler (void);
+  octave_value copy_out_handler (const std::string &, int);
 
-  octave_value copy_in_handler (void);
+  octave_value copy_in_handler (const std::string &, const Cell &);
 
   oct_pq_conv_t *pgtype_from_octtype (octave_value &);
 
--- a/main/database/src/pq_exec.cc	Wed Jan 16 16:27:46 2013 +0000
+++ b/main/database/src/pq_exec.cc	Thu Jan 17 19:34:11 2013 +0000
@@ -102,7 +102,7 @@
 
 #endif // code disabled
 
-DEFUN_DLD (pq_exec_params, args, ,
+DEFUN_DLD (pq_exec_params, args, nargout,
            "-*- texinfo -*-\n\
 @deftypefn {Loadable Function} pq_exec_params (@var{connection}, @var{command})\n\
 @deftypefnx {Loadable Function} pq_exec_params (@var{connection}, @var{command}, @var{params})\n\
@@ -181,11 +181,18 @@
   if (nargs == 1 && args(0).is_string () &&
       args(0).string_value () == "defaults")
     {
-      octave_value_list f_args (2);
+      octave_value_list f_args (8);
       Matrix a;
+      Cell c;
 
       f_args(0) = octave_value ("param_types");
       f_args(1) = octave_value (a);
+      f_args(2) = octave_value ("copy_in_path");
+      f_args(3) = octave_value ("");
+      f_args(4) = octave_value ("copy_out_path");
+      f_args(5) = octave_value ("");
+      f_args(6) = octave_value ("copy_in_data");
+      f_args(7) = octave_value (c);
 
       return feval ("setdbopts", f_args, 1);
     }
@@ -283,6 +290,8 @@
       return retval;
     }
 
+  // get option settings
+
   octave_value_list f_args (3);
 
   octave_value_list f_ret;
@@ -300,6 +309,44 @@
       return retval;
     }
 
+  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 ("could not convert copy_in_path to string");
+
+      return retval;
+    }
+
+  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 ("could not convert copy_out_path to string");
+
+      return retval;
+    }
+
+  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 ("could not convert copy_in_data to cell");
+
+      return retval;
+    }
+
+  // check option settings
+
   if (ptypes.length () != nparams)
     {
       error ("%s: if given, cell-array of parameter types must have same length as cell-array of parameters",
@@ -308,12 +355,30 @@
       return retval;
     }
 
+  if (nargout && ! cout_path.empty ())
+    {
+      error ("%s: copy out pathname and output argument may not be both given",
+             fname.c_str ());
+
+      return retval;
+    }
+
+  if (! cin_path.empty () && ! cin_data.is_empty ())
+    {
+      error ("%s: copy in pathname and copy in data may not be both given",
+             fname.c_str ());
+
+      return retval;
+    }
+
+  //
+
   Cell rtypes;
 
   command c (oct_pq_conn, cmd, params, ptypes, rtypes, fname);
 
   if (c.good ())
-    retval = c.process_single_result ();
+    retval = c.process_single_result (cin_path, cout_path, nargout, cin_data);
 
   return retval;
 }