1
/************************************************************************************
2
TerraLib - a library for developing GIS applications.
3
Copyright � 2001-2004 INPE and Tecgraf/PUC-Rio.
5
This code is part of the TerraLib library.
6
This library is free software; you can redistribute it and/or
7
modify it under the terms of the GNU Lesser General Public
8
License as published by the Free Software Foundation; either
9
version 2.1 of the License, or (at your option) any later version.
11
You should have received a copy of the GNU Lesser General Public
12
License along with this library.
14
The authors reassure the license terms regarding the warranties.
15
They specifically disclaim any warranties, including, but not limited to,
16
the implied warranties of merchantability and fitness for a particular purpose.
17
The library provided hereunder is on an "as is" basis, and the authors have no
18
obligation to provide maintenance, support, updates, enhancements, or modifications.
19
In no event shall INPE and Tecgraf / PUC-Rio be held liable to any party for direct,
20
indirect, special, incidental, or consequential damages arising out of the use
21
of this library and its documentation.
22
*************************************************************************************/
25
* TODO: 1. N�O PEGAR O DOBRO DE REGISTROS NA VOLTA (MOVE PREVIOUS) NO FUTURO!!!!
29
#include "TePGInterface.h"
30
#include "TePGUtils.h"
39
* Read/write mode flags for inversion (large object) calls
42
#define INV_WRITE 0x00020000
43
#define INV_READ 0x00040000
51
* PostgreSQL Geometric Types
60
/*******************************
61
* FUN��ES AUXILIARES *
62
*******************************/
63
// This function is the same parse_hex function in PostGIS rc3 source code.
64
inline unsigned char parse_hex(char *str)
66
//do this a little brute force to make it faster
68
unsigned char result_high = 0;
69
unsigned char result_low = 0;
173
return (unsigned char) ((result_high<<4) + result_low);
177
/*******************************
178
* Definicao de TePGConnection *
179
*******************************/
180
bool TePGConnection::open(const string& str_connection)
184
pg_connection_ = PQconnectdb(str_connection.c_str());
195
void TePGConnection::close(void)
201
PQfinish(pg_connection_);
210
int TePGConnection::exec_cmd(const string& str_qry)
212
PGresult *result_temp;
214
result_temp = PQexec(pg_connection_, str_qry.c_str());
216
switch (PQresultStatus(result_temp))
218
case PGRES_EMPTY_QUERY: // The string sent to the backend was empty.
220
case PGRES_COMMAND_OK: // Successful completion of a command returning no data
221
resp = atoi(PQcmdTuples(result_temp));
222
last_oid_ = PQoidValue(result_temp);
224
case PGRES_TUPLES_OK: // The query successfully executed
227
case PGRES_COPY_OUT: // Copy Out (from server) data transfer started
228
case PGRES_COPY_IN: // Copy In (to server) data transfer started
231
case PGRES_BAD_RESPONSE: // The server's response was not understood
232
case PGRES_NONFATAL_ERROR: // TODO: Is this one really an error?
233
case PGRES_FATAL_ERROR:
234
throw runtime_error("The server's response was not understood");
237
throw logic_error("Internal lib TePGInterface error: ");
240
PQclear(result_temp);
245
Oid TePGConnection::insertBlob(char* buff, const int& blobSize)
250
Oid obj_oid = lo_creat(pg_connection_, INV_READ | INV_WRITE);
252
int fd = lo_open(pg_connection_, obj_oid, INV_READ);
259
int size_tmp = blobSize;
263
if((size_tmp - BUFFSIZE) >= 0)
264
nbwrite = lo_write(pg_connection_, fd, buff, BUFFSIZE);
266
nbwrite = lo_write(pg_connection_, fd, buff, size_tmp);
275
if(lo_close(pg_connection_, fd) == 0)
281
int TePGConnection::getBlob(const Oid& blobId, char *&buff)
283
int fd = lo_open(pg_connection_, blobId, INV_READ);
288
int len = lo_lseek(pg_connection_, fd, 0, SEEK_END);
290
lo_lseek(pg_connection_, fd, 0, SEEK_SET);
296
buff = new char[len];
298
char* buffAux = buff;
302
while((nbread = lo_read(pg_connection_, fd, buffAux, BUFFSIZE)) > 0)
308
bool TePGConnection::beginTransaction(void)
313
if(exec_cmd("BEGIN TRANSACTION") == 0)
315
inTransaction_ = true;
324
bool TePGConnection::commitTransaction(void)
326
if(exec_cmd("COMMIT TRANSACTION") == 0)
328
inTransaction_ = false;
336
bool TePGConnection::rollBackTransaction(void)
338
if(exec_cmd("ROLLBACK TRANSACTION") == 0)
340
inTransaction_ = false;
349
/******************************
350
* Definicao de TePGRecordset *
351
******************************/
352
const int TePGRecordset::int_bof_ = -1;
353
int TePGRecordset::openRecordSets_ = 0;
354
set<int> TePGRecordset::freeCursorNumbers_;
355
//const int TePGRecordset::numRowsToRetrieve_ = 2000;
357
TePGRecordset::TePGRecordset(const string& str_qry, TePGConnection* con_x,
358
const TeCursorType& cursorType,
359
const TeCursorLocation& cursorLocation,
360
const TeCursorDataType& cursorDataType,
361
const int& numRowsToRetrieve)
362
: pg_recordset_(0), conn_(con_x), cursorDeclared_(false), int_index_current_(-1),
363
int_eof_(-1), cursorType_(cursorType), cursorLocation_(cursorLocation),
364
cursorDataType_(cursorDataType), numRowsToRetrieve_(numRowsToRetrieve)
367
if(((unsigned int) 1) == htonl((unsigned int) 1))
368
isLittleEndian_ = false;
370
isLittleEndian_ = true;
372
if(freeCursorNumbers_.empty())
373
{ // Se n�o houver cursores livres aberto => criar novo id
375
recordSetId_ = openRecordSets_;
379
set<int>::iterator it = freeCursorNumbers_.begin();
381
freeCursorNumbers_.erase(it);
384
if(!str_qry.empty() && conn_)
385
open(str_qry, conn_, cursorType_, cursorLocation_, cursorDataType_);
388
TePGRecordset::~TePGRecordset()
391
freeCursorNumbers_.insert(recordSetId_);
396
void TePGRecordset::close(void)
398
if(cursorDeclared_ && conn_)
400
string sqlCloseCursor = "CLOSE CURSOR_";
401
sqlCloseCursor += Te2String(recordSetId_);
403
conn_->exec_cmd(sqlCloseCursor.c_str());
408
cursorDeclared_ = false;
415
bool TePGRecordset::moveFirst(void)
420
if(cursorLocation_ == TeCLIENTESIDE)
422
if(recordCount() > 0)
424
int_index_current_ = 0;
434
string moveFirstSQL = "MOVE ABSOLUTE 0 IN CURSOR_";
435
moveFirstSQL += Te2String(recordSetId_);
437
int res = conn_->exec_cmd(moveFirstSQL.c_str());
443
string fetchSQL = "FETCH FORWARD " + Te2String(numRowsToRetrieve_);
444
fetchSQL += " FROM CURSOR_";
445
fetchSQL += Te2String(recordSetId_);
447
pg_recordset_ = conn_->exec(fetchSQL.c_str());
449
if(PQresultStatus(pg_recordset_) == PGRES_TUPLES_OK)
451
if(recordCount() > 0)
453
int_eof_ = recordCount();
454
int_index_current_ = 0;
466
bool TePGRecordset::movePrevious(void)
468
//if(!cursorDeclared_ || (cursorType_ == TeUNIDIRECTIONAL))
472
if(cursorLocation_ == TeCLIENTESIDE)
478
--int_index_current_;
483
if(recordCount() > 0)
486
string fetchSQL = "";
493
--int_index_current_;
497
movingBackward_ = true;
499
int val = recordCount() - 1;
506
move = " MOVE BACKWARD "+Te2String(val)+" FROM CURSOR_"+Te2String(recordSetId_)+";";
509
fetchSQL += " FETCH BACKWARD ";
510
fetchSQL += Te2String(numRowsToRetrieve_);
511
fetchSQL += " FROM CURSOR_";
512
fetchSQL += Te2String(recordSetId_);
524
++int_index_current_;
528
fetchSQL = "FETCH BACKWARD ";
529
fetchSQL += Te2String(numRowsToRetrieve_);
530
fetchSQL += " FROM CURSOR_";
531
fetchSQL += Te2String(recordSetId_);
538
pg_recordset_ = conn_->exec(fetchSQL.c_str());
540
if(PQresultStatus(pg_recordset_) == PGRES_TUPLES_OK)
545
if(this->recordCount() > 0)
547
int_eof_ = recordCount();
548
int_index_current_ = 0;
550
if(this->recordCount() > 0 != numRowsToRetrieve_)
567
bool TePGRecordset::moveNext(void)
572
if(cursorLocation_ == TeCLIENTESIDE)
577
++int_index_current_;
582
if((recordCount() > 0))
585
string fetchSQL = "";
591
++int_index_current_;
595
fetchSQL = "FETCH FORWARD ";
596
fetchSQL += Te2String(numRowsToRetrieve_);
597
fetchSQL += " FROM CURSOR_";
598
fetchSQL += Te2String(recordSetId_);
610
--int_index_current_;
614
movingBackward_ = false;
615
int val = recordCount() -1;
620
move = " MOVE FORWARD "+Te2String(val)+" FROM CURSOR_"+Te2String(recordSetId_)+";";
624
fetchSQL += "FETCH FORWARD ";
625
fetchSQL += Te2String(numRowsToRetrieve_);
626
fetchSQL += " FROM CURSOR_";
627
fetchSQL += Te2String(recordSetId_);
637
pg_recordset_ = conn_->exec(fetchSQL.c_str());
639
if(PQresultStatus(pg_recordset_) == PGRES_TUPLES_OK)
644
if(recordCount() > 0)
646
int_eof_ = recordCount();
647
int_index_current_ = 0;
649
if(this->recordCount() > 0 != numRowsToRetrieve_)
664
bool TePGRecordset::moveLast(void)
666
//if(!cursorDeclared_ || (cursorType_ == TeUNIDIRECTIONAL))
670
if(cursorLocation_ == TeCLIENTESIDE)
672
if(recordCount() > 0)
674
int_index_current_ = recordCount() - 1;
686
string fetchSQL = "FETCH LAST FROM CURSOR_";
687
fetchSQL += Te2String(recordSetId_);
689
pg_recordset_ = conn_->exec(fetchSQL.c_str());
691
if(PQresultStatus(pg_recordset_) == PGRES_TUPLES_OK)
693
if(this->recordCount() > 0)
695
int_eof_ = recordCount();
696
int_index_current_ = 0;
707
bool TePGRecordset::moveTo(const int& lin_number)
709
//if(!cursorDeclared_ || (cursorType_ == TeUNIDIRECTIONAL))
713
if(cursorLocation_ == TeCLIENTESIDE)
715
if((lin_number > int_bof_) && (lin_number < int_eof_))
717
int_index_current_ = lin_number;
729
string fetchSQL = "FETCH ABSOLUTE ";
730
fetchSQL += Te2String(lin_number);
731
fetchSQL += " FROM CURSOR_";
732
fetchSQL += Te2String(recordSetId_);
734
pg_recordset_ = conn_->exec(fetchSQL.c_str());
736
if(PQresultStatus(pg_recordset_) == PGRES_TUPLES_OK)
738
if(this->recordCount() > 0)
740
int_eof_ = recordCount();
741
int_index_current_ = 0;
751
bool TePGRecordset::open(const string& str_qry, TePGConnection* con_x,
752
const TeCursorType& cursorType,
753
const TeCursorLocation& cursorLocation,
754
const TeCursorDataType& cursorDataType,
755
const int& numRowsToRetrieve)
759
if(str_qry.empty() || !con_x)
762
cursorType_ = cursorType;
763
cursorLocation_ = cursorLocation;
764
cursorDataType_ = cursorDataType;
765
numRowsToRetrieve_ = numRowsToRetrieve;
766
cursorDeclared_ = false;
768
movingBackward_ = false;
772
string sqlCursor = "DECLARE CURSOR_";
773
sqlCursor += Te2String(recordSetId_);
774
sqlCursor += (cursorDataType_ == TeBINARYCURSOR) ? " BINARY " : " ";
775
//sqlCursor += (cursorType_ == TeUNIDIRECTIONAL) ? " NO " : " ";
776
sqlCursor += "SCROLL CURSOR WITH HOLD FOR ";
777
sqlCursor += str_qry;
779
pg_recordset_ = conn_->exec(sqlCursor.c_str());
781
if(PQresultStatus(pg_recordset_) == PGRES_COMMAND_OK)
783
cursorDeclared_ = true;
785
string numRows = (cursorLocation_ == TeSERVERSIDE) ? Te2String(numRowsToRetrieve_) : string("ALL");
787
string fetchSQL = "FETCH FORWARD " + numRows;
788
fetchSQL += " FROM CURSOR_";
789
fetchSQL += Te2String(recordSetId_);
791
pg_recordset_ = conn_->exec(fetchSQL.c_str());
793
if(PQresultStatus(pg_recordset_) == PGRES_TUPLES_OK)
795
if(recordCount() > 0)
797
int_eof_ = recordCount();
798
int_index_current_ = 0;
810
int TePGRecordset::getBytea(const int& field_num, char*& buff) const
812
if(cursorDataType_ == TeTEXTCURSOR)
816
unsigned char* ptData = PQunescapeBytea((unsigned char*)(value(field_num)), &newLen);
822
buff = new char[newLen];
824
memcpy(buff, ptData, newLen);
826
TePGConnection::freeMem(ptData);
830
else // TeBINARYCURSOR
832
char* ptData = value(field_num);
834
unsigned int numBytes;
835
memcpy(&numBytes, ptData, sizeof(int));
836
numBytes = ntohl(numBytes);
839
buff = new char[numBytes];
841
memcpy(buff, ptData + sizeof(int), numBytes);
847
void TePGRecordset::getPGLine2D(const int& field_num, TeLine2D& l) const
849
char* polygon = value(field_num);
851
if(cursorDataType_ == TeBINARYCURSOR)
854
memcpy(&numPts, polygon, sizeof(int));
855
numPts = ntohl(numPts);
859
// POINT ARRAY IS SUPPOSED ALWAYS IN BIG ENDIAN
860
BIN_PG_POINT* pts = (BIN_PG_POINT*)(polygon + sizeof(int));
868
unsigned int aux_[2];
869
} swapx1, swapy1, swapx2, swapy2;
872
for(unsigned int i = 0; i < numPts ; ++i)
874
swapx1.dWord_ = pts[i].x;
875
swapy1.dWord_ = pts[i].y;
877
swapx2.aux_[1] = ntohl(swapx1.aux_[0]);
878
swapx2.aux_[0] = ntohl(swapx1.aux_[1]);
880
swapy2.aux_[1] = ntohl(swapy1.aux_[0]);
881
swapy2.aux_[0] = ntohl(swapy1.aux_[1]);
883
l.add(TeCoord2D(swapx2.dWord_, swapy2.dWord_));
890
for(unsigned int i = 0; i < numPts ; ++i)
891
l.add(TeCoord2D(pts[i].x, pts[i].y));
896
l = PgGeomPolygon2Te(polygon);
899
char* TePGRecordset::getWKBHeader(char* v, unsigned char &byteOrder, unsigned int &wkbType, unsigned int &numGeometries) const
901
const int byteOrderPlusGeomType = sizeof(unsigned char) + sizeof(unsigned int);
903
if(cursorDataType_ == TeTEXTCURSOR)
905
unsigned char header [byteOrderPlusGeomType];
907
for (int t = 0; t < byteOrderPlusGeomType; ++t)
909
header[t] =(unsigned char) parse_hex(v) ;
913
memcpy(&byteOrder, header, sizeof(unsigned char));
914
memcpy(&wkbType, header + sizeof(unsigned char), sizeof(unsigned int));
918
memcpy(&byteOrder, v, sizeof(unsigned char));
919
memcpy(&wkbType, v + sizeof(unsigned char), sizeof(unsigned int));
921
v += byteOrderPlusGeomType;
925
// 0 = Big Endian (wkbXDR) e 1 = Little Endian (wkbNDR)
926
if((byteOrder == 0) && isLittleEndian_)
928
wkbType = ntohl(wkbType);
930
else if((byteOrder == 1) && !isLittleEndian_)
932
wkbType = htonl(wkbType);
937
if(wkbType > 1 && wkbType <= 7)
939
if(cursorDataType_ == TeTEXTCURSOR)
941
unsigned char qtd[sizeof(unsigned int)];
943
for(unsigned int t = 0; t < sizeof(unsigned int); ++t)
945
qtd[t] = (unsigned char)parse_hex(v);
949
memcpy(&numGeometries, qtd, sizeof(unsigned int));
953
memcpy(&numGeometries, v, sizeof(unsigned int));
954
v += sizeof(unsigned int);
957
// 0 = Big Endian (wkbXDR) e 1 = Little Endian (wkbNDR)
958
if((byteOrder == 0) && isLittleEndian_)
960
numGeometries = ntohl(numGeometries);
962
else if((byteOrder == 1) && !isLittleEndian_)
964
numGeometries = htonl(numGeometries);
971
char* TePGRecordset::getWKBPoint(char* v, TeCoord2D& c) const
973
unsigned char byteOrder;
974
unsigned int wkbType;
975
unsigned int numGeometries;
977
v = getWKBHeader(v, byteOrder, wkbType, numGeometries);
980
throw logic_error("Binary data doesn't supported!");
986
unsigned int aux_[2];
989
if(cursorDataType_ == TeTEXTCURSOR)
992
const int double2Size = 2 * sizeof(double);
993
unsigned char data[double2Size];
995
for(int t = 0; t < double2Size; ++t) // len/2
997
data[t] = (unsigned char)parse_hex(v);
1002
memcpy(&swapx1.dWord_, data , sizeof(double));
1003
memcpy(&swapy1.dWord_, data + sizeof(double), sizeof(double));
1007
memcpy(&swapx1.dWord_, v , sizeof(double));
1008
memcpy(&swapy1.dWord_, v + sizeof(double), sizeof(double));
1010
v += (sizeof(double) + sizeof(double)); // x + y
1013
// 0 = Big Endian (wkbXDR)
1014
if((byteOrder == 0) && isLittleEndian_)
1019
unsigned int aux_[2];
1022
swapx2.aux_[1] = ntohl(swapx1.aux_[0]);
1023
swapx2.aux_[0] = ntohl(swapx1.aux_[1]);
1025
swapy2.aux_[1] = ntohl(swapy1.aux_[0]);
1026
swapy2.aux_[0] = ntohl(swapy1.aux_[1]);
1033
else if((byteOrder == 1) && !isLittleEndian_)
1038
unsigned int aux_[2];
1041
swapx2.aux_[1] = htonl(swapx1.aux_[0]);
1042
swapx2.aux_[0] = htonl(swapx1.aux_[1]);
1044
swapy2.aux_[1] = htonl(swapy1.aux_[0]);
1045
swapy2.aux_[0] = htonl(swapy1.aux_[1]);
1060
char* TePGRecordset::getWKBLinearRing(char* v, int byteOrder, TeLine2D &line) const
1062
unsigned int numPoints;
1064
const int size2Double = sizeof(double) + sizeof(double); // x + y
1066
if(cursorDataType_ == TeTEXTCURSOR)
1068
unsigned char data[size2Double];
1070
for(unsigned int n = 0; n < sizeof(unsigned int); ++n)
1072
data[n] = (unsigned char)parse_hex(v);
1076
memcpy(&numPoints, data , sizeof(unsigned int));
1080
memcpy(&numPoints, v , sizeof(unsigned int));
1081
v += sizeof(unsigned int);
1084
// 0 = Big Endian (wkbXDR) e 1 = Little Endian (wkbNDR)
1085
if((byteOrder == 0) && isLittleEndian_)
1087
numPoints = ntohl(numPoints);
1089
else if((byteOrder == 1) && !isLittleEndian_)
1091
numPoints = htonl(numPoints);
1094
for(unsigned int i = 0; i < numPoints; ++i)
1099
unsigned int aux_[2];
1102
if(cursorDataType_ == TeTEXTCURSOR)
1104
unsigned char data[size2Double];
1106
for(int t = 0; t < size2Double; ++t) // len/2
1108
data[t] = (unsigned char)parse_hex(v);
1112
memcpy(&swapx1.dWord_, data , sizeof(double));
1113
memcpy(&swapy1.dWord_, data + sizeof(double), sizeof(double));
1117
memcpy(&swapx1.dWord_, v , sizeof(double));
1118
memcpy(&swapy1.dWord_, v + sizeof(double), sizeof(double));
1122
// 0 = Big Endian (wkbXDR)
1123
if((byteOrder == 0) && isLittleEndian_)
1128
unsigned int aux_[2];
1131
swapx2.aux_[1] = ntohl(swapx1.aux_[0]);
1132
swapx2.aux_[0] = ntohl(swapx1.aux_[1]);
1134
swapy2.aux_[1] = ntohl(swapy1.aux_[0]);
1135
swapy2.aux_[0] = ntohl(swapy1.aux_[1]);
1137
line.add(TeCoord2D(swapx2.dWord_, swapy2.dWord_));
1139
else if((byteOrder == 1) && !isLittleEndian_) //1 = Little Endian (wkbNDR)
1144
unsigned int aux_[2];
1147
swapx2.aux_[1] = htonl(swapx1.aux_[0]);
1148
swapx2.aux_[0] = htonl(swapx1.aux_[1]);
1150
swapy2.aux_[1] = htonl(swapy1.aux_[0]);
1151
swapy2.aux_[0] = htonl(swapy1.aux_[1]);
1153
line.add(TeCoord2D(swapx2.dWord_, swapy2.dWord_));
1157
line.add(TeCoord2D(swapx1.dWord_, swapy1.dWord_));
1165
char* TePGRecordset::getWKBLine(char* v, TeLine2D& l) const
1167
unsigned char byteOrder;
1168
unsigned int wkbType;
1169
unsigned int numPoints;
1171
v = getWKBHeader(v, byteOrder, wkbType, numPoints);
1174
throw logic_error("Binary data doesn't supported!");
1176
if(cursorDataType_ == TeTEXTCURSOR)
1178
// Volta duas vezes o n�mero de bytes do n�mero de geometrias lidos ao chamar getWKBHeader
1179
v = getWKBLinearRing(v - (sizeof(unsigned int) + sizeof(unsigned int)), byteOrder, l);
1183
// Volta o n�mero de bytes do n�mero de geometrias lidos ao chamar getWKBHeader
1184
v = getWKBLinearRing(v - sizeof(unsigned int), byteOrder, l);
1191
char* TePGRecordset::getWKBPolygon(char* v, TePolygon& p) const
1193
unsigned char byteOrder;
1194
unsigned int wkbType;
1195
unsigned int numRings;
1197
v = getWKBHeader(v, byteOrder, wkbType, numRings);
1200
throw logic_error("Binary data doesn't supported!");
1202
for(unsigned int i = 0; i < numRings; ++i)
1205
v = getWKBLinearRing(v, byteOrder, line);
1213
char* TePGRecordset::getWKBMultiPoint(char* v, TePointSet &ps) const
1215
unsigned char byteOrder;
1216
unsigned int wkbType;
1217
unsigned int num_wkbPoints;
1219
v = getWKBHeader(v, byteOrder, wkbType, num_wkbPoints);
1222
throw logic_error("Binary data doesn't supported!");
1224
for(unsigned int i = 0; i < num_wkbPoints; ++i)
1227
v = getWKBPoint(v, coord);
1234
char* TePGRecordset::getWKBMultiLine(char* v, TeLineSet &ls) const
1236
unsigned char byteOrder;
1237
unsigned int wkbType;
1238
unsigned int num_wkbLineStrings;
1240
v = getWKBHeader(v, byteOrder, wkbType, num_wkbLineStrings);
1243
throw logic_error("Binary data doesn't supported!");
1245
for(unsigned int i = 0; i < num_wkbLineStrings; ++i)
1248
v = getWKBLine(v, line);
1255
char* TePGRecordset::getWKBMultiPolygon(char* v, TePolygonSet &ps) const
1257
unsigned char byteOrder;
1258
unsigned int wkbType;
1259
unsigned int num_wkbPolygons;
1261
v = getWKBHeader(v, byteOrder, wkbType, num_wkbPolygons);
1264
throw logic_error("Binary data doesn't supported!");
1266
for(unsigned int i = 0; i < num_wkbPolygons; ++i)
1269
v = getWKBPolygon(v, poly);
1276
void TePGRecordset::getWKBGeomColl(char* v, TeMultiGeometry &mg) const
1278
unsigned char byteOrder;
1279
unsigned int wkbType;
1280
unsigned int num_wkbGeometries;
1282
v = getWKBHeader(v, byteOrder, wkbType, num_wkbGeometries);
1285
throw logic_error("Binary data doesn't supported!");
1287
for(unsigned int i = 0; i < num_wkbGeometries; ++i)
1289
unsigned int geomType;
1290
unsigned char geomByteOrder;
1291
unsigned int num_geometries;
1293
getWKBHeader(v, geomByteOrder, geomType, num_geometries);
1299
v = getWKBPoint(v, coord);
1301
mg.addGeometry(coord);
1303
else if(geomType == 2)
1307
v = getWKBLine(v, line);
1309
mg.addGeometry(line);
1311
else if(geomType == 3)
1315
v = getWKBPolygon(v, poly);
1317
mg.addGeometry(poly);
1319
else if(geomType == 4)
1321
TePointSet pointSet;
1323
v = getWKBMultiPoint(v, pointSet);
1325
for(unsigned int a = 0; a < pointSet.size(); ++a)
1327
TePoint point = pointSet[a];
1328
mg.addGeometry(point);
1331
else if(geomType == 5)
1335
v = getWKBMultiLine(v, lineSet);
1337
for(unsigned int a = 0; a < lineSet.size(); ++a)
1339
TeLine2D coord = lineSet[a];
1341
mg.addGeometry(coord);
1344
else if(geomType == 6)
1346
TePolygonSet polygonSet;
1348
v = getWKBMultiPolygon(v, polygonSet);
1350
for(unsigned int a = 0; a < polygonSet.size(); ++a)
1352
TePolygon poly = polygonSet[a];
1354
mg.addGeometry(poly);
1359
throw logic_error("The data couldn't be decoded as a valid WKB geometry!");
1366
void TePGRecordset::getPGISPoint(const int& field_num, TePoint& p) const
1369
getWKBPoint(value(field_num), c);
1374
void TePGRecordset::getPGISLine(const int& field_num, TeLine2D& l) const
1376
getWKBLine(value(field_num), l);
1380
void TePGRecordset::getPGISPolygon(const int& field_num, TePolygon& p) const
1382
getWKBPolygon(value(field_num), p);
1386
void TePGRecordset::getPGISMultiPoint(const int& field_num, TePointSet& ps) const
1388
getWKBMultiPoint(value(field_num), ps);
1392
void TePGRecordset::getPGISMultiLine(const int& field_num, TeLineSet& ls) const
1394
getWKBMultiLine(value(field_num), ls);
1398
void TePGRecordset::getPGISMultiPolygon(const int& field_num, TePolygonSet& ps) const
1400
getWKBMultiPolygon(value(field_num), ps);
1404
void TePGRecordset::getPGISGeomColl(const int& field_num, TeMultiGeometry& m) const
1406
getWKBGeomColl(value(field_num), m);
1411
char* TePGRecordset::getData(const int& field_num)
1415
if(cursorDataType_ == TeTEXTCURSOR)
1416
return value(field_num);
1419
// chamar o conversor de tipo de dado de bin�rio p/ string p/ cada tipo!
1420
switch(fieldType(field_num))
1423
case PG_BYTEA_TYPE :
1426
case PG_INT2_TYPE : break;
1428
case PG_INT4_TYPE : data_ = Te2String(getInt(field_num));
1433
case PG_POINT_TYPE :
1437
case PG_POLYGON_TYPE :
1439
case PG_PG_FLOAT4_TYPE : break;
1441
case PG_FLOAT8_TYPE : data_ = Te2String(getDouble(field_num));
1444
case PG_CIRCLE_TYPE :
1445
case PG_MONEY_TYPE :
1446
case PG_BPCHAR_TYPE :
1447
case PG_VARCHAR_TYPE :
1450
case PG_TIMESTAMP_TYPE :
1451
case PG_TIMESTAMPTZ_TYPE :
1452
case PG_INTERVAL_TYPE :
1453
case PG_TIMETZ_TYPE :
1455
case PG_VARBIT_TYPE :
1456
case PG_NUMERIC_TYPE :
1460
return (char*)data_.c_str();
1464
int TePGRecordset::fieldSize(const int& field_num)
1466
Oid field_t = this->fieldType(field_num);
1467
Oid field_m = PQfmod(pg_recordset_, field_num);
1468
PGresult *result_temp;
1469
char str_int[5]; //integer part if DECIMAL(p,s) or NUMERIC(p,s)
1472
char str_field_t[50];
1473
char str_field_m[50];
1474
sprintf(str_field_t,"%d", field_t);
1475
sprintf(str_field_m,"%d", field_m);
1476
string str_qry = "SELECT format_type(";
1477
str_qry += str_field_t;
1479
str_qry += str_field_m;
1483
case 1043: //VARCHAR(s) or CHARACTER VARYING(s)
1484
case 1700: //NUMERIC(p,s) or DECIMAL(p,s)
1485
result_temp = PQexec(conn_->c_ptr(), str_qry.c_str());
1486
if(PQresultStatus(result_temp) == PGRES_TUPLES_OK)
1488
char *lin = PQgetvalue(result_temp, 0, 0); //Don't free lin because the return of PQgetvalue is in the struct PGResult
1490
while(*lin != '\0' && *lin != ',')
1492
if(*lin >= '0' && *lin <= '9' && i < 4)
1500
size = atoi(str_int);
1502
PQclear(result_temp);
1504
default: //The size of fixed size or for other variable size -1
1505
return PQfsize(pg_recordset_, field_num);
1511
int TePGRecordset::fieldSizeFractionaryPart(const int& field_num)
1513
Oid field_t = this->fieldType(field_num);
1514
Oid field_m = PQfmod(pg_recordset_, field_num);
1515
PGresult *result_temp;
1516
char str_frac[5]; //fractionary part if DECIMAL(p,s) or NUMERIC(p,s)
1519
char str_field_t[50];
1520
char str_field_m[50];
1521
sprintf(str_field_t,"%d", field_t);
1522
sprintf(str_field_m,"%d", field_m);
1523
string str_qry = "SELECT format_type(";
1524
str_qry += str_field_t;
1526
str_qry += str_field_m;
1530
case 1700: //NUMERIC(p,s) or DECIMAL(p,s)
1531
result_temp = PQexec(conn_->c_ptr(), str_qry.c_str());
1532
if(PQresultStatus(result_temp) == PGRES_TUPLES_OK)
1534
char *lin = PQgetvalue(result_temp, 0, 0); //Don't free lin because the return of PQgetvalue is in the struct PGResult
1536
while(*lin != '\0' && *lin != ',')
1546
if(*lin >= '0' && *lin <= '9' && i < 4)
1554
size = atoi(str_frac);
1556
PQclear(result_temp);
1558
default: //Others doesn't have a fractionary part
1566
void TePGRecordset::freeRecordSet()
1569
PQclear(pg_recordset_);
1573
int_index_current_ = -1;