| TerraLib 4.1

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files
- Examples

- File List
- File Members

E:/Projetos_Primeiro_Semestre_2012/TerraView/terralib/src/terralib/drivers/PostgreSQL/TePGInterface.h
Go to the documentation of this file.

    00001 /************************************************************************************
    00002 TerraLib - a library for developing GIS applications.
    00003 Copyright � 2001-2007 INPE and Tecgraf/PUC-Rio.
    00004
    00005 This code is part of the TerraLib library.
    00006 This library is free software; you can redistribute it and/or
    00007 modify it under the terms of the GNU Lesser General Public
    00008 License as published by the Free Software Foundation; either
    00009 version 2.1 of the License, or (at your option) any later version.
    00010
    00011 You should have received a copy of the GNU Lesser General Public
    00012 License along with this library.
    00013
    00014 The authors reassure the license terms regarding the warranties.
    00015 They specifically disclaim any warranties, including, but not limited to,
    00016 the implied warranties of merchantability and fitness for a particular purpose.
    00017 The library provided hereunder is on an "as is" basis, and the authors have no
    00018 obligation to provide maintenance, support, updates, enhancements, or modifications.
    00019 In no event shall INPE and Tecgraf / PUC-Rio be held liable to any party for direct,
    00020 indirect, special, incidental, or consequential damages arising out of the use
    00021 of this library and its documentation.
    00022 *************************************************************************************/
    00029 #ifndef  __TERRALIB_INTERNAL_PGINTERFACE_H
    00030 #define  __TERRALIB_INTERNAL_PGINTERFACE_H
    00031
    00037 //extern "C"
    00038 //{
    00039 #include <libpq-fe.h>
    00040 //}
    00041
    00042 #ifdef WIN32
    00043 #include <winsock.h>
    00044 #else
    00045 #include <netinet/in.h>
    00046 #endif
    00047
    00048
    00049 #include <stdlib.h>
    00050 #include <string>
    00051 #include <cstring>
    00052
    00053 #include "../../kernel/TeDatabase.h"
    00054 #include "../../kernel/TeMultiGeometry.h"
    00055 #include "../../kernel/TeMutex.h"
    00056
    00057 #include "TePostgreSQLDefines.h"
    00058
    00059 using namespace std;
    00060
    00061 /***************************************************************************
    00062  * Constantes numericas dos tipos de dados do PostgreSQL                   *
    00063  ***************************************************************************/
    00064 const Oid PG_BOOL_TYPE = 16;
    00065 const Oid PG_BYTEA_TYPE = 17;
    00066 const Oid PG_CHAR_TYPE = 18;
    00067 const Oid PG_NAME_TYPE = 19;
    00068 const Oid PG_INT8_TYPE = 20;
    00069 const Oid PG_INT2_TYPE = 21;
    00070 const Oid PG_INT4_TYPE = 23;
    00071 const Oid PG_TEXT_TYPE = 25;
    00072 const Oid PG_OID_TYPE = 26;
    00073 const Oid PG_POINT_TYPE = 600;
    00074 const Oid PG_LSEG_TYPE = 601;
    00075 const Oid PG_PATH_TYPE = 602;
    00076 const Oid PG_BOX_TYPE = 603;
    00077 const Oid PG_POLYGON_TYPE = 604;
    00078 const Oid PG_LINE_TYPE = 628;
    00079 const Oid PG_PG_FLOAT4_TYPE = 700;
    00080 const Oid PG_FLOAT8_TYPE = 701;
    00081 const Oid PG_CIRCLE_TYPE = 718;
    00082 const Oid PG_MONEY_TYPE = 790;
    00083 const Oid PG_BPCHAR_TYPE = 1042;
    00084 const Oid PG_VARCHAR_TYPE = 1043;
    00085 const Oid PG_DATE_TYPE = 1082;
    00086 const Oid PG_TIME_TYPE = 1083;
    00087 const Oid PG_TIMESTAMP_TYPE = 1114;
    00088 const Oid PG_TIMESTAMPTZ_TYPE = 1184;
    00089 const Oid PG_INTERVAL_TYPE = 1186;
    00090 const Oid PG_TIMETZ_TYPE = 1266;
    00091 const Oid PG_BIT_TYPE = 1560;
    00092 const Oid PG_VARBIT_TYPE = 1562;
    00093 const Oid PG_NUMERIC_TYPE = 1700;
    00094
    00095
    00096 //method modified from Terralib5 used for EWKB compatibility
    00097 #define TE_EWKB_ZM_OFFSET    0xC0000000
    00098 #define TE_EWKB_Z_OFFSET     0x80000000
    00099 #define TE_EWKB_M_OFFSET     0x40000000
    00100 #define TE_EWKB_SRID_FLAG    0x20000000
    00101 #define TE_EWKB_BBOX_FLAG    0x10000000
    00102
    00103
    00104 /***************************************************************************
    00105  * Classe responsavel pela abertura e fechamento de uma conexao com o      *
    00106  * banco de dados. Alem de abrir e fechar uma conexao, permite que uma     *
    00107  * consulta seja executada, retornando um conjunto de registros, ou que um *
    00108  * comando - insert, update, delete - seja executado diretamente,          *
    00109  * retornando o numero de registros afetados pelo comando.                 *
    00110  ***************************************************************************/
    00111 class TLPOSTGRESQL_DLL TePGConnection
    00112 {
    00113     protected:
    00114
    00115         PGconn *pg_connection_;  // A pointer to a connection
    00116         int int_connection_;     // A flag that indicates the state of a connection
    00117         Oid last_oid_;                                 // Always stores the last OID resulted of a command
    00118                       bool inTransaction_;
    00119                       bool isDateInt_;                 // Tells if server date format is int64 or double (IEEE754)
    00120
    00121     public:
    00122
    00123         // Constructor / Destructor
    00124         TePGConnection(const string& str_connection = "")
    00125                                  : pg_connection_(0), int_connection_(0), last_oid_(0), inTransaction_(false), isDateInt_(true)
    00126                       {
    00127                                  if(!str_connection.empty())
    00128                                             open(str_connection);
    00129                       }
    00130
    00131         virtual ~TePGConnection() { close(); }
    00132
    00133                       // Basic database methods
    00134         bool open(const string& str_connection);
    00135
    00136                       bool open(PGconn* conn);
    00137
    00138         bool state(void) const { return (PQstatus(pg_connection_) == CONNECTION_OK); }
    00139         void close(void);
    00140         const char* dbname(void) const { return PQdb(pg_connection_); }
    00141         const char* err_msg(void) const { return PQerrorMessage(pg_connection_); }
    00142         PGresult* exec(const string& str_qry) { return PQexec(pg_connection_, str_qry.c_str()); }
    00143         int exec_cmd(const string& str_qry);
    00144         Oid getOID(void) const { return last_oid_; }
    00145                       PGconn* c_ptr(void) { return pg_connection_; }
    00146
    00147                       bool isDateInt() const
    00148                       {
    00149                                  return isDateInt_;
    00150                       }
    00151
    00152                       // Utilities functions - You must destroy the return string
    00153                       static char* escapeString(const char* from, const size_t& fromLen, size_t& newLen)
    00154                       {
    00155                                  char *sql = new char[2 * fromLen + 1];
    00156
    00157                                  newLen = PQescapeString(sql, from, fromLen);
    00158
    00159                                  return sql;
    00160                       }
    00161
    00162                       static void freeMem(void* ptr)   { PQfreemem(ptr); }
    00163
    00164                       static unsigned char* escapeBytea(const unsigned char *from, size_t from_length, size_t* to_length) { return PQescapeBytea(from, from_length, to_length); }
    00165
    00166                       Oid insertBlob(char* buff, const int& blobSize);       // Returns 0 on error
    00167                       int getBlob(const Oid& blobId, char *&buff);                      // return -1 on error otherwise returns bytes read
    00168                       bool removeBlob(const Oid& blobId) { return lo_unlink(pg_connection_, blobId) == 1; }
    00169
    00170                       bool beginTransaction(void);
    00171                       bool commitTransaction(void);
    00172                       bool rollBackTransaction(void);
    00173
    00174                       int exec_cmd_params(const char *command,
    00175                                                                               int nParams,
    00176                                                                               const Oid *paramTypes,
    00177                                                                               const char * const *paramValues,
    00178                                                                               const int *paramLengths,
    00179                                                                               const int *paramFormats,
    00180                                                                               int resultFormat);
    00181
    00182                       std::string getClientEncoding();
    00183
    00184            protected:
    00185
    00186         // don't support copying of TePGConnection objects,
    00187         // so make copy constructor and assignment op private.
    00188         TePGConnection(const TePGConnection& c);
    00189         TePGConnection& operator=(const TePGConnection& c);
    00190 };
    00191
    00192 /***************************************************************************
    00193  * Classe resposnsavel pela manipulacao de dados resultantes de uma        *
    00194  * consulta.                                                               *
    00195  ***************************************************************************/
    00196 class TLPOSTGRESQL_DLL TePGRecordset
    00197 {
    00198            protected:
    00199
    00200                       static const int int_bof_;
    00201                       static int openRecordSets_;
    00202                       static set<int> freeCursorNumbers_;
    00203                       static TeMutex _mutexLock;
    00204
    00205         PGresult *pg_recordset_;
    00206                       TePGConnection* conn_;
    00207                       bool cursorDeclared_;
    00208         int int_index_current_;
    00209         int int_eof_;
    00210                       TeCursorType cursorType_;
    00211                       TeCursorLocation cursorLocation_;
    00212                       TeCursorDataType cursorDataType_;
    00213                       int numRowsToRetrieve_;
    00214
    00215                       int recordSetId_;
    00216                       bool isLittleEndian_;
    00217
    00218                       string data_;
    00219
    00220                       bool movingBackward_; // Mario
    00221                       bool lastFetch;                             // Mario
    00222                       bool firstFetch;                 // Mario
    00223
    00224
    00225     public:
    00226
    00227         // Constructor / Destructor
    00228         TePGRecordset(const string& str_qry = string(""), TePGConnection* con_x = 0,
    00229                                            const TeCursorType& cursorType = TeUNIDIRECTIONAL,
    00230                                                   const TeCursorLocation& cursorLocation = TeSERVERSIDE,
    00231                                                   const TeCursorDataType& cursorDataType = TeTEXTCURSOR,
    00232                                                          const int& numRowsToRetrieve = 2000);
    00233         virtual ~TePGRecordset();
    00234
    00235         // Basic database methods
    00236                       void close(void);
    00237
    00238         int recordCount(void) const
    00239                       {
    00240                                  if(pg_recordset_)
    00241                                             return PQntuples(pg_recordset_);
    00242
    00243                                  return 0;
    00244                       }
    00245
    00246                       int getFieldCount(void) const    { return PQnfields(pg_recordset_); }
    00247
    00248                       bool state(void) const
    00249                       {
    00250                                  if(pg_recordset_)
    00251                                             return true;
    00252                                  else
    00253                                             return false;
    00254                       }
    00255
    00256                       bool eof(void) const { return int_index_current_ == int_eof_; }
    00257         bool bof(void) const { return int_index_current_ == int_bof_; }
    00258
    00259                       bool moveFirst(void);
    00260         bool movePrevious(void);
    00261         bool moveNext(void);
    00262         bool moveLast(void);
    00263         bool moveTo(const int& lin_number); // first index == 0
    00264
    00265                       int index(void) const
    00266                       {
    00267                                  if(!(this->bof() || this->eof()))
    00268                                             return int_index_current_;
    00269
    00270                                  return -1;
    00271                       }
    00272
    00273                bool open(const string& str_qry, TePGConnection* con_x,
    00274                                        const TeCursorType& cursorType = TeUNIDIRECTIONAL,
    00275                                               const TeCursorLocation& cursorLocation = TeSERVERSIDE,
    00276                                               const TeCursorDataType& cursorDataType = TeTEXTCURSOR,
    00277                                               const int& numRowsToRetrieve = 2000);
    00278
    00279
    00280
    00281                       // Functions tha apllies to columns
    00282                       char *fieldName(const int& field_num) const { return PQfname(pg_recordset_, field_num); }
    00283
    00284         int fieldNum(const string& field_name) const
    00285                       {
    00286                                  int num = PQfnumber(pg_recordset_, field_name.c_str());
    00287
    00288                                  if(num < 0)
    00289                                  {
    00290                                             std::string::size_type ip = field_name.rfind('.');
    00291
    00292                                             if(ip == std::string::npos)
    00293                                                        return num;
    00294
    00295                                             std::string::size_type len = field_name.size();
    00296
    00297                                             std::string fieldName = field_name.substr(ip + 1, len - ip - 1);
    00298
    00299                                             num = PQfnumber(pg_recordset_, fieldName.c_str());
    00300                                  }
    00301
    00302                                  return num;
    00303                       }
    00304
    00305                       Oid fieldType(const int& field_num) const { return PQftype(pg_recordset_, field_num); }
    00306         Oid fieldType(const string& field_name) const { return fieldType(fieldNum(field_name)); }
    00307
    00308                       bool isNull(const int& field_num) const { return PQgetisnull(pg_recordset_, index(), field_num) == 1; }
    00309                       bool isNull(const string& field_name) const { return isNull(fieldNum(field_name)); }
    00310
    00311                       int fieldSize(const int& field_num);
    00312         int fieldSize(const string& field_name) { return fieldSize(fieldNum(field_name)); }
    00313
    00314         int fieldSizeFractionaryPart(const int& field_num);
    00315         int fieldSizeFractionaryPart(const string& field_name) {  return fieldSizeFractionaryPart(fieldNum(field_name)); }
    00316
    00317
    00318                       // Datatype functions
    00319
    00320                       // when you use value, make sure to copy the value, otherwise, a sucessive call may destroy the pointer
    00321                       char* value(const int& field_num) const { return PQgetvalue(pg_recordset_, int_index_current_, field_num); }
    00322                       char* value(const string& field_name) const { return value(fieldNum(field_name)); }
    00323
    00324                       int getBytea(const int& field_num, char*& buff) const;
    00325                       int getBytea(const string& field_name, char*& buff) const { return getBytea(fieldNum(field_name), buff); }
    00326
    00327                       int getInt(const int& field_num) const
    00328                       {
    00329                                  if(cursorDataType_ == TeTEXTCURSOR)
    00330                                             return atol(value(field_num));
    00331                                  else
    00332                                  {
    00333                                             if(fieldType(field_num) == PG_INT8_TYPE)
    00334                                             {
    00335                                                        return getInt8(field_num);
    00336                                             }
    00337                                             else
    00338                                             {
    00339                                                        unsigned int number;
    00340
    00341                                                        memcpy(&number, value(field_num), sizeof(int));
    00342
    00343                                                        if(isLittleEndian_)
    00344                                                                   number = ntohl(number);
    00345
    00346                                                        return number;
    00347                                             }
    00348                                  }
    00349                       }
    00350
    00351                       int getInt(const string& field_name) const { return getInt(fieldNum(field_name)); }
    00352
    00353                       int getInt8(const int& field_num) const ;
    00354                       int getInt8(const string& field_name) const { return getInt8(fieldNum(field_name)); }
    00355
    00356                       bool getBool(const int& field_num) const
    00357                       {
    00358                                  if(cursorDataType_ == TeTEXTCURSOR)
    00359                                  {
    00360                                             string t = "t";
    00361
    00362                                             return (t == value(field_num));
    00363                                  }
    00364                                  else
    00365                                  {
    00366                                             unsigned char v = value(field_num)[0];
    00367                                             int v1 = v;
    00368                                             return v1 != 0;
    00369                                  }
    00370                       }
    00371
    00372                       bool getBool(const string& field_name) const { return getBool(fieldNum(field_name)); }
    00373
    00374                       double getDouble(const int& field_num) const
    00375                       {
    00376                                  if(cursorDataType_ == TeTEXTCURSOR)
    00377                                             return atof(value(field_num));
    00378                                  else
    00379                                  {
    00380                                             union
    00381                                             {
    00382                                                        double dWord_;
    00383                                                        unsigned int aux_[2];
    00384                                             } swapDouble1, swapDouble2;
    00385
    00386
    00387                                             // endianness test
    00388                                             if(isLittleEndian_)
    00389                                             {
    00390                                                        // little-endian!
    00391                                                        memcpy(&swapDouble1.dWord_, value(field_num), sizeof(double));
    00392
    00393                                                        swapDouble2.aux_[1] = ntohl(swapDouble1.aux_[0]);
    00394                                                        swapDouble2.aux_[0] = ntohl(swapDouble1.aux_[1]);
    00395
    00396                                                        return swapDouble2.dWord_;
    00397                                             }
    00398                                             else
    00399                                             {
    00400                                                        // big-endian!
    00401                                                        memcpy(&swapDouble1.dWord_, value(field_num), sizeof(double));
    00402
    00403                                                        swapDouble2.aux_[0] = ntohl(swapDouble1.aux_[0]);
    00404                                                        swapDouble2.aux_[1] = ntohl(swapDouble1.aux_[1]);
    00405
    00406                                                        return swapDouble2.dWord_;
    00407                                             }
    00408
    00409                                  }
    00410                       }
    00411
    00412                       double getDouble(const string& field_name) const { return getDouble(fieldNum(field_name)); }
    00413
    00414                       string getDate(const int& field_num) const;
    00415                       string getDate(const string& field_name) const { return getDate(fieldNum(field_name)); }
    00416
    00417                       string getTime(const int& field_num);
    00418                       string getTime(const string& field_name) { return getTime(fieldNum(field_name)); }
    00419
    00420                       string getTimeStamp(const int& field_num);
    00421                       string getTimeStamp(const string& field_name) { return getTimeStamp(fieldNum(field_name)); }
    00422
    00423
    00424
    00425                       char* getData(const int& field_num);
    00426                       char* getData(const string& field_name) { return getData(fieldNum(field_name)); }
    00427
    00428                       // TerraLib Geometric Types
    00429                       void getByteALine2D(const int& field_num, TeLine2D& l) const;
    00430                       void getByteALine2D(const string& field_name, TeLine2D& l) const { getByteALine2D(fieldNum(field_name), l); }
    00431
    00432                       // PostgreSQL Geometric types
    00433                       void getPGBox(const int& field_num, TeBox& b) const;
    00434                       void getPGBox(const string& field_name, TeBox& b) const { getPGBox(fieldNum(field_name), b); }
    00435
    00436                       void getPGLine2D(const int& field_num, TeLine2D& l) const;
    00437                       void getPGLine2D(const string& field_name, TeLine2D& l) const { getPGLine2D(fieldNum(field_name), l); }
    00438
    00439                       // PostGIS Methods
    00440                       void getPGISPoint(const int& field_num, TePoint& p) const;
    00441                       void getPGISPoint(const string& field_name, TePoint& p) const { getPGISPoint(fieldNum(field_name), p); }
    00442
    00443                       void getPGISLine(const int& field_num, TeLine2D& l) const;
    00444                       void getPGISLine(const string& field_name, TeLine2D& l) const { getPGISLine(fieldNum(field_name), l); }
    00445
    00446                       void getPGISPolygon(const int& field_num, TePolygon& p) const;
    00447                       void getPGISPolygon(const string& field_name, TePolygon& p) const { getPGISPolygon(fieldNum(field_name), p); }
    00448
    00449                       void getPGISMultiPoint(const int& field_num, TePointSet& ps) const;
    00450                       void getPGISMultiPoint(const string& field_name, TePointSet& ps) const { getPGISMultiPoint(fieldNum(field_name), ps); }
    00451
    00452                       void getPGISMultiLine(const int& field_num, TeLineSet& ls) const;
    00453                       void getPGISMultiLine(const string& field_name, TeLineSet& ls) const { getPGISMultiLine(fieldNum(field_name), ls); }
    00454
    00455                       void getPGISMultiPolygon(const int& field_num, TePolygonSet& ps) const;
    00456                       void getPGISMultiPolygon(const string& field_name, TePolygonSet& ps) const { getPGISMultiPolygon(fieldNum(field_name), ps); }
    00457
    00458                       void getPGISGeomColl(const int& field_num, TeMultiGeometry& m) const;
    00459                       void getPGISGeomColl(const string& field_name, TeMultiGeometry& m) const { getPGISGeomColl(fieldNum(field_name), m); }
    00460
    00461            protected:
    00462
    00463         // don't support copying of TePGRecordset objects,
    00464         // so make copy constructor and assignment op private.
    00465         TePGRecordset(const TePGRecordset& c);
    00466         TePGRecordset& operator=(const TePGRecordset& c);
    00467
    00468                       static int getFreeCursor()
    00469                       {
    00470                                  _mutexLock.lock();
    00471
    00472                                  int freeId = 0;
    00473                                  if(freeCursorNumbers_.empty())
    00474                                  {          // Se n�o houver cursores livres aberto => criar novo id
    00475                                             ++openRecordSets_;
    00476                                             freeId = openRecordSets_;
    00477                                  }
    00478                                  else
    00479                                  {
    00480                                             set<int>::iterator it = freeCursorNumbers_.begin();
    00481                                             freeId = *it;
    00482                                             freeCursorNumbers_.erase(it);
    00483                                  }
    00484
    00485                                  _mutexLock.unLock();
    00486
    00487                                  return freeId;
    00488                       }
    00489                       static void releaseCursor(const int& idToRelease)
    00490                       {
    00491                                  _mutexLock.lock();
    00492                                  freeCursorNumbers_.insert(idToRelease);
    00493                                  _mutexLock.unLock();
    00494                       }
    00495
    00496                       void freeRecordSet();
    00497
    00498 //method modified from Terralib5 used for EWKB compatibility
    00499                       char* getWKBHeader(char* v, unsigned char &byteOrder, unsigned int& wkbType, unsigned int &numGeometries, int& srid) const;
    00500
    00501                       char* getWKBPoint(char* v, TePoint& p) const;
    00502                       char* getWKBLine(char* v, TeLine2D& l) const;
    00503                       char* getWKBPolygon(char* v, TePolygon& p) const;
    00504
    00505                       char* getWKBMultiPoint(char* v, TePointSet &ps) const;
    00506                       char* getWKBMultiLine(char* v, TeLineSet &ls) const;
    00507                       char* getWKBMultiPolygon(char* v, TePolygonSet &ps) const;
    00508
    00509                       void getWKBGeomColl(char* v, TeMultiGeometry &mg) const;
    00510
    00511         char* getWKBLinearRing(char* v, int byteOrder, TeLine2D &line) const;
    00512 };
    00513
    00514 TLPOSTGRESQL_DLL char* TeLine2DToPGBinary(const TeLine2D &line, unsigned int &size);
    00515 TLPOSTGRESQL_DLL char* TeBoxToPGBinary(const TeBox &box, unsigned int &size);
    00516
    00517 TLPOSTGRESQL_DLL char* TePointToWKBPoint(const TePoint &point, unsigned int &size);
    00518 TLPOSTGRESQL_DLL char* TeLine2DToWKBLineString(const TeLine2D &line, unsigned int &size);
    00519 TLPOSTGRESQL_DLL char* TePolygonToWKBPolygon(const TePolygon &polygon, unsigned int &size);
    00520
    00521 TLPOSTGRESQL_DLL double TeConvertToBigEndian(const double &value);
    00522
    00523 TLPOSTGRESQL_DLL void TeConvert2OGCWKBType(unsigned int& gType, bool& isPostGIS);
    00524 TLPOSTGRESQL_DLL void TeConvert2PostGISWKBType(unsigned int& gType);
    00525
    00526
    00527 #endif     //  __TERRALIB_INTERNAL_PGINTERFACE_H

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines