Logo Search packages:      
Sourcecode: hitop version File versions

pgsql.cc

#ifndef __pluginh__
  #include "../plugin.h"
#endif
#ifndef __htmlh__
  #include "../html.h"
#endif
#ifndef __parammaph__
  #include "../parammap.h"
#endif
#ifndef __hitopcommandsh__
  #include "../hitopcommands.h"
#endif
#ifndef __errorh__
  #include "../error.h"
#endif
#ifndef __tables_entitiesh__
  #include "../tables/entities.h"
#endif

#include <string>
#include <vector>
#include <algorithm>
#include <libpq++.h>

class dsoDBpgsqlMod :public Plugin{
public:
  dsoDBpgsqlMod();
  virtual void Init();
private:
  // static void ESCAPE(__HITOPFUNC__);
};

class DBpgsql :public DBaseBase {
private:
  PgDatabase* m_connection;
public:
  virtual void Disconnect(HTMLStream &stream,HTMLStream::iterator cur,
      const ParamMap& params);
  virtual void Query(HTMLStream &stream,HTMLStream::iterator cur,
      const string& entryproc,const ParamMap& params, bool is_discard, bool is_assign);
  static DBaseBase* Connect(const string& handle,HTMLStream &stream,
      HTMLStream::iterator cur,const ParamMap& paramMap); 
};

static dsoDBpgsqlMod initmodule;

dsoDBpgsqlMod::dsoDBpgsqlMod() {
  RegisterPlugin(string("pgsql"),2);
}

void dsoDBpgsqlMod::Init(){
  RegisterDBDriver(string("PGSQL"),&DBpgsql::Connect);
  SetNamespace("PGSQL");
  //RegisterFunction("ESCAPE",&dsoDBmysqlMod::ESCAPE);
}

DBaseBase* DBpgsql::Connect(const string& handle, HTMLStream &stream,
    HTMLStream::iterator cur, const ParamMap& paramMap) {
  string params,whitetransitvan;
  DBpgsql* result = new DBpgsql;
  paramMap.Retrieve("SERVER",whitetransitvan);
  whitetransitvan=Entities::Unescape(whitetransitvan);
  if (!whitetransitvan.empty()) params="host= '"+whitetransitvan+"' ";
  paramMap.Retrieve("PORT",whitetransitvan);
  whitetransitvan=Entities::Unescape(whitetransitvan);
  if (!whitetransitvan.empty()) params+="port= '"+whitetransitvan+"' ";
  paramMap.Retrieve("DATABASE",whitetransitvan);
  whitetransitvan=Entities::Unescape(whitetransitvan);
  if (!whitetransitvan.empty()) params+="dbname= '"+whitetransitvan+"' ";
  paramMap.Retrieve("USER",whitetransitvan);
  whitetransitvan=Entities::Unescape(whitetransitvan);
  if (!whitetransitvan.empty()) params+="user= '"+whitetransitvan+"' ";
  paramMap.Retrieve("PASSWORD",whitetransitvan);
  whitetransitvan=Entities::Unescape(whitetransitvan);
  if (!whitetransitvan.empty()) params+="password= '"+whitetransitvan+"' ";

  result->m_connection = new PgDatabase(params.c_str());
  if (result->m_connection->ConnectionBad()) {
       Error(*cur,result->m_connection->ErrorMessage());
       delete result->m_connection;
       delete result;
       return NULL;
  }
  return result;
}
void DBpgsql::Query(HTMLStream &stream,HTMLStream::iterator cur,
    const string& entryproc,const ParamMap& params,bool is_discard, bool is_assign) {
  string query;
  if (!params.Retrieve("SQLQUERY",query)) {
    Error(*cur,"Missing SQLQUERY parameter");
  }
  query=Entities::Unescape(query);
  ExecStatusType ret =m_connection->Exec(query.c_str());
  if ((ret==PGRES_BAD_RESPONSE)||(ret==PGRES_NONFATAL_ERROR)||(ret==PGRES_FATAL_ERROR)) {
    Error(*cur,m_connection->ErrorMessage());
  }
  if (is_discard) {
    return;
  }
  // Evil thing to do, but we need to be able to run concurrent queries....
  // ... so copy the results into memory, and free up our resources.
  if (ret==PGRES_TUPLES_OK) {
    vector<string> columns;
    list<vector<string> > results;
    vector<string> thisrow;
    int fields = m_connection->Fields();
    columns.resize(fields);
    thisrow.resize(fields);
    for (int i=0; i<fields; ++i) {
      columns[i]=m_connection->FieldName(i);
      transform(columns[i].begin(),columns[i].end(),columns[i].begin(),ToUpper());
      string::iterator j;
      while (columns[i].end()!=(j=find(columns[i].begin(),columns[i].end(),'.'))) {
         *j='_';
      }
    }
    if (is_assign) {
      if (0==m_connection->Tuples()) {
        Warn (*cur,"No tuples returned to an ASSIGN query");
        return;
      }
      string value;
      for (int ii=0; ii<fields; ++ii) {
        value = m_connection->GetValue(0,ii);
        stream.m_curVars.Set(columns[ii],Entities::Escape(value),Vars::Local);
      }
      return;
    }
    int rows= m_connection->Tuples();
    for (int j=0; j<rows; j++) {
      for (int i=0; i<fields; i++) {
        thisrow[i]=m_connection->GetValue(j,i);
            thisrow[i]=Entities::Escape(thisrow[i]);
      }
      results.push_back(thisrow);
    }
    // how the hell do I clear the results?!
    ParamMap values=params;
    for (list<vector<string> >::iterator j=results.begin(); j!=results.end(); j++) {
      for (int i=0; i<fields; i++) {
        values[columns[i]]=(*j)[i];
      }
      HitopCommands::UserEngine(stream,cur,values,entryproc);
    }
    return;
  }
  if ((ret == PGRES_COMMAND_OK)||(PGRES_EMPTY_QUERY)) {
    return;
  }  
  Error(*cur,"Unsupported SQL query used. The query has been run (but not committed if you are using transactions), but hitop does not understand the output");
}


void DBpgsql::Disconnect(HTMLStream &stream,HTMLStream::iterator cur,
        const ParamMap& params) {
  // do I have to do anything here? Does anyone ever actually call disconnect on their database handles anyway?!
}

Generated by  Doxygen 1.6.0   Back to index