00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "TePGInterface.h"
00031 #include "TePGUtils.h"
00032 #include <stdexcept>
00033 #include <string>
00034 #include <climits>
00035
00036 #include "../../kernel/TeUtils.h"
00037
00038
00039
00040
00041
00042 #define INV_WRITE 0x00020000
00043 #define INV_READ 0x00040000
00044
00045
00046
00047
00048 #define BUFFSIZE 1024
00049
00050
00051
00052
00053 typedef struct
00054 {
00055 double x, y;
00056 } BIN_PG_POINT;
00057
00058 using namespace std;
00059
00060
00061
00062
00063
00064 unsigned int TePGSwapUInt(const unsigned int& uintVal)
00065 {
00066 char uintIn[4], uintOut[4];
00067
00068 unsigned int outVal;
00069
00070 memcpy(uintIn,&uintVal,4);
00071
00072 uintOut[0] = uintIn[3];
00073 uintOut[1] = uintIn[2];
00074 uintOut[2] = uintIn[1];
00075 uintOut[3] = uintIn[0];
00076
00077 memcpy (&outVal,uintOut,4);
00078
00079 return outVal;
00080 }
00081
00082
00083
00084 inline unsigned char parse_hex(char *str)
00085 {
00086
00087
00088 unsigned char result_high = 0;
00089 unsigned char result_low = 0;
00090
00091 switch (str[0])
00092 {
00093 case '0' :
00094 result_high = 0;
00095 break;
00096 case '1' :
00097 result_high = 1;
00098 break;
00099 case '2' :
00100 result_high = 2;
00101 break;
00102 case '3' :
00103 result_high = 3;
00104 break;
00105 case '4' :
00106 result_high = 4;
00107 break;
00108 case '5' :
00109 result_high = 5;
00110 break;
00111 case '6' :
00112 result_high = 6;
00113 break;
00114 case '7' :
00115 result_high = 7;
00116 break;
00117 case '8' :
00118 result_high = 8;
00119 break;
00120 case '9' :
00121 result_high = 9;
00122 break;
00123 case 'A' :
00124 result_high = 10;
00125 break;
00126 case 'B' :
00127 result_high = 11;
00128 break;
00129 case 'C' :
00130 result_high = 12;
00131 break;
00132 case 'D' :
00133 result_high = 13;
00134 break;
00135 case 'E' :
00136 result_high = 14;
00137 break;
00138 case 'F' :
00139 result_high = 15;
00140 break;
00141 }
00142 switch (str[1])
00143 {
00144 case '0' :
00145 result_low = 0;
00146 break;
00147 case '1' :
00148 result_low = 1;
00149 break;
00150 case '2' :
00151 result_low = 2;
00152 break;
00153 case '3' :
00154 result_low = 3;
00155 break;
00156 case '4' :
00157 result_low = 4;
00158 break;
00159 case '5' :
00160 result_low = 5;
00161 break;
00162 case '6' :
00163 result_low = 6;
00164 break;
00165 case '7' :
00166 result_low = 7;
00167 break;
00168 case '8' :
00169 result_low = 8;
00170 break;
00171 case '9' :
00172 result_low = 9;
00173 break;
00174 case 'A' :
00175 result_low = 10;
00176 break;
00177 case 'B' :
00178 result_low = 11;
00179 break;
00180 case 'C' :
00181 result_low = 12;
00182 break;
00183 case 'D' :
00184 result_low = 13;
00185 break;
00186 case 'E' :
00187 result_low = 14;
00188 break;
00189 case 'F' :
00190 result_low = 15;
00191 break;
00192 }
00193 return (unsigned char) ((result_high<<4) + result_low);
00194 }
00195
00196
00197
00198 #define UNIX_EPOCH_JDATE 2440588
00199
00200 #define POSTGRES_EPOCH_JDATE 2451545
00201 #define MAXDATELEN 51
00202 #define MAXDATEFIELDS 25
00203
00204 typedef int TeDateADT;
00205 typedef long long int te_int64;
00206 typedef te_int64 te_pg_time_t;
00207
00208 typedef int te_fsec_t;
00209
00210
00211
00212 #define INT64CONST(x) ((te_int64) x##LL)
00213
00214
00215
00216
00217
00218 #define DT_NOBEGIN (-INT64CONST(0x7fffffffffffffff) - 1)
00219 #define DT_NOEND (INT64CONST(0x7fffffffffffffff))
00220
00221 #define TIMESTAMP_NOBEGIN(j) do {j = DT_NOBEGIN;} while (0)
00222 #define TIMESTAMP_IS_NOBEGIN(j) ((j) == DT_NOBEGIN)
00223
00224 #define TIMESTAMP_NOEND(j) do {j = DT_NOEND;} while (0)
00225 #define TIMESTAMP_IS_NOEND(j) ((j) == DT_NOEND)
00226
00227 #define TIMESTAMP_NOT_FINITE(j) (TIMESTAMP_IS_NOBEGIN(j) || TIMESTAMP_IS_NOEND(j))
00228
00229 #define TMODULO_INT64(t,q,u) \
00230 do { \
00231 q = (t / u); \
00232 if (q != 0) t -= (q * u); \
00233 } while(0)
00234
00235
00236
00237 struct te_pg_tm
00238 {
00239 int tm_sec;
00240 int tm_min;
00241 int tm_hour;
00242 int tm_mday;
00243 int tm_mon;
00244 int tm_year;
00245 int tm_wday;
00246 int tm_yday;
00247 int tm_isdst;
00248 long int tm_gmtoff;
00249 const char *tm_zone;
00250 };
00251
00252 inline void j2date(int jd, int *year, int *month, int *day)
00253 {
00254 unsigned int julian;
00255 unsigned int quad;
00256 unsigned int extra;
00257 int y;
00258
00259 julian = jd;
00260 julian += 32044;
00261 quad = julian / 146097;
00262 extra = (julian - quad * 146097) * 4 + 3;
00263 julian += 60 + quad * 3 + extra / 146097;
00264 quad = julian / 1461;
00265 julian -= quad * 1461;
00266 y = julian * 4 / 1461;
00267 julian = ((y != 0) ? ((julian + 305) % 365) : ((julian + 306) % 366))
00268 + 123;
00269 y += quad * 4;
00270 *year = y - 4800;
00271 quad = julian * 2141 / 65536;
00272 *day = julian - 7834 * quad / 256;
00273 *month = (quad + 10) % 12 + 1;
00274
00275 return;
00276 }
00277
00278
00279
00280
00281 inline bool EncodeDateOnly(struct te_pg_tm* tm, char *str)
00282 {
00283 if ((tm->tm_mon < 1) || (tm->tm_mon > 12))
00284 return false;
00285
00286
00287 if (tm->tm_year > 0)
00288 sprintf(str, "%04d-%02d-%02d",
00289 tm->tm_year, tm->tm_mon, tm->tm_mday);
00290 else
00291 sprintf(str, "%04d-%02d-%02d %s", -(tm->tm_year - 1), tm->tm_mon, tm->tm_mday, "BC");
00292
00293
00294 return true;
00295 }
00296
00297 inline int time2tm(te_int64 time, struct te_pg_tm * tm, te_fsec_t *fsec)
00298 {
00299 tm->tm_hour = (int)((time / INT64CONST(3600000000)));
00300 time -= (tm->tm_hour * INT64CONST(3600000000));
00301 tm->tm_min = (int)((time / INT64CONST(60000000)));
00302 time -= (tm->tm_min * INT64CONST(60000000));
00303 tm->tm_sec = (int)((time / INT64CONST(1000000)));
00304 time -= (tm->tm_sec * INT64CONST(1000000));
00305 *fsec = (te_fsec_t)time;
00306
00307 return 0;
00308 }
00309
00310
00311
00312
00313 inline bool EncodeTimeOnly(struct te_pg_tm * tm, te_fsec_t fsec, int *tzp, char *str)
00314 {
00315 if ((tm->tm_hour < 0) || (tm->tm_hour > 24))
00316 return false;
00317
00318 sprintf(str, "%02d:%02d", tm->tm_hour, tm->tm_min);
00319
00320
00321
00322
00323
00324
00325 if(fsec != 0)
00326 {
00327 sprintf((str + strlen(str)), ":%02d.%06d", tm->tm_sec, fsec);
00328
00329
00330 while ((strcmp((str + strlen(str) - 2), "00") == 0)
00331 && (*(str + strlen(str) - 3) != '.'))
00332 *(str + strlen(str) - 2) = '\0';
00333 }
00334 else
00335 sprintf((str + strlen(str)), ":%02d", tm->tm_sec);
00336
00337 if(tzp != NULL)
00338 {
00339 int hour,
00340 min;
00341
00342 hour = -(*tzp / 3600);
00343 min = ((abs(*tzp) / 60) % 60);
00344 sprintf((str + strlen(str)), ((min != 0) ? "%+03d:%02d" : "%+03d"), hour, min);
00345 }
00346
00347 return true;
00348 }
00349
00350 inline void TrimTrailingZeros(char *str)
00351 {
00352 size_t len = strlen(str);
00353
00354
00355 while ((*(str + len - 1) == '0') && (*(str + len - 3) != '.'))
00356 {
00357 len--;
00358 *(str + len) = '\0';
00359 }
00360 }
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374 inline bool EncodeDateTime(struct te_pg_tm * tm, te_fsec_t fsec, int *tzp, char ** , char *str)
00375 {
00376 int hour,
00377 min;
00378
00379 if ((tm->tm_mon < 1) || (tm->tm_mon > 12))
00380 return false;
00381
00382
00383
00384 sprintf(str, "%04d-%02d-%02d %02d:%02d",
00385 ((tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1)),
00386 tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min);
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396 if (fsec != 0)
00397 {
00398 sprintf((str + strlen(str)), ":%02d.%06d", tm->tm_sec, fsec);
00399 TrimTrailingZeros(str);
00400 }
00401 else
00402 sprintf((str + strlen(str)), ":%02d", tm->tm_sec);
00403
00404
00405
00406
00407
00408
00409
00410 if ((tzp != NULL) && (tm->tm_isdst >= 0))
00411 {
00412 hour = -(*tzp / 3600);
00413 min = ((abs(*tzp) / 60) % 60);
00414 sprintf((str + strlen(str)), ((min != 0) ? "%+03d:%02d" : "%+03d"), hour, min);
00415 }
00416
00417 if (tm->tm_year <= 0)
00418 sprintf((str + strlen(str)), " BC");
00419
00420 return true;
00421 }
00422
00423
00424
00425
00426
00427 inline bool EncodeSpecialTimestamp(te_int64 dt, char *str)
00428 {
00429 if (TIMESTAMP_IS_NOBEGIN(dt))
00430 strcpy(str, "-infinity");
00431 else if (TIMESTAMP_IS_NOEND(dt))
00432 strcpy(str, "infinity");
00433 else
00434 return false;
00435
00436 return true;
00437 }
00438
00439 inline void dt2time(te_int64 jd, int *hour, int *min, int *sec, te_fsec_t *fsec)
00440 {
00441
00442 te_int64 time;
00443
00444 time = jd;
00445
00446 *hour = (int)((time / INT64CONST(3600000000)));
00447 time -= ((*hour) * INT64CONST(3600000000));
00448 *min = (int)((time / INT64CONST(60000000)));
00449 time -= ((*min) * INT64CONST(60000000));
00450 *sec = (int)((time / INT64CONST(1000000)));
00451 *fsec = (te_fsec_t)(time - (*sec * INT64CONST(1000000)));
00452
00453 return;
00454 }
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466 bool timestamp2tm(te_int64 dt, int *tzp, struct te_pg_tm * tm, te_fsec_t *fsec, char **tzn)
00467 {
00468 te_int64 date;
00469 te_int64 time;
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482 time = dt;
00483
00484 TMODULO_INT64(time, date, INT64CONST(86400000000));
00485
00486 if (time < INT64CONST(0))
00487 {
00488 time += INT64CONST(86400000000);
00489 date -=1;
00490 }
00491
00492
00493 date +=POSTGRES_EPOCH_JDATE;
00494
00495
00496 if (date <0 || date > (te_int64) INT_MAX)
00497 return false;
00498
00499 j2date((int) date, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
00500 dt2time(time, &tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec);
00501
00502
00503 if (tzp == NULL)
00504 {
00505 tm->tm_isdst = -1;
00506 tm->tm_gmtoff = 0;
00507 tm->tm_zone = NULL;
00508 if (tzn != NULL)
00509 *tzn = NULL;
00510 return true;
00511 }
00512
00513 return false;
00514
00515 }
00516
00517
00518
00519
00520 bool TePGConnection::open(const string& str_connection)
00521 {
00522 close();
00523
00524 std::string test = str_connection;
00525
00526 pg_connection_ = PQconnectdb(str_connection.c_str());
00527
00528 if(this->state())
00529 {
00530 int_connection_ = 1;
00531
00532 string off = "off";
00533 string answer = PQparameterStatus(pg_connection_, "integer_datetimes");
00534
00535 if(answer == off)
00536 isDateInt_ = false;
00537
00538 return true;
00539 }
00540 else
00541 return false;
00542 }
00543
00544 bool TePGConnection::open(PGconn* conn)
00545 {
00546 pg_connection_ = conn;
00547
00548 if(this->state())
00549 {
00550 int_connection_ = 1;
00551
00552 string off = "off";
00553 string answer = PQparameterStatus(pg_connection_, "integer_datetimes");
00554
00555 if(answer == off)
00556 isDateInt_ = false;
00557
00558 return true;
00559 }
00560 return false;
00561 }
00562
00563 void TePGConnection::close(void)
00564 {
00565 if(int_connection_)
00566 {
00567 if(pg_connection_)
00568 {
00569 PQfinish(pg_connection_);
00570 }
00571 pg_connection_ = 0;
00572 int_connection_ = 0;
00573 }
00574 return;
00575 }
00576
00577
00578 int TePGConnection::exec_cmd(const string& str_qry)
00579 {
00580 PGresult *result_temp;
00581 int resp = -1;
00582 result_temp = PQexec(pg_connection_, str_qry.c_str());
00583
00584 switch (PQresultStatus(result_temp))
00585 {
00586 case PGRES_EMPTY_QUERY:
00587 break;
00588 case PGRES_COMMAND_OK:
00589 resp = atoi(PQcmdTuples(result_temp));
00590 last_oid_ = PQoidValue(result_temp);
00591 break;
00592 case PGRES_TUPLES_OK:
00593 break;
00594
00595 case PGRES_COPY_OUT:
00596 case PGRES_COPY_IN:
00597 break;
00598
00599 case PGRES_BAD_RESPONSE:
00600 case PGRES_NONFATAL_ERROR:
00601 case PGRES_FATAL_ERROR:
00602 throw runtime_error("The server's response was not understood");
00603
00604 default:
00605 throw logic_error("Internal lib TePGInterface error: ");
00606 }
00607
00608 PQclear(result_temp);
00609 result_temp = 0;
00610 return resp;
00611 }
00612
00613 Oid TePGConnection::insertBlob(char* buff, const int& blobSize)
00614 {
00615 if(!buff)
00616 return 0;
00617
00618 Oid obj_oid = lo_creat(pg_connection_, INV_READ | INV_WRITE);
00619
00620 int fd = lo_open(pg_connection_, obj_oid, INV_READ);
00621
00622 if(fd < 0)
00623 return 0;
00624
00625 int nbwrite = 0;
00626
00627 int size_tmp = blobSize;
00628
00629 while(size_tmp > 0)
00630 {
00631 if((size_tmp - BUFFSIZE) >= 0)
00632 nbwrite = lo_write(pg_connection_, fd, buff, BUFFSIZE);
00633 else
00634 nbwrite = lo_write(pg_connection_, fd, buff, size_tmp);
00635
00636 if(nbwrite <= 0)
00637 return 0;
00638
00639 buff += nbwrite;
00640 size_tmp -= nbwrite;
00641 }
00642
00643 if(lo_close(pg_connection_, fd) == 0)
00644 return obj_oid;
00645
00646 return 0;
00647 }
00648
00649 int TePGConnection::getBlob(const Oid& blobId, char *&buff)
00650 {
00651 int fd = lo_open(pg_connection_, blobId, INV_READ);
00652
00653 if(fd < 0)
00654 return -1;
00655
00656 int len = lo_lseek(pg_connection_, fd, 0, SEEK_END);
00657
00658 lo_lseek(pg_connection_, fd, 0, SEEK_SET);
00659
00660 if(len <= 0)
00661 return len;
00662
00663 if(!buff)
00664 buff = new char[len];
00665
00666 char* buffAux = buff;
00667
00668 int nbread = 0;
00669
00670 while((nbread = lo_read(pg_connection_, fd, buffAux, BUFFSIZE)) > 0)
00671 buffAux += nbread;
00672
00673 return len;
00674 }
00675
00676 bool TePGConnection::beginTransaction(void)
00677 {
00678 if(inTransaction_)
00679 return true;
00680
00681 if(exec_cmd("BEGIN TRANSACTION") == 0)
00682 {
00683 inTransaction_ = true;
00684
00685 return true;
00686 }
00687
00688 return false;
00689 }
00690
00691
00692 bool TePGConnection::commitTransaction(void)
00693 {
00694 if(exec_cmd("COMMIT TRANSACTION") == 0)
00695 {
00696 inTransaction_ = false;
00697
00698 return true;
00699 }
00700
00701 return false;
00702 }
00703
00704 bool TePGConnection::rollBackTransaction(void)
00705 {
00706 if(exec_cmd("ROLLBACK TRANSACTION") == 0)
00707 {
00708 inTransaction_ = false;
00709
00710 return true;
00711 }
00712
00713 return false;
00714 }
00715
00716 int TePGConnection::exec_cmd_params(const char *command,
00717 int nParams,
00718 const Oid *paramTypes,
00719 const char * const *paramValues,
00720 const int *paramLengths,
00721 const int *paramFormats,
00722 int resultFormat)
00723 {
00724 PGresult *result_temp;
00725 int resp = -1;
00726 result_temp = PQexecParams(pg_connection_,
00727 command,
00728 nParams,
00729 paramTypes,
00730 paramValues,
00731 paramLengths,
00732 paramFormats,
00733 resultFormat);
00734
00735
00736 switch (PQresultStatus(result_temp))
00737 {
00738 case PGRES_EMPTY_QUERY:
00739 break;
00740 case PGRES_COMMAND_OK:
00741 resp = atoi(PQcmdTuples(result_temp));
00742 last_oid_ = PQoidValue(result_temp);
00743 break;
00744 case PGRES_TUPLES_OK:
00745 break;
00746
00747 case PGRES_COPY_OUT:
00748 case PGRES_COPY_IN:
00749 break;
00750
00751 case PGRES_BAD_RESPONSE:
00752 case PGRES_NONFATAL_ERROR:
00753 case PGRES_FATAL_ERROR:
00754 throw runtime_error("The server's response was not understood");
00755
00756 default:
00757 throw logic_error("Internal lib TePGInterface error: ");
00758 }
00759
00760 PQclear(result_temp);
00761 result_temp = 0;
00762 return resp;
00763 }
00764
00765 std::string TePGConnection::getClientEncoding()
00766 {
00767 std::string clientEncoding = "";
00768
00769 PGresult* result = PQexec(pg_connection_, "SHOW client_encoding");
00770 if(PQresultStatus(result) == PGRES_TUPLES_OK)
00771 {
00772 clientEncoding = PQgetvalue(result, 0, 0);
00773 }
00774 PQclear(result);
00775 return clientEncoding;
00776 }
00777
00778
00779
00780
00781
00782 const int TePGRecordset::int_bof_ = -1;
00783 int TePGRecordset::openRecordSets_ = 0;
00784 std::set<int> TePGRecordset::freeCursorNumbers_;
00785 TeMutex TePGRecordset::_mutexLock;
00786
00787
00788
00789 TePGRecordset::TePGRecordset(const string& str_qry, TePGConnection* con_x,
00790 const TeCursorType& cursorType,
00791 const TeCursorLocation& cursorLocation,
00792 const TeCursorDataType& cursorDataType,
00793 const int& numRowsToRetrieve)
00794 : pg_recordset_(0), conn_(con_x), cursorDeclared_(false), int_index_current_(-1),
00795 int_eof_(-1), cursorType_(cursorType), cursorLocation_(cursorLocation),
00796 cursorDataType_(cursorDataType), numRowsToRetrieve_(numRowsToRetrieve)
00797 {
00798
00799 if(((unsigned int) 1) == htonl((unsigned int) 1))
00800 isLittleEndian_ = false;
00801 else
00802 isLittleEndian_ = true;
00803
00804 recordSetId_ = TePGRecordset::getFreeCursor();
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818 if(!str_qry.empty() && conn_)
00819 open(str_qry, conn_, cursorType_, cursorLocation_, cursorDataType_);
00820 }
00821
00822 TePGRecordset::~TePGRecordset()
00823 {
00824
00825
00826 TePGRecordset::releaseCursor(recordSetId_);
00827
00828 close();
00829 }
00830
00831 void TePGRecordset::close(void)
00832 {
00833 if(cursorDeclared_ && conn_)
00834 {
00835 string sqlCloseCursor = "CLOSE CURSOR_";
00836 sqlCloseCursor += Te2String(recordSetId_);
00837
00838 conn_->exec_cmd(sqlCloseCursor.c_str());
00839 }
00840
00841 freeRecordSet();
00842
00843 cursorDeclared_ = false;
00844
00845 conn_ = 0;
00846
00847 return;
00848 }
00849
00850 bool TePGRecordset::moveFirst(void)
00851 {
00852 if(!cursorDeclared_)
00853 return false;
00854
00855 if(cursorLocation_ == TeCLIENTESIDE)
00856 {
00857 if(recordCount() > 0)
00858 {
00859 int_index_current_ = 0;
00860 return true;
00861 }
00862 else
00863 return false;
00864 }
00865
00866 firstFetch = false;
00867 lastFetch = false;
00868
00869 string moveFirstSQL = "MOVE ABSOLUTE 0 IN CURSOR_";
00870 moveFirstSQL += Te2String(recordSetId_);
00871
00872 int res = conn_->exec_cmd(moveFirstSQL.c_str());
00873
00874 if(res == 0)
00875 {
00876 freeRecordSet();
00877
00878 string fetchSQL = "FETCH FORWARD " + Te2String(numRowsToRetrieve_);
00879 fetchSQL += " FROM CURSOR_";
00880 fetchSQL += Te2String(recordSetId_);
00881
00882 pg_recordset_ = conn_->exec(fetchSQL.c_str());
00883
00884 if(PQresultStatus(pg_recordset_) == PGRES_TUPLES_OK)
00885 {
00886 if(recordCount() > 0)
00887 {
00888 int_eof_ = recordCount();
00889 int_index_current_ = 0;
00890 return true;
00891 }
00892 }
00893
00894 freeRecordSet();
00895 return false;
00896 }
00897
00898 return false;
00899 }
00900
00901 bool TePGRecordset::movePrevious(void)
00902 {
00903
00904 if(!cursorDeclared_)
00905 return false;
00906
00907 if(cursorLocation_ == TeCLIENTESIDE)
00908 {
00909 if(bof())
00910 return false;
00911 else
00912 {
00913 --int_index_current_;
00914 return true;
00915 }
00916 }
00917
00918 if(recordCount() > 0)
00919 {
00920 string move = "";
00921 string fetchSQL = "";
00922
00923 if(!movingBackward_)
00924 {
00925 if(bof())
00926 return false;
00927
00928 --int_index_current_;
00929
00930 if(bof())
00931 {
00932 movingBackward_ = true;
00933
00934 int val = recordCount() - 1;
00935
00936 if(lastFetch)
00937 {
00938 ++val;
00939 }
00940
00941 move = " MOVE BACKWARD "+Te2String(val)+" FROM CURSOR_"+Te2String(recordSetId_)+";";
00942
00943 fetchSQL = move;
00944 fetchSQL += " FETCH BACKWARD ";
00945 fetchSQL += Te2String(numRowsToRetrieve_);
00946 fetchSQL += " FROM CURSOR_";
00947 fetchSQL += Te2String(recordSetId_);
00948 }
00949 else
00950 {
00951 return true;
00952 }
00953 }
00954 else
00955 {
00956 if(eof())
00957 return false;
00958
00959 ++int_index_current_;
00960
00961 if(eof())
00962 {
00963 fetchSQL = "FETCH BACKWARD ";
00964 fetchSQL += Te2String(numRowsToRetrieve_);
00965 fetchSQL += " FROM CURSOR_";
00966 fetchSQL += Te2String(recordSetId_);
00967 }
00968 else
00969 {
00970 return true;
00971 }
00972 }
00973 pg_recordset_ = conn_->exec(fetchSQL.c_str());
00974
00975 if(PQresultStatus(pg_recordset_) == PGRES_TUPLES_OK)
00976 {
00977 firstFetch = false;
00978 lastFetch = false;
00979
00980 if(this->recordCount() > 0)
00981 {
00982 int_eof_ = recordCount();
00983 int_index_current_ = 0;
00984
00985 if(this->recordCount() != numRowsToRetrieve_)
00986 {
00987 firstFetch = true;
00988 }
00989
00990
00991 return true;
00992 }
00993
00994 }
00995
00996 freeRecordSet();
00997 }
00998
00999 return false;
01000 }
01001
01002 bool TePGRecordset::moveNext(void)
01003 {
01004 if(!cursorDeclared_)
01005 return false;
01006
01007 if(cursorLocation_ == TeCLIENTESIDE)
01008 {
01009 if(eof())
01010 return false;
01011
01012 ++int_index_current_;
01013
01014 return true;
01015 }
01016
01017 if((recordCount() > 0))
01018 {
01019 string move = "";
01020 string fetchSQL = "";
01021
01022 if(!movingBackward_)
01023 {
01024 if(!eof())
01025 {
01026 ++int_index_current_;
01027
01028 if(eof())
01029 {
01030 fetchSQL = "FETCH FORWARD ";
01031 fetchSQL += Te2String(numRowsToRetrieve_);
01032 fetchSQL += " FROM CURSOR_";
01033 fetchSQL += Te2String(recordSetId_);
01034 }
01035 else
01036 {
01037 return true;
01038 }
01039 }
01040 }
01041 else
01042 {
01043 if(!bof())
01044 {
01045 --int_index_current_;
01046
01047 if(bof())
01048 {
01049 movingBackward_ = false;
01050 int val = recordCount() -1;
01051 if(firstFetch)
01052 {
01053 ++val;
01054 }
01055 move = " MOVE FORWARD "+Te2String(val)+" FROM CURSOR_"+Te2String(recordSetId_)+";";
01056
01057 fetchSQL = move;
01058
01059 fetchSQL += "FETCH FORWARD ";
01060 fetchSQL += Te2String(numRowsToRetrieve_);
01061 fetchSQL += " FROM CURSOR_";
01062 fetchSQL += Te2String(recordSetId_);
01063 }
01064 else
01065 {
01066 return true;
01067 }
01068 }
01069 }
01070 freeRecordSet();
01071
01072 pg_recordset_ = conn_->exec(fetchSQL.c_str());
01073
01074 if(PQresultStatus(pg_recordset_) == PGRES_TUPLES_OK)
01075 {
01076 firstFetch = false;
01077 lastFetch = false;
01078
01079 if(recordCount() > 0)
01080 {
01081 int_eof_ = recordCount();
01082 int_index_current_ = 0;
01083
01084 if(this->recordCount() != numRowsToRetrieve_)
01085 {
01086 lastFetch = true;
01087 }
01088
01089 return true;
01090 }
01091 }
01092
01093 freeRecordSet();
01094 }
01095
01096 return false;
01097 }
01098
01099 bool TePGRecordset::moveLast(void)
01100 {
01101
01102 if(!cursorDeclared_)
01103 return false;
01104
01105 if(cursorLocation_ == TeCLIENTESIDE)
01106 {
01107 if(recordCount() > 0)
01108 {
01109 int_index_current_ = recordCount() - 1;
01110 return true;
01111 }
01112
01113 return false;
01114 }
01115
01116 firstFetch = false;
01117 lastFetch = false;
01118
01119 freeRecordSet();
01120
01121 string fetchSQL = "FETCH LAST FROM CURSOR_";
01122 fetchSQL += Te2String(recordSetId_);
01123
01124 pg_recordset_ = conn_->exec(fetchSQL.c_str());
01125
01126 if(PQresultStatus(pg_recordset_) == PGRES_TUPLES_OK)
01127 {
01128 if(this->recordCount() > 0)
01129 {
01130 int_eof_ = recordCount();
01131 int_index_current_ = 0;
01132 return true;
01133 }
01134 }
01135
01136 freeRecordSet();
01137
01138 return false;
01139
01140 }
01141
01142 bool TePGRecordset::moveTo(const int& lin_number)
01143 {
01144
01145 if(!cursorDeclared_)
01146 return false;
01147
01148 if(cursorLocation_ == TeCLIENTESIDE)
01149 {
01150 if((lin_number > int_bof_) && (lin_number < int_eof_))
01151 {
01152 int_index_current_ = lin_number;
01153 return true;
01154 }
01155
01156 return false;
01157 }
01158
01159 firstFetch = false;
01160 lastFetch = false;
01161
01162 freeRecordSet();
01163
01164 string fetchSQL = "FETCH ABSOLUTE ";
01165 fetchSQL += Te2String(lin_number);
01166 fetchSQL += " FROM CURSOR_";
01167 fetchSQL += Te2String(recordSetId_);
01168
01169 pg_recordset_ = conn_->exec(fetchSQL.c_str());
01170
01171 if(PQresultStatus(pg_recordset_) == PGRES_TUPLES_OK)
01172 {
01173 if(this->recordCount() > 0)
01174 {
01175 int_eof_ = recordCount();
01176 int_index_current_ = 0;
01177 return true;
01178 }
01179 }
01180
01181 freeRecordSet();
01182
01183 return false;
01184 }
01185
01186 bool TePGRecordset::open(const string& str_qry, TePGConnection* con_x,
01187 const TeCursorType& cursorType,
01188 const TeCursorLocation& cursorLocation,
01189 const TeCursorDataType& cursorDataType,
01190 const int& numRowsToRetrieve)
01191 {
01192 close();
01193
01194 if(str_qry.empty() || !con_x)
01195 return false;
01196
01197 cursorType_ = cursorType;
01198 cursorLocation_ = cursorLocation;
01199 cursorDataType_ = cursorDataType;
01200 numRowsToRetrieve_ = numRowsToRetrieve;
01201 cursorDeclared_ = false;
01202 conn_ = con_x;
01203 movingBackward_ = false;
01204 lastFetch = false;
01205 firstFetch = false;
01206
01207 string sqlCursor = "DECLARE CURSOR_";
01208 sqlCursor += Te2String(recordSetId_);
01209 sqlCursor += (cursorDataType_ == TeBINARYCURSOR) ? " BINARY " : " ";
01210
01211 sqlCursor += "SCROLL CURSOR WITH HOLD FOR ";
01212 sqlCursor += str_qry;
01213
01214
01215
01216 pg_recordset_ = conn_->exec(sqlCursor.c_str());
01217
01218 if(PQresultStatus(pg_recordset_) == PGRES_COMMAND_OK)
01219 {
01220 cursorDeclared_ = true;
01221
01222 string numRows = (cursorLocation_ == TeSERVERSIDE) ? Te2String(numRowsToRetrieve_) : string("ALL");
01223
01224 string fetchSQL = "FETCH FORWARD " + numRows;
01225 fetchSQL += " FROM CURSOR_";
01226 fetchSQL += Te2String(recordSetId_);
01227
01228 PQclear(pg_recordset_);
01229
01230 pg_recordset_ = conn_->exec(fetchSQL.c_str());
01231
01232 if(PQresultStatus(pg_recordset_) == PGRES_TUPLES_OK)
01233 {
01234 if(recordCount() > 0)
01235 {
01236 int_eof_ = recordCount();
01237 int_index_current_ = 0;
01238 }
01239
01240 return true;
01241 }
01242 }
01243
01244 freeRecordSet();
01245
01246 return false;
01247 }
01248
01249 int TePGRecordset::getBytea(const int& field_num, char*& buff) const
01250 {
01251 if(cursorDataType_ == TeTEXTCURSOR)
01252 {
01253 size_t newLen;
01254
01255 unsigned char* ptData = PQunescapeBytea((unsigned char*)(value(field_num)), &newLen);
01256
01257 if(newLen <= 0)
01258 return (int)newLen;
01259
01260 if(!buff)
01261 buff = new char[newLen];
01262
01263 memcpy(buff, ptData, newLen);
01264
01265 TePGConnection::freeMem(ptData);
01266
01267 return (int)newLen;
01268 }
01269 else
01270 {
01271 unsigned int numBytes = PQgetlength(pg_recordset_, int_index_current_, field_num);
01272
01273 char* ptData = value(field_num);
01274
01275 if(!buff)
01276 buff = new char[numBytes];
01277
01278 memcpy(buff, ptData, numBytes);
01279
01280 return numBytes;
01281 }
01282 }
01283
01284 void TePGRecordset::getByteALine2D(const int& field_num, TeLine2D& l) const
01285 {
01286 char* ptDataAux = 0;
01287
01288 unsigned long newLen = getBytea(field_num, ptDataAux);
01289
01290 double* data = (double*) ptDataAux;
01291
01292 unsigned int npts = newLen / (2 * sizeof(double));
01293
01294 double x, y;
01295
01296 for(unsigned int k = 0; k < npts; ++k)
01297 {
01298 x = (*data++);
01299 y = (*data++);
01300
01301 TeCoord2D pt(x,y);
01302
01303 l.add(pt);
01304 }
01305
01306 delete [] ptDataAux;
01307 }
01308
01309 void TePGRecordset::getPGBox(const int& field_num, TeBox& b) const
01310 {
01311 char* pgbox = value(field_num);
01312
01313 if(cursorDataType_ == TeBINARYCURSOR)
01314 {
01315
01316 BIN_PG_POINT* pts = (BIN_PG_POINT*)(pgbox);
01317
01318
01319 if(isLittleEndian_)
01320 {
01321 union
01322 {
01323 double dWord_;
01324 unsigned int aux_[2];
01325 } swapx1, swapy1, swapx2, swapy2;
01326
01327
01328 swapx1.dWord_ = pts[0].x;
01329 swapy1.dWord_ = pts[0].y;
01330
01331 swapx2.aux_[1] = ntohl(swapx1.aux_[0]);
01332 swapx2.aux_[0] = ntohl(swapx1.aux_[1]);
01333
01334 swapy2.aux_[1] = ntohl(swapy1.aux_[0]);
01335 swapy2.aux_[0] = ntohl(swapy1.aux_[1]);
01336
01337 double X2 = swapx2.dWord_;
01338 double Y2 = swapy2.dWord_;
01339
01340 swapx1.dWord_ = pts[1].x;
01341 swapy1.dWord_ = pts[1].y;
01342
01343 swapx2.aux_[1] = ntohl(swapx1.aux_[0]);
01344 swapx2.aux_[0] = ntohl(swapx1.aux_[1]);
01345
01346 swapy2.aux_[1] = ntohl(swapy1.aux_[0]);
01347 swapy2.aux_[0] = ntohl(swapy1.aux_[1]);
01348
01349 double X1 = swapx2.dWord_;
01350 double Y1 = swapy2.dWord_;
01351
01352 TeBox baux(X1, Y1, X2, Y2);
01353
01354 b = baux;
01355 }
01356 else
01357 {
01358
01359 double X2 = pts[0].x;
01360 double Y2 = pts[0].y;
01361 double X1 = pts[1].x;
01362 double Y1 = pts[1].y;
01363 TeBox baux(X1, Y1, X2, Y2);
01364
01365 b = baux;
01366 }
01367 }
01368 else
01369 b = PGBoxRtree_decode(pgbox);
01370 }
01371
01372 void TePGRecordset::getPGLine2D(const int& field_num, TeLine2D& l) const
01373 {
01374 char* polygon = value(field_num);
01375
01376 if(cursorDataType_ == TeBINARYCURSOR)
01377 {
01378 unsigned int numPts;
01379 memcpy(&numPts, polygon, sizeof(int));
01380 numPts = ntohl(numPts);
01381
01382 l.reserve(numPts);
01383
01384
01385 BIN_PG_POINT* pts = (BIN_PG_POINT*)(polygon + sizeof(int));
01386
01387
01388 if(isLittleEndian_)
01389 {
01390 union
01391 {
01392 double dWord_;
01393 unsigned int aux_[2];
01394 } swapx1, swapy1, swapx2, swapy2;
01395
01396
01397 for(unsigned int i = 0; i < numPts ; ++i)
01398 {
01399 swapx1.dWord_ = pts[i].x;
01400 swapy1.dWord_ = pts[i].y;
01401
01402 swapx2.aux_[1] = ntohl(swapx1.aux_[0]);
01403 swapx2.aux_[0] = ntohl(swapx1.aux_[1]);
01404
01405 swapy2.aux_[1] = ntohl(swapy1.aux_[0]);
01406 swapy2.aux_[0] = ntohl(swapy1.aux_[1]);
01407
01408 l.add(TeCoord2D(swapx2.dWord_, swapy2.dWord_));
01409 }
01410
01411 }
01412 else
01413 {
01414
01415 for(unsigned int i = 0; i < numPts ; ++i)
01416 l.add(TeCoord2D(pts[i].x, pts[i].y));
01417
01418 }
01419 }
01420 else
01421 l = PgGeomPolygon2Te(polygon);
01422 }
01423
01424 char* TePGRecordset::getWKBHeader(char* v, unsigned char &byteOrder, unsigned int &wkbType, unsigned int &numGeometries, int& srid) const
01425 {
01426 srid = -1;
01427
01428 const int byteOrderPlusGeomType = sizeof(unsigned char) + sizeof(unsigned int);
01429
01430 if(cursorDataType_ == TeTEXTCURSOR)
01431 {
01432 unsigned char header [byteOrderPlusGeomType];
01433
01434 for (int t = 0; t < byteOrderPlusGeomType; ++t)
01435 {
01436 header[t] =(unsigned char) parse_hex(v) ;
01437 v += 2;
01438 }
01439
01440 memcpy(&byteOrder, header, sizeof(unsigned char));
01441 memcpy(&wkbType, header + sizeof(unsigned char), sizeof(unsigned int));
01442 }
01443 else
01444 {
01445 memcpy(&byteOrder, v, sizeof(unsigned char));
01446 memcpy(&wkbType, v + sizeof(unsigned char), sizeof(unsigned int));
01447
01448 v += byteOrderPlusGeomType;
01449 }
01450
01451
01452
01453 if((byteOrder == 0) && isLittleEndian_)
01454 {
01455 wkbType = ntohl(wkbType);
01456 }
01457 else if((byteOrder == 1) && !isLittleEndian_)
01458 {
01459 wkbType = TePGSwapUInt(wkbType);
01460 }
01461
01462 if(wkbType & TE_EWKB_SRID_FLAG)
01463 {
01464 if(cursorDataType_ == TeTEXTCURSOR)
01465 {
01466 unsigned char sridArray[sizeof(unsigned int)];
01467 for(unsigned int t = 0; t < sizeof(unsigned int); ++t)
01468 {
01469 sridArray[t] = (unsigned char)parse_hex(v);
01470 v += 2;
01471 }
01472
01473 memcpy(&srid, sridArray, sizeof(unsigned int));
01474 }
01475 else
01476 {
01477 memcpy(&srid, v, 4);
01478 v += 4;
01479 }
01480 }
01481
01482
01483 bool isPostGIS = false;
01484 TeConvert2OGCWKBType(wkbType, isPostGIS);
01485
01486 numGeometries = 0;
01487
01488 if(wkbType > 1 && wkbType <= 7)
01489 {
01490 if(cursorDataType_ == TeTEXTCURSOR)
01491 {
01492 unsigned char qtd[sizeof(unsigned int)];
01493
01494 for(unsigned int t = 0; t < sizeof(unsigned int); ++t)
01495 {
01496 qtd[t] = (unsigned char)parse_hex(v);
01497 v += 2;
01498 }
01499
01500 memcpy(&numGeometries, qtd, sizeof(unsigned int));
01501 }
01502 else
01503 {
01504 memcpy(&numGeometries, v, sizeof(unsigned int));
01505 v += sizeof(unsigned int);
01506 }
01507
01508
01509 if((byteOrder == 0) && isLittleEndian_)
01510 {
01511 numGeometries = ntohl(numGeometries);
01512 }
01513 else if((byteOrder == 1) && !isLittleEndian_)
01514 {
01515 numGeometries = TePGSwapUInt(numGeometries);
01516 }
01517 }
01518
01519 return v;
01520 }
01521
01522 char* TePGRecordset::getWKBPoint(char* v, TePoint& p) const
01523 {
01524 unsigned char byteOrder;
01525 unsigned int wkbType;
01526 unsigned int numGeometries;
01527 int srid = -1;
01528 TeCoord2D c;
01529
01530 v = getWKBHeader(v, byteOrder, wkbType, numGeometries, srid);
01531
01532 p.srid(srid);
01533
01534 if(wkbType != 1)
01535 throw logic_error("Binary data doesn't supported!");
01536
01537
01538 union
01539 {
01540 double dWord_;
01541 unsigned int aux_[2];
01542 } swapx1, swapy1;
01543
01544 if(cursorDataType_ == TeTEXTCURSOR)
01545 {
01546
01547 const int double2Size = 2 * sizeof(double);
01548 unsigned char data[double2Size];
01549
01550 for(int t = 0; t < double2Size; ++t)
01551 {
01552 data[t] = (unsigned char)parse_hex(v);
01553 v += 2;
01554 }
01555
01556
01557 memcpy(&swapx1.dWord_, data , sizeof(double));
01558 memcpy(&swapy1.dWord_, data + sizeof(double), sizeof(double));
01559 }
01560 else
01561 {
01562 memcpy(&swapx1.dWord_, v , sizeof(double));
01563 memcpy(&swapy1.dWord_, v + sizeof(double), sizeof(double));
01564
01565 v += (sizeof(double) + sizeof(double));
01566 }
01567
01568
01569 if((byteOrder == 0) && isLittleEndian_)
01570 {
01571 union
01572 {
01573 double dWord_;
01574 unsigned int aux_[2];
01575 } swapx2, swapy2;
01576
01577 swapx2.aux_[1] = ntohl(swapx1.aux_[0]);
01578 swapx2.aux_[0] = ntohl(swapx1.aux_[1]);
01579
01580 swapy2.aux_[1] = ntohl(swapy1.aux_[0]);
01581 swapy2.aux_[0] = ntohl(swapy1.aux_[1]);
01582
01583 c.x(swapx2.dWord_);
01584 c.y(swapy2.dWord_);
01585
01586 p.add(c);
01587
01588 return v;
01589 }
01590 else if((byteOrder == 1) && !isLittleEndian_)
01591 {
01592 union
01593 {
01594 double dWord_;
01595 unsigned int aux_[2];
01596 } swapx2, swapy2;
01597
01598 swapx2.aux_[1] = TePGSwapUInt(swapx1.aux_[0]);
01599 swapx2.aux_[0] = TePGSwapUInt(swapx1.aux_[1]);
01600
01601 swapy2.aux_[1] = TePGSwapUInt(swapy1.aux_[0]);
01602 swapy2.aux_[0] = TePGSwapUInt(swapy1.aux_[1]);
01603
01604 c.x(swapx2.dWord_);
01605 c.y(swapy2.dWord_);
01606
01607 p.add(c);
01608
01609 return v;
01610
01611 }
01612
01613 c.x(swapx1.dWord_);
01614 c.y(swapy1.dWord_);
01615
01616 p.add(c);
01617
01618 return v;
01619 }
01620
01621 char* TePGRecordset::getWKBLinearRing(char* v, int byteOrder, TeLine2D &line) const
01622 {
01623 unsigned int numPoints;
01624
01625 const int size2Double = sizeof(double) + sizeof(double);
01626
01627 if(cursorDataType_ == TeTEXTCURSOR)
01628 {
01629 unsigned char data[size2Double];
01630
01631 for(unsigned int n = 0; n < sizeof(unsigned int); ++n)
01632 {
01633 data[n] = (unsigned char)parse_hex(v);
01634 v += 2;
01635 }
01636
01637 memcpy(&numPoints, data , sizeof(unsigned int));
01638 }
01639 else
01640 {
01641 memcpy(&numPoints, v , sizeof(unsigned int));
01642 v += sizeof(unsigned int);
01643 }
01644
01645
01646 if((byteOrder == 0) && isLittleEndian_)
01647 {
01648 numPoints = ntohl(numPoints);
01649 }
01650 else if((byteOrder == 1) && !isLittleEndian_)
01651 {
01652 numPoints = TePGSwapUInt(numPoints);
01653 }
01654
01655 for(unsigned int i = 0; i < numPoints; ++i)
01656 {
01657 union
01658 {
01659 double dWord_;
01660 unsigned int aux_[2];
01661 } swapx1, swapy1;
01662
01663 if(cursorDataType_ == TeTEXTCURSOR)
01664 {
01665 unsigned char data[size2Double];
01666
01667 for(int t = 0; t < size2Double; ++t)
01668 {
01669 data[t] = (unsigned char)parse_hex(v);
01670 v += 2;
01671 }
01672
01673 memcpy(&swapx1.dWord_, data , sizeof(double));
01674 memcpy(&swapy1.dWord_, data + sizeof(double), sizeof(double));
01675 }
01676 else
01677 {
01678 memcpy(&swapx1.dWord_, v , sizeof(double));
01679 memcpy(&swapy1.dWord_, v + sizeof(double), sizeof(double));
01680 v += size2Double;
01681 }
01682
01683
01684 if((byteOrder == 0) && isLittleEndian_)
01685 {
01686 union
01687 {
01688 double dWord_;
01689 unsigned int aux_[2];
01690 } swapx2, swapy2;
01691
01692 swapx2.aux_[1] = ntohl(swapx1.aux_[0]);
01693 swapx2.aux_[0] = ntohl(swapx1.aux_[1]);
01694
01695 swapy2.aux_[1] = ntohl(swapy1.aux_[0]);
01696 swapy2.aux_[0] = ntohl(swapy1.aux_[1]);
01697
01698 line.add(TeCoord2D(swapx2.dWord_, swapy2.dWord_));
01699 }
01700 else if((byteOrder == 1) && !isLittleEndian_)
01701 {
01702 union
01703 {
01704 double dWord_;
01705 unsigned int aux_[2];
01706 } swapx2, swapy2;
01707
01708 swapx2.aux_[1] = TePGSwapUInt(swapx1.aux_[0]);
01709 swapx2.aux_[0] = TePGSwapUInt(swapx1.aux_[1]);
01710
01711 swapy2.aux_[1] = TePGSwapUInt(swapy1.aux_[0]);
01712 swapy2.aux_[0] = TePGSwapUInt(swapy1.aux_[1]);
01713
01714 line.add(TeCoord2D(swapx2.dWord_, swapy2.dWord_));
01715 }
01716 else
01717 {
01718 line.add(TeCoord2D(swapx1.dWord_, swapy1.dWord_));
01719 }
01720 }
01721
01722 return v;
01723
01724 }
01725
01726 char* TePGRecordset::getWKBLine(char* v, TeLine2D& l) const
01727 {
01728 unsigned char byteOrder;
01729 unsigned int wkbType;
01730 unsigned int numPoints;
01731 int srid = -1;
01732
01733 v = getWKBHeader(v, byteOrder, wkbType, numPoints, srid);
01734
01735 if(wkbType != 2)
01736 throw logic_error("Binary data doesn't supported!");
01737
01738 if(cursorDataType_ == TeTEXTCURSOR)
01739 {
01740
01741 v = getWKBLinearRing(v - (sizeof(unsigned int) + sizeof(unsigned int)), byteOrder, l);
01742 }
01743 else
01744 {
01745
01746 v = getWKBLinearRing(v - sizeof(unsigned int), byteOrder, l);
01747 }
01748
01749 l.srid(srid);
01750
01751 return v;
01752
01753 }
01754
01755 char* TePGRecordset::getWKBPolygon(char* v, TePolygon& p) const
01756 {
01757 unsigned char byteOrder;
01758 unsigned int wkbType;
01759 unsigned int numRings;
01760 int srid = -1;
01761
01762 v = getWKBHeader(v, byteOrder, wkbType, numRings, srid);
01763
01764
01765 if(wkbType != 3)
01766 throw logic_error("Binary data doesn't supported!");
01767
01768 for(unsigned int i = 0; i < numRings; ++i)
01769 {
01770 TeLine2D line;
01771 v = getWKBLinearRing(v, byteOrder, line);
01772 line.srid(srid);
01773 p.add(line);
01774 }
01775
01776 p.srid(srid);
01777
01778 return v;
01779
01780 }
01781
01782 char* TePGRecordset::getWKBMultiPoint(char* v, TePointSet &ps) const
01783 {
01784 unsigned char byteOrder;
01785 unsigned int wkbType;
01786 unsigned int num_wkbPoints;
01787 int srid = -1;
01788
01789 char* vCopy = getWKBHeader(v, byteOrder, wkbType, num_wkbPoints, srid);
01790 if(wkbType == 1)
01791 {
01792 TePoint p;
01793 v = getWKBPoint(v, p);
01794 p.srid(srid);
01795 ps.add(p);
01796 return v;
01797 }
01798
01799 v = vCopy;
01800
01801 if(wkbType != 4)
01802 throw logic_error("Binary data doesn't supported!");
01803
01804 for(unsigned int i = 0; i < num_wkbPoints; ++i)
01805 {
01806 TePoint p;
01807 v = getWKBPoint(v, p);
01808 p.srid(srid);
01809 ps.add(p);
01810 }
01811
01812 return v;
01813 }
01814
01815 char* TePGRecordset::getWKBMultiLine(char* v, TeLineSet &ls) const
01816 {
01817 unsigned char byteOrder;
01818 unsigned int wkbType;
01819 unsigned int num_wkbLineStrings;
01820 int srid = -1;
01821
01822 char* vCopy = getWKBHeader(v, byteOrder, wkbType, num_wkbLineStrings, srid);
01823 if(wkbType == 2)
01824 {
01825 TeLine2D l;
01826 v = getWKBLine(v, l);
01827 l.srid(srid);
01828 ls.add(l);
01829 return v;
01830 }
01831
01832 v = vCopy;
01833
01834 if(wkbType != 5)
01835 throw logic_error("Binary data doesn't supported!");
01836
01837 for(unsigned int i = 0; i < num_wkbLineStrings; ++i)
01838 {
01839 TeLine2D line;
01840 v = getWKBLine(v, line);
01841 line.srid(srid);
01842 ls.add(line);
01843 }
01844
01845 return v;
01846 }
01847
01848 char* TePGRecordset::getWKBMultiPolygon(char* v, TePolygonSet &ps) const
01849 {
01850 unsigned char byteOrder;
01851 unsigned int wkbType;
01852 unsigned int num_wkbPolygons;
01853 int srid = -1;
01854
01855 char* vCopy = getWKBHeader(v, byteOrder, wkbType, num_wkbPolygons, srid);
01856
01857 if(wkbType == 3)
01858 {
01859 TePolygon p;
01860 v = getWKBPolygon(v, p);
01861 p.srid(srid);
01862 ps.add(p);
01863 return v;
01864 }
01865
01866 v = vCopy;
01867
01868 if(wkbType != 6)
01869 throw logic_error("Binary data doesn't supported!");
01870
01871 for(unsigned int i = 0; i < num_wkbPolygons; ++i)
01872 {
01873 TePolygon poly;
01874 v = getWKBPolygon(v, poly);
01875 poly.srid(srid);
01876 ps.add(poly);
01877 }
01878
01879 return v;
01880 }
01881
01882 void TePGRecordset::getWKBGeomColl(char* v, TeMultiGeometry &mg) const
01883 {
01884 unsigned char byteOrder;
01885 unsigned int wkbType;
01886 unsigned int num_wkbGeometries;
01887 int srid = -1;
01888
01889 v = getWKBHeader(v, byteOrder, wkbType, num_wkbGeometries, srid);
01890
01891 if(wkbType != 7)
01892 throw logic_error("Binary data doesn't supported!");
01893
01894 for(unsigned int i = 0; i < num_wkbGeometries; ++i)
01895 {
01896 unsigned int geomType;
01897 unsigned char geomByteOrder;
01898 unsigned int num_geometries;
01899 int srid = -1;
01900
01901 getWKBHeader(v, geomByteOrder, geomType, num_geometries, srid);
01902
01903 if(geomType == 1)
01904 {
01905 TePoint p;
01906
01907 v = getWKBPoint(v, p);
01908
01909 mg.addGeometry(p);
01910 }
01911 else if(geomType == 2)
01912 {
01913 TeLine2D line;
01914
01915 v = getWKBLine(v, line);
01916
01917 mg.addGeometry(line);
01918 }
01919 else if(geomType == 3)
01920 {
01921 TePolygon poly;
01922
01923 v = getWKBPolygon(v, poly);
01924
01925 mg.addGeometry(poly);
01926 }
01927 else if(geomType == 4)
01928 {
01929 TePointSet pointSet;
01930
01931 v = getWKBMultiPoint(v, pointSet);
01932
01933 for(unsigned int a = 0; a < pointSet.size(); ++a)
01934 {
01935 TePoint point = pointSet[a];
01936 mg.addGeometry(point);
01937 }
01938 }
01939 else if(geomType == 5)
01940 {
01941 TeLineSet lineSet;
01942
01943 v = getWKBMultiLine(v, lineSet);
01944
01945 for(unsigned int a = 0; a < lineSet.size(); ++a)
01946 {
01947 TeLine2D coord = lineSet[a];
01948
01949 mg.addGeometry(coord);
01950 }
01951 }
01952 else if(geomType == 6)
01953 {
01954 TePolygonSet polygonSet;
01955
01956 v = getWKBMultiPolygon(v, polygonSet);
01957
01958 for(unsigned int a = 0; a < polygonSet.size(); ++a)
01959 {
01960 TePolygon poly = polygonSet[a];
01961
01962 mg.addGeometry(poly);
01963 }
01964 }
01965 else
01966 {
01967 throw logic_error("The data couldn't be decoded as a valid WKB geometry!");
01968 }
01969 }
01970
01971 }
01972
01973
01974 void TePGRecordset::getPGISPoint(const int& field_num, TePoint& p) const
01975 {
01976 getWKBPoint(value(field_num), p);
01977 }
01978
01979
01980 void TePGRecordset::getPGISLine(const int& field_num, TeLine2D& l) const
01981 {
01982 getWKBLine(value(field_num), l);
01983 }
01984
01985
01986 void TePGRecordset::getPGISPolygon(const int& field_num, TePolygon& p) const
01987 {
01988 getWKBPolygon(value(field_num), p);
01989 }
01990
01991
01992 void TePGRecordset::getPGISMultiPoint(const int& field_num, TePointSet& ps) const
01993 {
01994 getWKBMultiPoint(value(field_num), ps);
01995 }
01996
01997
01998 void TePGRecordset::getPGISMultiLine(const int& field_num, TeLineSet& ls) const
01999 {
02000 getWKBMultiLine(value(field_num), ls);
02001 }
02002
02003
02004 void TePGRecordset::getPGISMultiPolygon(const int& field_num, TePolygonSet& ps) const
02005 {
02006 getWKBMultiPolygon(value(field_num), ps);
02007 }
02008
02009
02010 void TePGRecordset::getPGISGeomColl(const int& field_num, TeMultiGeometry& m) const
02011 {
02012 getWKBGeomColl(value(field_num), m);
02013 }
02014
02015 string TePGRecordset::getDate(const int& field_num) const
02016 {
02017 if(cursorDataType_ == TeTEXTCURSOR)
02018 return value(field_num);
02019
02020
02021 struct te_pg_tm tt;
02022 struct te_pg_tm *tm = &tt;
02023
02024 TeDateADT date = getInt(field_num);
02025
02026 j2date(date + POSTGRES_EPOCH_JDATE,
02027 &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday));
02028
02029 char buf[MAXDATELEN + 1];
02030
02031 string datestr = "";
02032
02033 if(EncodeDateOnly(tm, buf))
02034 datestr = buf;
02035
02036 return datestr;
02037 }
02038
02039 string TePGRecordset::getTime(const int& field_num)
02040 {
02041 if(cursorDataType_ == TeTEXTCURSOR)
02042 {
02043 string res = value(field_num);
02044
02045 return res;
02046 }
02047
02048 te_int64 time;
02049
02050 if(this->conn_->isDateInt())
02051 {
02052 unsigned int h32;
02053 unsigned int l32;
02054
02055 memcpy(&h32, value(field_num), sizeof(unsigned));
02056 memcpy(&l32, value(field_num) + sizeof(unsigned), sizeof(unsigned));
02057
02058 h32 = ntohl(h32);
02059 l32 = ntohl(l32);
02060
02061 time = h32;
02062 time <<= 32;
02063 time |= l32;
02064 }
02065 else
02066 {
02067 double t_aux = getDouble(field_num);
02068
02069 t_aux*=1000000;
02070 time=(te_int64)t_aux;
02071 }
02072
02073 struct te_pg_tm tt;
02074 struct te_pg_tm *tm = &tt;
02075 te_fsec_t fsec;
02076
02077 char buf[MAXDATELEN + 1];
02078
02079 string datestr = "";
02080
02081 time2tm(time, tm, &fsec);
02082
02083 if(EncodeTimeOnly(tm, fsec, NULL, buf))
02084 datestr = buf;
02085
02086 return datestr;
02087 }
02088
02089 string TePGRecordset::getTimeStamp(const int& field_num)
02090 {
02091 if(cursorDataType_ == TeTEXTCURSOR)
02092 {
02093 string res = value(field_num);
02094
02095 return res;
02096 }
02097
02098 te_int64 timestamp;
02099
02100 if(this->conn_->isDateInt())
02101 {
02102 unsigned int h32;
02103 unsigned int l32;
02104
02105 memcpy(&h32, value(field_num), sizeof(unsigned));
02106 memcpy(&l32, value(field_num) + sizeof(unsigned), sizeof(unsigned));
02107
02108 h32 = ntohl(h32);
02109 l32 = ntohl(l32);
02110
02111 timestamp = h32;
02112 timestamp <<= 32;
02113 timestamp |= l32;
02114 }
02115 else
02116 {
02117 double t_aux = getDouble(field_num);
02118
02119 t_aux*=1000000;
02120 timestamp=(te_int64)t_aux;
02121 }
02122
02123 struct te_pg_tm tt;
02124 struct te_pg_tm *tm = &tt;
02125 te_fsec_t fsec;
02126 char *tzn = NULL;
02127
02128 char buf[MAXDATELEN + 1];
02129
02130 string datestr = "";
02131
02132 if(TIMESTAMP_NOT_FINITE(timestamp))
02133 {
02134 if(EncodeSpecialTimestamp(timestamp, buf))
02135 datestr = buf;
02136 }
02137 else if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL))
02138 {
02139 if(EncodeDateTime(tm, fsec, NULL, &tzn, buf))
02140 datestr = buf;
02141 }
02142
02143
02144 return datestr;
02145 }
02146
02147 int TePGRecordset::getInt8(const int& field_num) const
02148 {
02149 unsigned int h32;
02150 unsigned int l32;
02151
02152 memcpy(&h32, value(field_num), sizeof(unsigned));
02153 memcpy(&l32, value(field_num) + sizeof(unsigned), sizeof(unsigned));
02154
02155 h32 = ntohl(h32);
02156 l32 = ntohl(l32);
02157
02158 te_int64 i64value = h32;
02159 i64value <<= 32;
02160 i64value |= l32;
02161
02162 return (int)i64value;
02163 }
02164
02165
02166 char* TePGRecordset::getData(const int& field_num)
02167 {
02168 data_ = "";
02169
02170 if(cursorDataType_ == TeTEXTCURSOR)
02171 return value(field_num);
02172 else
02173 {
02174
02175 switch(fieldType(field_num))
02176 {
02177 case PG_NAME_TYPE :
02178 case PG_TEXT_TYPE :
02179 case PG_VARCHAR_TYPE : if(isNull(field_num))
02180 {
02181 data_ = "";
02182 }
02183 else
02184 {
02185 return value(field_num);
02186 }
02187
02188 break;
02189
02190 case PG_INT8_TYPE : if(isNull(field_num))
02191 {
02192 data_ = "";
02193 }
02194 else
02195 {
02196 data_ = Te2String(getInt8(field_num));
02197 }
02198 break;
02199
02200 case PG_BOOL_TYPE :
02201 case PG_BYTEA_TYPE :
02202 case PG_CHAR_TYPE :
02203 case PG_INT2_TYPE :
02204 break;
02205
02206 case PG_OID_TYPE :
02207 case PG_INT4_TYPE : if(isNull(field_num))
02208 {
02209 data_ = "";
02210 }
02211 else
02212 {
02213 data_ = Te2String(getInt(field_num));
02214 }
02215 break;
02216
02217 case PG_PG_FLOAT4_TYPE :
02218 case PG_POINT_TYPE :
02219 case PG_LSEG_TYPE :
02220 case PG_PATH_TYPE :
02221 case PG_BOX_TYPE :
02222 case PG_POLYGON_TYPE :
02223 case PG_LINE_TYPE :
02224 break;
02225
02226
02227 case PG_FLOAT8_TYPE : if(isNull(field_num))
02228 {
02229 data_ = "";
02230 }
02231 else
02232 {
02233 data_ = Te2String(getDouble(field_num), 15);
02234 }
02235 break;
02236
02237 case PG_TIMESTAMP_TYPE : if(isNull(field_num))
02238 {
02239 data_ = "";
02240 }
02241 else
02242 {
02243 data_ = getTimeStamp(field_num);
02244 }
02245 break;
02246
02247 case PG_DATE_TYPE : if(isNull(field_num))
02248 {
02249 data_ = "";
02250 }
02251 else
02252 {
02253 data_ = getDate(field_num);
02254 }
02255 break;
02256
02257 case PG_TIME_TYPE : if(isNull(field_num))
02258 {
02259 data_ = "";
02260 }
02261 else
02262 {
02263 data_ = getTime(field_num);
02264 }
02265 break;
02266
02267
02268 case PG_TIMESTAMPTZ_TYPE :
02269 case PG_TIMETZ_TYPE :
02270
02271 break;
02272
02273 case PG_INTERVAL_TYPE :
02274 break;
02275
02276 case PG_CIRCLE_TYPE :
02277 case PG_MONEY_TYPE :
02278 case PG_BPCHAR_TYPE :
02279 case PG_BIT_TYPE :
02280 case PG_VARBIT_TYPE :
02281 case PG_NUMERIC_TYPE :
02282 default :
02283
02284 break;
02285 }
02286
02287 return (char*)data_.c_str();
02288 }
02289 }
02290
02291 int TePGRecordset::fieldSize(const int& field_num)
02292 {
02293 Oid field_t = this->fieldType(field_num);
02294 Oid field_m = PQfmod(pg_recordset_, field_num);
02295 PGresult *result_temp;
02296 char str_int[5];
02297
02298 int size = 0;
02299 char str_field_t[50];
02300 char str_field_m[50];
02301 sprintf(str_field_t,"%d", field_t);
02302 sprintf(str_field_m,"%d", field_m);
02303 string str_qry = "SELECT format_type(";
02304 str_qry += str_field_t;
02305 str_qry += ",";
02306 str_qry += str_field_m;
02307 str_qry += ")";
02308 switch(field_t)
02309 {
02310 case 1042:
02311 case 1043:
02312 case 1700:
02313 result_temp = PQexec(conn_->c_ptr(), str_qry.c_str());
02314 if(PQresultStatus(result_temp) == PGRES_TUPLES_OK)
02315 {
02316 char *lin = PQgetvalue(result_temp, 0, 0);
02317 int i = 0;
02318 while(*lin != '\0' && *lin != ',')
02319 {
02320 if(*lin >= '0' && *lin <= '9' && i < 4)
02321 {
02322 str_int[i] = *lin;
02323 i++;
02324 }
02325 lin++;
02326 }
02327 str_int[i]='\0';
02328 size = atoi(str_int);
02329 }
02330 PQclear(result_temp);
02331 break;
02332 default:
02333 return PQfsize(pg_recordset_, field_num);
02334 }
02335 result_temp = 0;
02336 return size;
02337 }
02338
02339 int TePGRecordset::fieldSizeFractionaryPart(const int& field_num)
02340 {
02341 Oid field_t = this->fieldType(field_num);
02342 Oid field_m = PQfmod(pg_recordset_, field_num);
02343 PGresult *result_temp;
02344 char str_frac[5];
02345
02346 int size = 0;
02347 char str_field_t[50];
02348 char str_field_m[50];
02349 sprintf(str_field_t,"%d", field_t);
02350 sprintf(str_field_m,"%d", field_m);
02351 string str_qry = "SELECT format_type(";
02352 str_qry += str_field_t;
02353 str_qry += ",";
02354 str_qry += str_field_m;
02355 str_qry += ")";
02356 switch(field_t)
02357 {
02358 case 1700:
02359 result_temp = PQexec(conn_->c_ptr(), str_qry.c_str());
02360 if(PQresultStatus(result_temp) == PGRES_TUPLES_OK)
02361 {
02362 char *lin = PQgetvalue(result_temp, 0, 0);
02363 int i = 0;
02364 while(*lin != '\0' && *lin != ',')
02365 {
02366 lin++;
02367 }
02368 if(*lin == ',')
02369 {
02370 lin++;
02371 }
02372 while(*lin != '\0')
02373 {
02374 if(*lin >= '0' && *lin <= '9' && i < 4)
02375 {
02376 str_frac[i] = *lin;
02377 i++;
02378 }
02379 lin++;
02380 }
02381 str_frac[i]='\0';
02382 size = atoi(str_frac);
02383 }
02384 PQclear(result_temp);
02385 break;
02386 default:
02387 break;
02388
02389 }
02390 result_temp = 0;
02391 return size;
02392 }
02393
02394 void TePGRecordset::freeRecordSet()
02395 {
02396 if(pg_recordset_)
02397 PQclear(pg_recordset_);
02398
02399
02400 pg_recordset_ = 0;
02401 int_index_current_ = -1;
02402 int_eof_ = -1;
02403 return;
02404 }
02405
02406 char* TeLine2DToPGBinary(const TeLine2D &line, unsigned int &size)
02407 {
02408 unsigned int numPts = line.size();
02409 size = sizeof(int) + (numPts * sizeof(double) * 2);
02410
02411 char* p = new char[size];
02412
02413 char* paux = p;
02414
02415
02416 unsigned int numPts_net = htonl(numPts);
02417
02418 memcpy(p, &numPts_net, sizeof(int));
02419 p += sizeof(int);
02420
02421 for(unsigned int i = 0; i < numPts ; ++i)
02422 {
02423 double swappedDoubleX = TeConvertToBigEndian(line[i].x());
02424 double swappedDoubleY = TeConvertToBigEndian(line[i].y());
02425
02426 memcpy(p, &swappedDoubleX, sizeof(double));
02427 p += sizeof(double);
02428
02429 memcpy(p, &swappedDoubleY, sizeof(double));
02430 p += sizeof(double);
02431 }
02432
02433 return paux;
02434 }
02435
02436 char* TeBoxToPGBinary(const TeBox &box, unsigned int &size)
02437 {
02438 size = 4 * sizeof(double);
02439
02440 char* b = new char[size];
02441 char* baux = b;
02442
02443 double swappedDoubleURX = TeConvertToBigEndian(box.upperRight().x());
02444 double swappedDoubleURY = TeConvertToBigEndian(box.upperRight().y());
02445
02446 double swappedDoubleLFX = TeConvertToBigEndian(box.lowerLeft().x());
02447 double swappedDoubleLFY = TeConvertToBigEndian(box.lowerLeft().y());
02448
02449 memcpy(b, &swappedDoubleURX, sizeof(double));
02450 b += sizeof(double);
02451
02452 memcpy(b, &swappedDoubleURY, sizeof(double));
02453 b += sizeof(double);
02454
02455 memcpy(b, &swappedDoubleLFX, sizeof(double));
02456 b += sizeof(double);
02457
02458 memcpy(b, &swappedDoubleLFY, sizeof(double));
02459 b += sizeof(double);
02460
02461 return baux;
02462 }
02463
02464 double TeConvertToBigEndian(const double &value)
02465 {
02466 double swappedValue;
02467
02468 union
02469 {
02470 double dWord_;
02471 unsigned int aux_[2];
02472 } swapIN, swapOUT;
02473
02474
02475
02476 if(((unsigned int) 1) == htonl((unsigned int) 1))
02477 {
02478
02479 swapIN.dWord_ = value;
02480
02481 memcpy(&swappedValue, &swapIN.dWord_, sizeof(double));
02482 }
02483 else
02484 {
02485
02486 swapIN.dWord_ = value;
02487
02488 swapOUT.aux_[1] = htonl(swapIN.aux_[0]);
02489 swapOUT.aux_[0] = htonl(swapIN.aux_[1]);
02490
02491 memcpy(&swappedValue, &swapOUT.dWord_, sizeof(double));
02492 }
02493 return swappedValue;
02494 }
02495
02496 void TeConvert2OGCWKBType(unsigned int& gType, bool& isPostGIS)
02497 {
02498 isPostGIS = false;
02499 if(gType & 0xF0000000)
02500 {
02501 isPostGIS = true;
02502
02503 if((gType & TE_EWKB_ZM_OFFSET) == 0xC0000000)
02504 {
02505 gType = (gType & 0x0FFFFFFF) | 0xBB8;
02506 }
02507 else if(gType & TE_EWKB_Z_OFFSET)
02508 {
02509 gType = (gType & 0x0FFFFFFF) | 0x3E8;
02510 }
02511 else if(gType & TE_EWKB_M_OFFSET)
02512 {
02513 gType = (gType & 0x0FFFFFFF) | 0x7D0;
02514 }
02515 else
02516 {
02517 gType = (gType & 0x0FFFFFFF);
02518 }
02519 }
02520 }
02521
02522 void TeConvert2PostGISWKBType(unsigned int& gType)
02523 {
02524 if((gType & 0xF00) == 0xB00)
02525 {
02526 gType -= 3000;
02527 gType |= TE_EWKB_ZM_OFFSET;
02528 }
02529 else if((gType & 0x0F00) == 0x300)
02530 {
02531 gType -= 1000;
02532 gType |= TE_EWKB_Z_OFFSET;
02533 }
02534 else if((gType & 0xF00) == 0x700)
02535 {
02536 gType -= 2000;
02537 gType |= TE_EWKB_M_OFFSET;
02538 }
02539 }
02540
02541
02542 char* TePointToWKBPoint(const TePoint &point, unsigned int &size)
02543 {
02544 char byteOrder;
02545 unsigned int wkbType = 1;
02546 int srid = point.srid();
02547
02548
02549 if(((unsigned int) 1) == htonl((unsigned int) 1))
02550 {
02551 byteOrder = 0;
02552 }
02553 else
02554 {
02555 byteOrder = 1;
02556 }
02557
02558
02559 size = sizeof(char) + sizeof(int) + (2 * sizeof(double));
02560 if(srid != -1)
02561 {
02562 size += sizeof(int);
02563 }
02564
02565 char* p = new char[size];
02566 char* paux = p;
02567
02568
02569 memcpy(p, &byteOrder , sizeof(char));
02570 p += sizeof(char);
02571
02572
02573 if(srid == -1)
02574 {
02575 memcpy(p, &wkbType , sizeof(unsigned int));
02576 p += sizeof(unsigned int);
02577 }
02578 else
02579 {
02580 TeConvert2PostGISWKBType(wkbType);
02581
02582 wkbType |= TE_EWKB_SRID_FLAG;
02583
02584 memcpy(p, &wkbType , sizeof(unsigned int));
02585 p += sizeof(unsigned int);
02586
02587 memcpy(p, &srid, sizeof(int));
02588 p += sizeof(int);
02589 }
02590
02591 double x = point.location().x();
02592 double y = point.location().y();
02593
02594 memcpy(p, &x, sizeof(double));
02595 p += sizeof(double);
02596 memcpy(p, &y, sizeof(double));
02597 p += sizeof(double);
02598
02599 return paux;
02600 }
02601
02602
02603 char* TeLine2DToWKBLineString(const TeLine2D &line, unsigned int &size)
02604 {
02605 char byteOrder;
02606 unsigned int wkbType = 2;
02607 unsigned int nPoints = line.size();
02608 int srid = line.srid();
02609
02610
02611 if(((unsigned int) 1) == htonl((unsigned int) 1))
02612 {
02613 byteOrder = 0;
02614 }
02615 else
02616 {
02617 byteOrder = 1;
02618 }
02619
02620 size = sizeof(char) + sizeof(int) + sizeof(int) + (2 * sizeof(double) * nPoints);
02621 if(srid != -1)
02622 {
02623 size += sizeof(int);
02624 }
02625
02626 char* l = new char[size];
02627 char* laux = l;
02628
02629
02630 memcpy(l, &byteOrder , sizeof(char));
02631 l += sizeof(char);
02632
02633
02634 if(srid == -1)
02635 {
02636 memcpy(l, &wkbType , sizeof(unsigned int));
02637 l += sizeof(unsigned int);
02638 }
02639 else
02640 {
02641 TeConvert2PostGISWKBType(wkbType);
02642
02643 wkbType |= TE_EWKB_SRID_FLAG;
02644
02645 memcpy(l, &wkbType , sizeof(unsigned int));
02646 l += sizeof(unsigned int);
02647
02648 memcpy(l, &srid, sizeof(int));
02649 l += sizeof(int);
02650 }
02651
02652
02653 memcpy(l, &nPoints , sizeof(unsigned int));
02654 l += sizeof(unsigned int);
02655
02656 for(unsigned int i = 0; i < nPoints ; ++i)
02657 {
02658 double x = line[i].x();
02659 double y = line[i].y();
02660
02661 memcpy(l, &x, sizeof(double));
02662 l += sizeof(double);
02663
02664 memcpy(l, &y, sizeof(double));
02665 l += sizeof(double);
02666 }
02667
02668 return laux;
02669 }
02670
02671
02672 char* TePolygonToWKBPolygon(const TePolygon &polygon, unsigned int &size)
02673 {
02674 char byteOrder;
02675 unsigned int wkbType = 3;
02676 unsigned int nRings = polygon.size();
02677 int srid = polygon.srid();
02678
02679
02680 if(((unsigned int) 1) == htonl((unsigned int) 1))
02681 {
02682 byteOrder = 0;
02683 }
02684 else
02685 {
02686 byteOrder = 1;
02687 }
02688
02689
02690 size = sizeof(char) + sizeof(int) + sizeof(int);
02691 if(srid != -1)
02692 {
02693 size += sizeof(int);
02694 }
02695
02696 for(unsigned int i = 0; i < nRings ; ++i)
02697 {
02698 size += sizeof(int) + (2 * sizeof(double) * polygon[i].size());
02699 }
02700
02701 char* p = new char[size];
02702 char* paux = p;
02703
02704
02705 memcpy(p, &byteOrder , sizeof(char));
02706 p += sizeof(char);
02707
02708
02709 if(srid == -1)
02710 {
02711 memcpy(p, &wkbType , sizeof(unsigned int));
02712 p += sizeof(unsigned int);
02713 }
02714 else
02715 {
02716 TeConvert2PostGISWKBType(wkbType);
02717
02718 wkbType |= TE_EWKB_SRID_FLAG;
02719
02720 memcpy(p, &wkbType , sizeof(unsigned int));
02721 p += sizeof(unsigned int);
02722
02723 memcpy(p, &srid, sizeof(int));
02724 p += sizeof(int);
02725 }
02726
02727
02728 memcpy(p, &nRings , sizeof(unsigned int));
02729 p += sizeof(unsigned int);
02730
02731 for(unsigned int i = 0; i < nRings ; ++i)
02732 {
02733 TeLinearRing ring = polygon[i];
02734 unsigned int nPoints = ring.size();
02735
02736 memcpy(p, &nPoints, sizeof(int));
02737 p += sizeof(int);
02738
02739 for(unsigned int j = 0; j < nPoints; ++j)
02740 {
02741 double x = ring[j].x();
02742 double y = ring[j].y();
02743
02744 memcpy(p, &x, sizeof(double));
02745 p += sizeof(double);
02746
02747 memcpy(p, &y, sizeof(double));
02748 p += sizeof(double);
02749 }
02750 }
02751
02752 return paux;
02753 }
02754
02755
02756
02757