# HG changeset patch # User i7tiol # Date 1358451251 0 # Node ID 913ac5491db192188e2ea23d2efc3a9c6db2af79 # Parent 8979fcae5e7d6d0fbc954c6ab42b2d75fef12a5c Copy in/out from/to local file hacked in. Doc change waits till copy in/out from/to variable. diff -r 8979fcae5e7d -r 913ac5491db1 main/database/src/command.cc --- 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 #include +#include +#include + #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; } diff -r 8979fcae5e7d -r 913ac5491db1 main/database/src/command.h --- 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 &); diff -r 8979fcae5e7d -r 913ac5491db1 main/database/src/pq_exec.cc --- 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; }