Mercurial > forge
diff main/database/src/command.cc @ 11484:154bc776dfa8 octave-forge
Implemented copy in from Octave variable.
author | i7tiol |
---|---|
date | Wed, 27 Feb 2013 20:40:31 +0000 |
parents | d14a23884d9c |
children | 1176424db5df |
line wrap: on
line diff
--- a/main/database/src/command.cc Wed Feb 27 13:56:09 2013 +0000 +++ b/main/database/src/command.cc Wed Feb 27 20:40:31 2013 +0000 @@ -270,7 +270,12 @@ } octave_value command::process_single_result (const std::string &infile, - const std::string &outfile) + const std::string &outfile, + const Cell &cdata, + const Cell &ctypes, + bool coids, + bool cin_var, + bool cout_var) { octave_value retval; @@ -300,10 +305,10 @@ retval = tuples_ok_handler (); break; case PGRES_COPY_OUT: - retval = copy_out_handler (outfile); + retval = copy_out_handler (outfile, cout_var); break; case PGRES_COPY_IN: - retval = copy_in_handler (infile); + retval = copy_in_handler (infile, cdata, ctypes, coids, cin_var); break; } @@ -455,7 +460,7 @@ } } -octave_value command::copy_out_handler (const std::string &outfile) +octave_value command::copy_out_handler (const std::string &outfile, bool var) { octave_value retval; @@ -507,7 +512,11 @@ return retval; } -octave_value command::copy_in_handler (const std::string &infile) +octave_value command::copy_in_handler (const std::string &infile, + const Cell &data, + const Cell &cin_types, + bool oids, + bool var) { octave_value retval; @@ -515,10 +524,19 @@ char buff [OCT_PQ_READSIZE]; - if (! infile.empty ()) + if (! var) { // read unchecked input from file + if (infile.empty ()) + { + error ("no input file given"); + + valid = 0; + + return retval; + } + std::ifstream istr (infile.c_str (), std::ios_base::in); if (istr.fail ()) { @@ -585,7 +603,222 @@ } } else - error ("no filename given for copy-in"); + { + // copy in from octave variable + + dim_vector dv = data.dims (); + octave_idx_type r = dv(0); + octave_idx_type c = dv(1); + + 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); + + PQputCopyEnd + (cptr, "variable for copy-in has wrong number of columns"); + } + else if (! PQbinaryTuples (res)) + { + error ("copy-in from variable must use binary mode"); + + PQputCopyEnd (cptr, "copy-in from variable must use binary mode"); + } + else + { + for (octave_idx_type j = 0; j < c; j++) + if (! PQfformat (res, j)) + { + error ("copy-in from argument must use binary mode in all columns"); + + PQputCopyEnd (cptr, "copy-in from argument must use binary mode in all columns"); + + break; + } + } + + if (error_state) + { + error ("server error: %s", PQerrorMessage (cptr)); + + valid = 0; + + return retval; + } + +#define COPY_HEADER_SIZE 19 + char header [COPY_HEADER_SIZE]; + memset (header, 0, COPY_HEADER_SIZE); + strcpy (header, "PGCOPY\n\377\r\n\0"); + *((uint32_t *) (&header[11])) = htobe32 (uint32_t (oids) << 16); + + char trailer [2]; + *((int16_t *) (&trailer)) = htobe16 (int16_t (-1)); + + if (PQputCopyData (cptr, header, COPY_HEADER_SIZE) == -1) + { + PQputCopyEnd (cptr, "could not send header"); + + error ("server error: %s", PQerrorMessage (cptr)); + } + else + { + oct_pq_conv_t *convs [c]; + memset (convs, 0, sizeof (convs)); + oct_type_t oct_types [c]; + + for (octave_idx_type i = 0; i < r; i++) // i is row + { + int16_t fc = htobe16 (int16_t (nf)); + if (PQputCopyData (cptr, (char *) &fc, 2) == -1) + { + error ("%s", PQerrorMessage (cptr)); + + PQputCopyEnd (cptr, "error sending field count"); + + error ("server error: %s", PQerrorMessage (cptr)); + + break; + } + + // j is column of argument data + for (octave_idx_type j = 0; j < c; j++) + { + if (data(i, j).is_real_scalar () && + data(i, j).isna ().bool_value ()) + { + int32_t t = htobe32 (int32_t (-1)); + if (PQputCopyData (cptr, (char *) &t, 4) == -1) + { + error ("could not send NULL in copy-in"); + + break; + } + } + else + { + if (! convs [j]) + { + if ((j == 0) && oids) + { + std::string t ("oid"); + convs[0] = pgtype_from_spec (t, oct_types[0]); + } + else + { + if (cin_types(j).is_empty ()) + { + oct_types[j] = simple; + + if (! (convs[j] = + pgtype_from_octtype (data(i, j)))) + { + error ("could not determine type in column %i for copy-in", + j); + + break; + } + } + else + { + std::string s = cin_types(j).string_value (); + if (error_state) + { + error ("column type specification no string"); + + break; + } + + if (! (convs[j] = + pgtype_from_spec (s, oct_types[j]))) + { + error ("invalid column type specification"); + + break; + } + } + } + } // ! convs [j] + + oct_pq_dynvec_t val; + + bool conversion_failed = false; + switch (oct_types[j]) + { + case simple: + if (convs[j]->from_octave_bin (data(i, j), val)) + conversion_failed = true; + break; + + case array: + if (from_octave_bin_array (data(i, j), val, convs[j])) + conversion_failed = true; + break; + + case composite: + if (from_octave_bin_composite (data(i, j), val, + convs[j])) + conversion_failed = true; + break; + + default: + // should not get here + error ("internal error, undefined type identifier"); + } + + if (conversion_failed) + 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"); + else if (PQputCopyData (cptr, &(val.front ()), + val.size ()) == -1) + error ("could not send copy-in data"); + } + + if (error_state) break; + } + } // columns of argument data + + if (error_state) + { + PQputCopyEnd (cptr, "error sending copy-in data"); + + error ("server error: %s", PQerrorMessage (cptr)); + + break; + } + } // rows of argument data + } + + if (! error_state) + if (PQputCopyData (cptr, trailer, 2) == -1) + { + PQputCopyEnd (cptr, "could not send trailer"); + + error ("%s", PQerrorMessage (cptr)); + } + + if (! error_state) + 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"); + } + } // copy from variable if (error_state) valid = 0;