TePGInterface.cpp

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 *************************************************************************************/
00023 
00024 /*
00025  * TODO: 1. NAO PEGAR O DOBRO DE REGISTROS NA VOLTA (MOVE PREVIOUS) NO FUTURO!!!!
00026  *       2. set datestyle = 'ISO, YMD'
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  *      Read/write mode flags for inversion (large object) calls
00040  */
00041 
00042 #define INV_WRITE               0x00020000
00043 #define INV_READ                0x00040000
00044 
00045 /*
00046  * Read buffer size
00047  */
00048 #define BUFFSIZE        1024
00049 
00050 /*
00051  * PostgreSQL Geometric Types
00052  */
00053 typedef struct
00054 {
00055         double          x, y;
00056 } BIN_PG_POINT;
00057 
00058 using namespace std;
00059 
00060 /*******************************
00061  * FUN��ES AUXILIARES          *
00062  *******************************/
00063 // swapp bytes
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 // This function is the same parse_hex function in PostGIS rc3 source code.
00084 inline unsigned char parse_hex(char *str)
00085 {
00086         //do this a little brute force to make it faster
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 //Os trechos abaixo fram retirados do codigo fonte do Servidor PostgreSQL, pois aqui utilizamos cursores binarios
00197 // timestamp values are stored as seconds before or after midnight 2000-01-01
00198 #define UNIX_EPOCH_JDATE                2440588 /* == date2j(1970, 1, 1) */
00199 
00200 #define POSTGRES_EPOCH_JDATE    2451545 /* == date2j(2000, 1, 1) */
00201 #define MAXDATELEN              51              /* maximum possible length of an input date string (not counting tr. null) */
00202 #define MAXDATEFIELDS   25              /* maximum possible number of fields in a date string */
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 /* Decide if we need to decorate 64-bit constants */
00211 //#ifdef HAVE_LL_CONSTANTS
00212 #define INT64CONST(x)  ((te_int64) x##LL)
00213 //#else
00214 //#define INT64CONST(x)  ((te_int64) x)
00215 //#endif
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;                 /* origin 0, not 1 */
00244         int                     tm_year;                /* relative to 1900 */
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 }       /* j2date() */
00277 
00278 /* EncodeDateOnly()
00279  * Encode date as local time.
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         /* compatible with ISO date formats */
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 }       /* EncodeDateOnly() */
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 /* EncodeTimeOnly()
00311  * Encode time fields only.
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          * Print fractional seconds if any.  The field widths here should be
00322          * at least equal to the larger of MAX_TIME_PRECISION and
00323          * MAX_TIMESTAMP_PRECISION.
00324          */
00325         if(fsec != 0)
00326         {
00327                 sprintf((str + strlen(str)), ":%02d.%06d", tm->tm_sec, fsec);
00328 
00329                 /* chop off trailing pairs of zeros... */
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 }       /* EncodeTimeOnly() */
00349 
00350 inline void TrimTrailingZeros(char *str)
00351 {
00352         size_t  len = strlen(str);
00353 
00354         /* chop off trailing zeros... but leave at least 2 fractional digits */
00355         while ((*(str + len - 1) == '0') && (*(str + len - 3) != '.'))
00356         {
00357                 len--;
00358                 *(str + len) = '\0';
00359         }
00360 }
00361 
00362 
00363 /* EncodeDateTime()
00364  * Encode date and time interpreted as local time.
00365  * Support several date styles:
00366  *      Postgres - day mon hh:mm:ss yyyy tz
00367  *      SQL - mm/dd/yyyy hh:mm:ss.ss tz
00368  *      ISO - yyyy-mm-dd hh:mm:ss+/-tz
00369  *      German - dd.mm.yyyy hh:mm:ss tz
00370  * Variants (affects order of month and day for Postgres and SQL styles):
00371  *      US - mm/dd/yyyy
00372  *      European - dd/mm/yyyy
00373  */
00374 inline bool EncodeDateTime(struct te_pg_tm * tm, te_fsec_t fsec, int *tzp, char ** /* tzn */, char *str)
00375 {
00376         int                     hour,
00377                                 min;
00378 
00379         if ((tm->tm_mon < 1) || (tm->tm_mon > 12))
00380                 return false;
00381 
00382         /* Compatible with ISO-8601 date formats */
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                 * Print fractional seconds if any.  The field widths here
00390                 * should be at least equal to MAX_TIMESTAMP_PRECISION.
00391                 *
00392                 * In float mode, don't print fractional seconds before 1 AD,
00393                 * since it's unlikely there's any precision left ...
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                 * tzp == NULL indicates that we don't want *any* time zone
00406                 * info in the output string. *tzn != NULL indicates that we
00407                 * have alpha time zone info available. tm_isdst != -1
00408                 * indicates that we have a valid time zone translation.
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 /* EncodeSpecialTimestamp()
00425  * Convert reserved timestamp data type to string.
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 }       /* EncodeSpecialTimestamp() */
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 }       /* dt2time() */
00455 
00456 
00457 /*
00458  * timestamp2tm() - Convert timestamp data type to POSIX time structure.
00459  *
00460  * Note that year is _not_ 1900-based, but is an explicit full value.
00461  * Also, month is one-based, _not_ zero-based.
00462  * Returns:
00463  *       0 on success
00464  *      -1 on out of range
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          * If HasCTZSet is true then we have a brute force time zone
00473          * specified. Go ahead and rotate to the local time zone since we will
00474          * later bypass any calls which adjust the tm fields.
00475          */
00476         //if (HasCTZSet && (tzp != NULL))
00477         //{
00478         //      dt -= CTimeZone * INT64CONST(1000000);
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         /* add offset to go from J2000 back to standard Julian date */
00493         date      +=POSTGRES_EPOCH_JDATE;
00494 
00495         /* Julian day routine does not work for negative Julian days */
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         /* Done if no TZ conversion wanted */
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 //      return true;
00515 }
00516 
00517 /*******************************
00518  * Definicao de TePGConnection *
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: // The string sent to the backend was empty.
00587                                 break;
00588                 case PGRES_COMMAND_OK: // Successful completion of a command returning no data
00589                             resp = atoi(PQcmdTuples(result_temp));
00590                                 last_oid_ = PQoidValue(result_temp);
00591                                 break;
00592                 case PGRES_TUPLES_OK: // The query successfully executed
00593                                 break;
00594 
00595                 case PGRES_COPY_OUT: // Copy Out (from server) data transfer started
00596                 case PGRES_COPY_IN: // Copy In (to server) data transfer started
00597                                 break;
00598 
00599                 case PGRES_BAD_RESPONSE: // The server's response was not understood
00600                 case PGRES_NONFATAL_ERROR: // TODO: Is this one really an 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         //errorMessage_= PQresultErrorMessage(result_temp);
00736     switch (PQresultStatus(result_temp))
00737         {
00738                 case PGRES_EMPTY_QUERY: // The string sent to the backend was empty.
00739                                 break;
00740                 case PGRES_COMMAND_OK: // Successful completion of a command returning no data
00741                             resp = atoi(PQcmdTuples(result_temp));
00742                                 last_oid_ = PQoidValue(result_temp);
00743                                 break;
00744                 case PGRES_TUPLES_OK: // The query successfully executed
00745                                 break;
00746 
00747                 case PGRES_COPY_OUT: // Copy Out (from server) data transfer started
00748                 case PGRES_COPY_IN: // Copy In (to server) data transfer started
00749                                 break;
00750 
00751                 case PGRES_BAD_RESPONSE: // The server's response was not understood
00752                 case PGRES_NONFATAL_ERROR: // TODO: Is this one really an 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);  //Don't free lin because the return of PQgetvalue is in the struct PGResult
00773         }
00774         PQclear(result);
00775         return clientEncoding;
00776 }
00777 
00778 
00779 /******************************
00780  * Definicao de TePGRecordset *
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 //const int TePGRecordset::numRowsToRetrieve_ = 2000;
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         // endianness test
00799         if(((unsigned int) 1) == htonl((unsigned int) 1))
00800                 isLittleEndian_ = false;        
00801         else
00802                 isLittleEndian_ = true;
00803 
00804         recordSetId_ = TePGRecordset::getFreeCursor();
00805 
00806         /*if(freeCursorNumbers_.empty())
00807         {       // Se n�o houver cursores livres aberto => criar novo id
00808                 ++openRecordSets_;
00809                 recordSetId_ = openRecordSets_;
00810         }
00811         else
00812         {
00813                 set<int>::iterator it = freeCursorNumbers_.begin();
00814                 recordSetId_ = *it;
00815                 freeCursorNumbers_.erase(it);
00816         }*/
00817 
00818         if(!str_qry.empty() && conn_)
00819                 open(str_qry, conn_, cursorType_, cursorLocation_, cursorDataType_);
00820 }
00821 
00822 TePGRecordset::~TePGRecordset()
00823 {       
00824         // Deixa o id livre
00825         //freeCursorNumbers_.insert(recordSetId_);
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         //if(!cursorDeclared_ || (cursorType_ == TeUNIDIRECTIONAL))
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         //if(!cursorDeclared_ || (cursorType_ == TeUNIDIRECTIONAL))
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         //if(!cursorDeclared_ || (cursorType_ == TeUNIDIRECTIONAL))
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                    //sqlCursor += (cursorType_ == TeUNIDIRECTIONAL) ? " NO " : " ";
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    // TeBINARYCURSOR
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                 // POINT ARRAY IS SUPPOSED ALWAYS IN BIG ENDIAN
01316                 BIN_PG_POINT* pts = (BIN_PG_POINT*)(pgbox);
01317 
01318                 // endianness test
01319                 if(isLittleEndian_)
01320                 {
01321                         union
01322                         {
01323                                 double dWord_;
01324                                 unsigned int aux_[2];
01325                         } swapx1, swapy1, swapx2, swapy2;
01326 
01327                         // little-endian
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                         // big-endian!
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    //TeTEXTCURSOR
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                 // POINT ARRAY IS SUPPOSED ALWAYS IN BIG ENDIAN
01385                 BIN_PG_POINT* pts = (BIN_PG_POINT*)(polygon + sizeof(int));             
01386 
01387                 // endianness test
01388                 if(isLittleEndian_)
01389                 {
01390                         union
01391                         {
01392                                 double dWord_;
01393                                 unsigned int aux_[2];
01394                         } swapx1, swapy1, swapx2, swapy2;
01395 
01396                         // little-endian
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                         // big-endian!
01415                         for(unsigned int i = 0; i < numPts ; ++i)
01416                                 l.add(TeCoord2D(pts[i].x, pts[i].y));
01417                         
01418                 }
01419         }
01420         else    //TeTEXTCURSOR
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         // 0 = Big Endian (wkbXDR) e 1 = Little Endian (wkbNDR)
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 //added for EWKB compatibility
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                 // 0 = Big Endian (wkbXDR) e 1 = Little Endian (wkbNDR)
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) // len/2
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)); // x + y
01566         }
01567 
01568         // 0 = Big Endian (wkbXDR)
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); // x + y
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         // 0 = Big Endian (wkbXDR) e 1 = Little Endian (wkbNDR)
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) // len/2
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                 // 0 = Big Endian (wkbXDR)
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_)   //1 = Little Endian (wkbNDR)
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                 // Volta duas vezes o n�mero de bytes do n�mero de geometrias lidos ao chamar getWKBHeader
01741                 v = getWKBLinearRing(v - (sizeof(unsigned int) + sizeof(unsigned int)), byteOrder, l);
01742         }
01743         else
01744         {
01745                 // Volta o n�mero de bytes do n�mero de geometrias lidos ao chamar getWKBHeader
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         //TeWKBGeometryDecoder::getWKBHeader(v, byteOrder, wkbType, numRings);
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 // for binary cursors only
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                 // chamar o conversor de tipo de dado de binario p/ string p/ cada tipo!
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];   //integer part if DECIMAL(p,s) or NUMERIC(p,s)
02297  //int size = -1;
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:      // CHAR(n)
02311         case 1043:   //VARCHAR(s) or CHARACTER VARYING(s)
02312         case 1700:   //NUMERIC(p,s) or DECIMAL(p,s)
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);  //Don't free lin because the return of PQgetvalue is in the struct PGResult
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:     //The size of fixed size or for other variable size -1
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];   //fractionary part if DECIMAL(p,s) or NUMERIC(p,s)
02345  //int size = -1;
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:   //NUMERIC(p,s) or DECIMAL(p,s)
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);  //Don't free lin because the return of PQgetvalue is in the struct PGResult
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:     //Others doesn't have a fractionary part
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         //coloca o cabe�alho (Numero de pontos)
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         // endianness test
02476         if(((unsigned int) 1) == htonl((unsigned int) 1))
02477         {
02478                 //isLittleEndian_ = false => doesn't need to swap bytes;        
02479                 swapIN.dWord_ = value;
02480 
02481                 memcpy(&swappedValue, &swapIN.dWord_, sizeof(double));
02482         }               
02483         else
02484         {
02485                 //isLittleEndian_ = true  => swap bytes;
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)  // Is PostGIS?
02500     {
02501                 isPostGIS = true;
02502 
02503                 if((gType & TE_EWKB_ZM_OFFSET) == 0xC0000000) // z and m is on
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)    // it is zm
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;//WKBPoint
02546         int srid = point.srid();
02547 
02548         // 0 = Big Endian (wkbXDR) e 1 = Little Endian (wkbNDR)
02549         if(((unsigned int) 1) == htonl((unsigned int) 1))
02550         {
02551                 byteOrder = 0;
02552         }
02553         else
02554         {
02555                 byteOrder = 1;          
02556         }
02557 
02558         //cabecalho
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         //byteOrder     
02569         memcpy(p, &byteOrder , sizeof(char));
02570         p += sizeof(char);
02571 
02572         //WKBPoint
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;//WKBLineString
02607         unsigned int nPoints = line.size();
02608         int srid = line.srid();
02609 
02610         // 0 = Big Endian (wkbXDR) e 1 = Little Endian (wkbNDR)
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         //byteOrder     
02630         memcpy(l, &byteOrder , sizeof(char));
02631         l += sizeof(char);
02632 
02633         //WKBLineString
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         //nPoints
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;//WKBPolygon
02676         unsigned int nRings = polygon.size();
02677         int srid = polygon.srid();
02678 
02679         // 0 = Big Endian (wkbXDR) e 1 = Little Endian (wkbNDR)
02680         if(((unsigned int) 1) == htonl((unsigned int) 1))
02681         {
02682                 byteOrder = 0;
02683         }
02684         else
02685         {
02686                 byteOrder = 1;          
02687         }
02688 
02689         //cabecalho
02690         size = sizeof(char) + sizeof(int) + sizeof(int);
02691         if(srid != -1)
02692         {
02693                 size += sizeof(int);
02694         }
02695         //rings
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         //byteOrder     
02705         memcpy(p, &byteOrder , sizeof(char));
02706         p += sizeof(char);
02707 
02708         //WKBPolygon
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         //nRings
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 

Generated on Sun Jul 29 04:01:26 2012 for TerraLib - Development Source by  doxygen 1.5.3