Hi we needed to acces a postgres db from octave, and tried the database-1.01 package from octave-forge, and didnt like it: it is slow, creates 108 global variables, and crashes :
After installing it globally: octave 1> pkg load database octave 2> clear -a panic: Segmentation fault -- stopping myself... attempting to save variables to `octave-core'... save to `octave-core' complete http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=523085 After some digging, it seems that swig is the cause of this, and we cannot fix this. So we made our own tools (inspired by pgnumdata 1999 D.Eddelbuettel) and would like to put them in octave-forge. Currently we only read from postgresdb, we will add 'insert' very soon, as we need this too. Any comments are welcome. Alain. ------------------------- Makefile ----------------------------------- # build oct files MAKEFLAGS=s all: echo "Building pgsql oct files..." rm -f *.oct mkoctfile pg_lib.cc -lpq --output pg_lib.oct ln -s pg_lib.oct pgOpen.oct ln -s pg_lib.oct pgEnd.oct ln -s pg_lib.oct pgCell.oct ln -s pg_lib.oct pgMatrix.oct echo "done." rm -f *.o clean: rm -f *.o rm -f *.oct ------------------------ End of Makefile ------------------------------ -------------------------- pg_lib.cc ---------------------------------- /* * pg_lib.cc -- octave functions to retrieve data from Postgresql 8 * * Copyright (C) 2009 Alain Baeckeroot <alain.baecker...@laposte.net> * * This is a direct adaptation to postgres 8.3 of pgnumdata 1.1 : * pgnumdata 1.1 Copyright (C) 1999 Dirk Eddelbuettel <e...@debian.org> */ // // 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, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // // #include <octave/oct.h> #include <octave/Cell.h> #include <postgresql/libpq-fe.h> /***************************************************************************************/ /************** octave function to retrieve any data from Postgresql 8 ****************/ DEFUN_DLD(pgCell, args, nargout, \ "usage : C = pgCell( conn, select_command )\n\n\ (long int) conn is obtained by 'conn = pgOpen(...)'\n\ (string) select_command = \"select n1, n2, n3 from mytable limit 10\"\n\ returns a Cell\n\ see also pgOpen pgMatrix\n") { const char *conninfo; PGconn *conn; const char *sqlcmd; PGresult *res; long iconn; std::string tmp; octave_value_list retval; // list of return values int nargs = args.length(); // number of arguments supplied if (nargs != 2) { // if not enough arguments, show message usage("Try 'help pgCell' for info"); return retval; // and return empty } iconn = args(0).long_value(); // get the info to connect to the database conn = (PGconn *) iconn; // set the pointer to this address tmp = args(1).string_value(); // get SQL command "select numbers from ..." sqlcmd = tmp.c_str(); /* Check to see that the backend connection was successfully made */ if (PQstatus(conn) != CONNECTION_OK) { error("Connection to database failed: %s \n", PQerrorMessage(conn)); PQfinish(conn); return retval; // ... then return empty } // pass SQL argument as char*, and check if executed allright res = PQexec(conn, sqlcmd); // Check that the query was OK if ( (PQresultStatus(res) != PGRES_TUPLES_OK) && (PQresultStatus(res) != 2) ) { error("Query failed failed: %s", PQerrorMessage(conn)); PQclear(res); // avoid memory leaks return retval; // ... then return empty } long k = PQnfields(res); // we know that query was executed, long n = PQntuples(res); if (n == 0) { // but did we get any data ? error("Query returned no data"); return retval; // ... then return empty } Cell C (n, k); // now we know there's data, so let's assign it for (long i = 0; i < n; i++) // loop over all elements for (long j = 0; j < k; j++) C (i,j) = PQgetvalue(res, i, j); /* cleanup */ PQclear(res); retval(0) = C; // set the return vector and return retval; // give it back to the caller } /***************************************************************************************/ /********** octave function to retrieve *numerical* data from Postgresql 8 *************/ DEFUN_DLD(pgMatrix, args, nargout, \ "usage : X = pgMatrix( conn, select_command )\n\ (long int) conn is obtained by 'conn = pgOpen(...)'\n\ (string) select_command = \"select n1, n2, n3 from mytable limit 10\"\n\ returns a Matrix\n\ see also pgOpen pgCell\n") { const char *conninfo; PGconn *conn; const char *sqlcmd; PGresult *res; long iconn; std::string tmp; octave_value_list retval; // list of return values int nargs = args.length(); // number of arguments supplied if (nargs != 2) { // if not enough arguments, show message usage("Try 'help pgMatrix' for info"); return retval; // and return empty } iconn = args(0).long_value(); // get the info to connect to the database conn = (PGconn *) iconn; // set the pointer to this address tmp = args(1).string_value(); // get SQL command "select numbers from ..." sqlcmd = tmp.c_str(); /* Check to see that the backend connection was successfully made */ if (PQstatus(conn) != CONNECTION_OK) { error("Connection to database failed: %s \n", PQerrorMessage(conn)); PQfinish(conn); return retval; // ... then return empty } // pass SQL argument as char*, and check if executed allright res = PQexec(conn, sqlcmd); // Check that the query was OK if (PQresultStatus(res) != PGRES_TUPLES_OK) { error("Query failed : %s", PQerrorMessage(conn)); PQclear(res); // avoid memory leaks return retval; // ... then return empty } long k = PQnfields(res); // we know that query was executed, long n = PQntuples(res); if (n == 0) { // but did we get any data ? error("Query returned no data"); return retval; // ... then return empty } Matrix X(n, k); // now we know there's data, so let's assign it for (long i = 0; i < n; i++) // loop over all elements, and convert to doubles for (long j = 0; j < k; j++) sscanf(PQgetvalue(res, i, j), "%lf", &X(i, j)); /* cleanup */ PQclear(res); retval(0) = X; // set the return vector and return retval; // give it back to the caller } /***************************************************************************************/ /************** octave function to open a connection to postgres 8.3 db ****************/ DEFUN_DLD(pgOpen, args, nargout, "Returns the address of the connection pointer\n\ usage : conn = pgOpen( \"user=foo dbname=thedb password=secret ...\")\n\ see also pgEnd, pgMatrix ...\n" ) { const char *conninfo; PGconn *conn; std::string tmp; octave_value_list retval; // list of return values int nargs = args.length(); // number of arguments supplied if (nargs != 1) { // if not enough arguments, show message usage("Try 'help pgOpen' for info"); return retval; // and return empty } tmp = args(0).string_value(); // get info to connect to the database // "dbname=foodb user=foo password=secret ..." conninfo = tmp.c_str(); /* Make a connection to the database */ conn = PQconnectdb(conninfo); /* Check to see that the backend connection was successfully made */ if (PQstatus(conn) == CONNECTION_OK) { // read the address of the pointer (octave does not have pointer) retval(0) = (long) ( conn ); } else { error("Connection to database failed: %s \n", PQerrorMessage(conn)); PQfinish(conn); retval(0) = -1; } return retval; // give it back to the caller } /***************************************************************************************/ /************* octave function to close a connection with Postgresql 8.3 ***************/ DEFUN_DLD(pgEnd, args, nargout, "pgEnd( conn )\n\ Ends the connection opened by : conn = pgOpen(...)\n\ Returns error code (negative value)\n") { PGconn *conn; octave_value_list retval; // list of return values int nargs = args.length(); // number of arguments supplied if (nargs != 1) { // if not enough arguments, show message usage("Try 'help pgEnd' for info"); retval(0) = -1; return retval; // return negative err code } conn = (PGconn *) args(0).long_value(); // get info to connect to the database // either segfault or finish ! /* Close the connection to the database */ PQfinish(conn); return retval; // Return empty is ok. } /***************************************************************************************/ -----------------------------End of pg_lib.cc ------------------------------------------ ------------------------------------------------------------------------------ Register Now & Save for Velocity, the Web Performance & Operations Conference from O'Reilly Media. Velocity features a full day of expert-led, hands-on workshops and two days of sessions from industry leaders in dedicated Performance & Operations tracks. Use code vel09scf and Save an extra 15% before 5/3. http://p.sf.net/sfu/velocityconf _______________________________________________ Octave-dev mailing list Octave-dev@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/octave-dev