Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Namespace Members | Compound Members | File Members | Related Pages | Examples

vos/metaobjects/property/pgdb_property.cc

Go to the documentation of this file.
00001 /* $Id: pgdb_property.cc,v 1.9 2003/07/22 05:08:37 tetron Exp $ */
00002 
00003 
00004 
00005 /**
00006     @file pgdb_property.cc
00007 
00008     Implements DBProperty using PostgreSQL DB (using libpq).
00009     @see pgdb_property.hh
00010 
00011 
00012 
00013 
00014     @author Reed Hedges <reed@zerohour.net>
00015 
00016 
00017     This file is part of the Virtual Object System of
00018     the Interreality project (http://interreality.org).
00019 
00020     Copyright (C) 2001, 2002 Reed Hedges
00021 
00022     This library is free software; you can redistribute it and/or
00023     modify it under the terms of the GNU Lesser General Public
00024     License as published by the Free Software Foundation; either
00025     version 2 of the License, or (at your option) any later version.
00026 
00027     This library is distributed in the hope that it will be useful,
00028     but WITHOUT ANY WARRANTY; without even the implied warranty of
00029     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00030     Lesser General Public License for more details.
00031 
00032     You should have received a copy of the GNU Lesser General Public
00033     License along with this library; if not, write to the Free Software
00034     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
00035 
00036 */
00037 
00038 #include "pgdb_property.hh"
00039 #include <vos/corelibs/vos/vos.hh>
00040 
00041 #ifdef HAVE_POSTGRESQL_LIBPQ_FE_H
00042     #include <postgresql/libpq-fe.h>
00043 #else
00044     #ifdef HAVE_PGSQL_LIBPQ_FE_H
00045         #include <pgsql/libpq-fe.h>
00046     #else
00047         #error "Neither HAVE_POSTGRESQL_LIBPQ_FE_H nor HAVE_PGSQL_LIBPQ_FE_H are define, so I don't know where libpq-fe.h is!"
00048     #endif
00049 #endif
00050 
00051 
00052 /* basic ctor */
00053 PGDBProperty::PGDBProperty(MetaObject* superobject) :
00054     DBProperty(superobject), LocalProperty(superobject), Property(superobject), MetaObject(superobject), dbcon(NULL) {
00055     // yay.
00056 }
00057 
00058 
00059 /* Open connection. Will create table and/or columns if necesary.  */
00060 void PGDBProperty::open(const string& dbinfo = "")
00061 {
00062     dbcon = PQconnectdb(dbinfo.c_str());
00063 
00064     LOG("postgres property", 4, "opening connection to database ("<<dbinfo<<")");
00065 
00066     switch(PQstatus(dbcon)) {
00067         case CONNECTION_OK: /* connection successful. */ break;
00068         case CONNECTION_BAD: throw DBAccessError("Failed to make database connection."); break;
00069 #ifndef HAVE_PGSQL_LIBPQ_FE_H
00070         // newer versions return more codes
00071         case CONNECTION_STARTED: throw DBAccessError("Database connection incomplete. (waiting for connection to be made)"); break;
00072         case CONNECTION_AWAITING_RESPONSE: throw DBAccessError("Database connection incomplete. (still waiting for response from PG postmaster)"); break;
00073         case CONNECTION_AUTH_OK: throw DBAccessError("Database connection incomplete. (authorization was okay, backend did not start)"); break;
00074         case CONNECTION_SETENV: throw DBAccessError("Database connection incomplete. (getting environment variables)"); break;
00075 #endif
00076         default: throw DBAccessError(string("Failed to make database connection (unkown error at ") + string(__FILE__) + string(" (PGDBProperty::PGDBProperty())."));
00077     }
00078 
00079 
00080 
00081 }
00082 
00083 
00084 /* Destructoratorizer. Close database connection. */
00085 PGDBProperty::~PGDBProperty() {
00086     PQfinish(dbcon);
00087 }
00088 
00089 
00090 
00091 
00092 
00093 
00094 /* Perform a query on the database. Currently only the first field of the first
00095 row is returned if the query returns more than one value. */
00096 string PGDBProperty::queryDB(const string& query) throw(DBAccessError) {
00097 
00098     PGresult *result;
00099     int ntuples, nfields, t, f;
00100     string s = "";
00101 
00102 
00103     LOG("postgres", 7, "querying db: " << query);
00104 
00105     result = PQexec(dbcon, query.c_str());
00106 
00107 
00108     /// XXX BUG: does not free 'result' when errors occur (just throws message)
00109 
00110 
00111 
00112     switch(PQresultStatus(result)) {
00113 
00114         case PGRES_COMMAND_OK:  // Successful completion of a command returning no data
00115         case PGRES_COPY_OUT:
00116         case PGRES_COPY_IN: // actually i think these won't occur, technically
00117 
00118             PQclear(result);
00119             return "";
00120 
00121         case PGRES_TUPLES_OK:   // The query successfully executed
00122             ntuples = PQntuples(result);
00123             nfields = PQnfields(result);
00124             LOG("postgres", 9, "queryDB: there are "<<ntuples<<" tuples and "<<nfields<<" fields."<< (( (ntuples > 1) || (nfields > 1))?"Warning: only the first field will be returned.":""));
00125             s = string(PQgetvalue(result, 0, 0));
00126 
00127             /*
00128             for(t = 0; t < ntuples; t++) {
00129                 if(t != 0) s += "\n";
00130                 for(f = 0; f < nfields; f++) {
00131                     if(f != 0) s += "\t";
00132                     s += string(PQgetvalue(result, t, f));
00133                 }
00134             }
00135             */
00136 
00137             PQclear(result);
00138             return s;
00139 
00140 
00141         case PGRES_BAD_RESPONSE:    // The server's response was not understood
00142             throw DBAccessError(string("Error, Postgres server is talking jibba-jabba. ")+PQresultErrorMessage(result));
00143 
00144         case PGRES_NONFATAL_ERROR:
00145             throw DBAccessError(string("Postgres reports a nonfatal error. But I don't know what to do with it, you try something: ")+PQresultErrorMessage(result));
00146 
00147         case PGRES_EMPTY_QUERY: //The string sent to the backend was empty. I think this is also NULL (0), for really fatal error.
00148         case PGRES_FATAL_ERROR:
00149             throw DBAccessError(string("Fatal error querying Postgres database! ")+PQresultErrorMessage(result));
00150     }
00151 
00152     PQclear(result);
00153     return "";
00154 
00155 }

Generated on Tue Aug 12 03:55:46 2003 for Interreality Project - VOS by doxygen 1.3.2