00001 #ifndef __vtkPostgreSQLDatabasePrivate_h
00002 #define __vtkPostgreSQLDatabasePrivate_h
00003
00004 #include "vtkStdString.h"
00005 #include "vtkType.h"
00006 #include "vtkTimeStamp.h"
00007
00008 #define PQXX_ALLOW_LONG_LONG
00009 #include <pqxx/pqxx>
00010
00011
00012 class vtkPostgreSQLDatabasePrivate
00013 {
00014 public:
00015
00016
00017 vtkPostgreSQLDatabasePrivate( const char options[] )
00018 : Connection( options )
00019 {
00020 this->Work = 0;
00021 this->UpdateColumnTypeMap();
00022 }
00023
00024
00025
00026 virtual ~vtkPostgreSQLDatabasePrivate()
00027 {
00028 this->RollbackTransaction();
00029 }
00030
00031
00032
00033
00034
00035 bool BeginTransaction()
00036 {
00037 this->RollbackTransaction();
00038 this->Work = new pqxx::transaction<>( this->Connection );
00039 return true;
00040 }
00041
00042
00043
00044
00045 bool CommitTransaction()
00046 {
00047 if ( this->Work )
00048 {
00049 bool ok = true;
00050 try
00051 {
00052 this->Work->commit();
00053 }
00054 catch ( const vtkstd::exception& e )
00055 {
00056 this->LastErrorText = e.what();
00057 vtkGenericWarningMacro( << this->LastErrorText.c_str() );
00058 ok = false;
00059 }
00060 delete this->Work;
00061 this->Work = 0;
00062 return ok;
00063 }
00064
00065 vtkGenericWarningMacro( "Cannot commit without first beginning a transaction." );
00066 return false;
00067 }
00068
00069
00070
00071
00072 bool RollbackTransaction()
00073 {
00074 if ( this->Work )
00075 {
00076
00077 delete this->Work;
00078 this->Work = 0;
00079 return true;
00080 }
00081
00082 return false;
00083 }
00084
00085
00086 int GetVTKTypeFromOID( pqxx::oid pgtype )
00087 {
00088 vtkstd::map<pqxx::oid,int>::const_iterator it = this->ColumnTypeMap.find( pgtype );
00089 if ( it == this->ColumnTypeMap.end() )
00090 {
00091 return VTK_STRING;
00092 }
00093 return it->second;
00094 }
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109 void UpdateColumnTypeMap()
00110 {
00111 this->ColumnTypeMap.clear();
00112 this->BeginTransaction();
00113 try
00114 {
00115 pqxx::result res = this->Work->exec( "SELECT oid,typname,typlen FROM pg_type" );
00116 pqxx::result::const_iterator rit = res.begin();
00117 pqxx::oid oid;
00118 vtkstd::string typname;
00119 int typlen;
00120 for ( ; rit != res.end(); ++rit )
00121 {
00122 rit[0].to( oid );
00123 rit[1].to( typname );
00124 rit[2].to( typlen );
00125 if ( typname == "int8" || ( typname == "oid" && typlen == 8 ) )
00126 {
00127 this->ColumnTypeMap[ oid ] = VTK_TYPE_INT64;
00128 }
00129 else if ( typname == "int4" || ( typname == "oid" && typlen == 4 ) )
00130 {
00131 this->ColumnTypeMap[ oid ] = VTK_TYPE_INT32;
00132 }
00133 else if ( typname == "int2" )
00134 {
00135 this->ColumnTypeMap[ oid ] = VTK_TYPE_INT16;
00136 }
00137 else if ( typname == "char" )
00138 {
00139 this->ColumnTypeMap[ oid ] = VTK_TYPE_INT8;
00140 }
00141 else if ( typname == "time_stamp" )
00142 {
00143 this->ColumnTypeMap[ oid ] = VTK_TYPE_INT64;
00144 }
00145 else if ( typname == "float4" )
00146 {
00147 this->ColumnTypeMap[ oid ] = VTK_FLOAT;
00148 }
00149 else if ( typname == "float8" )
00150 {
00151 this->ColumnTypeMap[ oid ] = VTK_DOUBLE;
00152 }
00153 else if ( typname == "abstime" || typname == "reltime" )
00154 {
00155 this->ColumnTypeMap[ oid ] = ( typlen == 4 ? VTK_TYPE_INT32 : VTK_TYPE_INT64 );
00156 }
00157 else if ( typname == "text" )
00158 {
00159 this->ColumnTypeMap[ oid ] = VTK_STRING;
00160 }
00161 }
00162 }
00163 catch ( vtkstd::exception& e )
00164 {
00165 this->LastErrorText = e.what();
00166 }
00167 this->RollbackTransaction();
00168 }
00169
00170
00171 vtkStdString LastErrorText;
00172
00173 pqxx::connection Connection;
00174
00175
00176
00177 pqxx::work* Work;
00178
00179 vtkstd::map<pqxx::oid,int> ColumnTypeMap;
00180 };
00181
00182 #endif // __vtkPostgreSQLDatabasePrivate_h