~ubuntu-branches/ubuntu/hardy/libterralib/hardy

« back to all changes in this revision

Viewing changes to src/terralib/drivers/PostgreSQL/TePGInterface.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Daniel T Chen
  • Date: 2005-11-25 22:32:59 UTC
  • Revision ID: james.westby@ubuntu.com-20051125223259-3zubal8ux4ki4fjg
Tags: upstream-3.0.3b2
Import upstream version 3.0.3b2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/************************************************************************************
 
2
TerraLib - a library for developing GIS applications.
 
3
Copyright � 2001-2004 INPE and Tecgraf/PUC-Rio.
 
4
 
 
5
This code is part of the TerraLib library.
 
6
This library is free software; you can redistribute it and/or
 
7
modify it under the terms of the GNU Lesser General Public
 
8
License as published by the Free Software Foundation; either
 
9
version 2.1 of the License, or (at your option) any later version.
 
10
 
 
11
You should have received a copy of the GNU Lesser General Public
 
12
License along with this library.
 
13
 
 
14
The authors reassure the license terms regarding the warranties.
 
15
They specifically disclaim any warranties, including, but not limited to,
 
16
the implied warranties of merchantability and fitness for a particular purpose.
 
17
The library provided hereunder is on an "as is" basis, and the authors have no
 
18
obligation to provide maintenance, support, updates, enhancements, or modifications.
 
19
In no event shall INPE and Tecgraf / PUC-Rio be held liable to any party for direct,
 
20
indirect, special, incidental, or consequential damages arising out of the use
 
21
of this library and its documentation.
 
22
*************************************************************************************/
 
23
 
 
24
/*
 
25
 * TODO: 1. N�O PEGAR O DOBRO DE REGISTROS NA VOLTA (MOVE PREVIOUS) NO FUTURO!!!!
 
26
 *
 
27
 */
 
28
 
 
29
#include "TePGInterface.h"
 
30
#include "TePGUtils.h"
 
31
#include <stdexcept>
 
32
#include <string>
 
33
 
 
34
 
 
35
 
 
36
#include "TeUtils.h"
 
37
 
 
38
/*
 
39
 *      Read/write mode flags for inversion (large object) calls
 
40
 */
 
41
 
 
42
#define INV_WRITE               0x00020000
 
43
#define INV_READ                0x00040000
 
44
 
 
45
/*
 
46
 * Read buffer size
 
47
 */
 
48
#define BUFFSIZE        1024
 
49
 
 
50
/*
 
51
 * PostgreSQL Geometric Types
 
52
 */
 
53
typedef struct
 
54
{
 
55
        double          x, y;
 
56
} BIN_PG_POINT;
 
57
 
 
58
using namespace std;
 
59
 
 
60
/*******************************
 
61
 * FUN��ES AUXILIARES          *
 
62
 *******************************/
 
63
// This function is the same parse_hex function in PostGIS rc3 source code.
 
64
inline unsigned char parse_hex(char *str)
 
65
{
 
66
        //do this a little brute force to make it faster
 
67
 
 
68
        unsigned char           result_high = 0;
 
69
        unsigned char           result_low = 0;
 
70
 
 
71
        switch (str[0])
 
72
        {
 
73
                case '0' :
 
74
                        result_high = 0;
 
75
                        break;
 
76
                case '1' :
 
77
                        result_high = 1;
 
78
                        break;
 
79
                case '2' :
 
80
                        result_high = 2;
 
81
                        break;
 
82
                case '3' :
 
83
                        result_high = 3;
 
84
                        break;
 
85
                case '4' :
 
86
                        result_high = 4;
 
87
                        break;
 
88
                case '5' :
 
89
                        result_high = 5;
 
90
                        break;
 
91
                case '6' :
 
92
                        result_high = 6;
 
93
                        break;
 
94
                case '7' :
 
95
                        result_high = 7;
 
96
                        break;
 
97
                case '8' :
 
98
                        result_high = 8;
 
99
                        break;
 
100
                case '9' :
 
101
                        result_high = 9;
 
102
                        break;
 
103
                case 'A' :
 
104
                        result_high = 10;
 
105
                        break;
 
106
                case 'B' :
 
107
                        result_high = 11;
 
108
                        break;
 
109
                case 'C' :
 
110
                        result_high = 12;
 
111
                        break;
 
112
                case 'D' :
 
113
                        result_high = 13;
 
114
                        break;
 
115
                case 'E' :
 
116
                        result_high = 14;
 
117
                        break;
 
118
                case 'F' :
 
119
                        result_high = 15;
 
120
                        break;
 
121
        }
 
122
        switch (str[1])
 
123
        {
 
124
                case '0' :
 
125
                        result_low = 0;
 
126
                        break;
 
127
                case '1' :
 
128
                        result_low = 1;
 
129
                        break;
 
130
                case '2' :
 
131
                        result_low = 2;
 
132
                        break;
 
133
                case '3' :
 
134
                        result_low = 3;
 
135
                        break;
 
136
                case '4' :
 
137
                        result_low = 4;
 
138
                        break;
 
139
                case '5' :
 
140
                        result_low = 5;
 
141
                        break;
 
142
                case '6' :
 
143
                        result_low = 6;
 
144
                        break;
 
145
                case '7' :
 
146
                        result_low = 7;
 
147
                        break;
 
148
                case '8' :
 
149
                        result_low = 8;
 
150
                        break;
 
151
                case '9' :
 
152
                        result_low = 9;
 
153
                        break;
 
154
                case 'A' :
 
155
                        result_low = 10;
 
156
                        break;
 
157
                case 'B' :
 
158
                        result_low = 11;
 
159
                        break;
 
160
                case 'C' :
 
161
                        result_low = 12;
 
162
                        break;
 
163
                case 'D' :
 
164
                        result_low = 13;
 
165
                        break;
 
166
                case 'E' :
 
167
                        result_low = 14;
 
168
                        break;
 
169
                case 'F' :
 
170
                        result_low = 15;
 
171
                        break;
 
172
        }
 
173
        return (unsigned char) ((result_high<<4) + result_low);
 
174
}
 
175
 
 
176
 
 
177
/*******************************
 
178
 * Definicao de TePGConnection *
 
179
 *******************************/
 
180
bool TePGConnection::open(const string& str_connection)
 
181
{
 
182
        close();
 
183
 
 
184
        pg_connection_ = PQconnectdb(str_connection.c_str());
 
185
 
 
186
        if(this->state())
 
187
        {
 
188
                int_connection_ = 1;
 
189
                return true;
 
190
        }
 
191
        else
 
192
                return false;
 
193
}
 
194
 
 
195
void TePGConnection::close(void)
 
196
{
 
197
 if(int_connection_)
 
198
   {
 
199
    if(pg_connection_)
 
200
      {
 
201
       PQfinish(pg_connection_);
 
202
      }
 
203
    pg_connection_ = 0;
 
204
    int_connection_ = 0;
 
205
   }
 
206
 return;
 
207
}
 
208
 
 
209
 
 
210
int TePGConnection::exec_cmd(const string& str_qry)
 
211
{
 
212
 PGresult *result_temp;
 
213
 int resp = -1;
 
214
 result_temp = PQexec(pg_connection_, str_qry.c_str());
 
215
 
 
216
    switch (PQresultStatus(result_temp))
 
217
        {
 
218
                case PGRES_EMPTY_QUERY: // The string sent to the backend was empty.
 
219
                                break;
 
220
                case PGRES_COMMAND_OK: // Successful completion of a command returning no data
 
221
                            resp = atoi(PQcmdTuples(result_temp));
 
222
                                last_oid_ = PQoidValue(result_temp);
 
223
                                break;
 
224
                case PGRES_TUPLES_OK: // The query successfully executed
 
225
                                break;
 
226
 
 
227
                case PGRES_COPY_OUT: // Copy Out (from server) data transfer started
 
228
                case PGRES_COPY_IN: // Copy In (to server) data transfer started
 
229
                                break;
 
230
 
 
231
                case PGRES_BAD_RESPONSE: // The server's response was not understood
 
232
                case PGRES_NONFATAL_ERROR: // TODO: Is this one really an error?
 
233
                case PGRES_FATAL_ERROR:
 
234
                        throw runtime_error("The server's response was not understood");
 
235
 
 
236
                default:
 
237
                        throw logic_error("Internal lib TePGInterface error: ");
 
238
        }
 
239
 
 
240
 PQclear(result_temp);
 
241
 result_temp = 0;
 
242
 return resp;
 
243
}
 
244
 
 
245
Oid TePGConnection::insertBlob(char* buff, const int& blobSize)
 
246
{
 
247
        if(!buff)
 
248
                return 0;
 
249
 
 
250
        Oid obj_oid = lo_creat(pg_connection_, INV_READ | INV_WRITE);
 
251
 
 
252
        int fd  = lo_open(pg_connection_, obj_oid, INV_READ);
 
253
 
 
254
        if(fd < 0)
 
255
                return 0;
 
256
 
 
257
        int nbwrite = 0;
 
258
 
 
259
        int size_tmp = blobSize;
 
260
 
 
261
        while(size_tmp > 0)
 
262
        {
 
263
                if((size_tmp - BUFFSIZE) >= 0)
 
264
                        nbwrite = lo_write(pg_connection_, fd, buff, BUFFSIZE);                         
 
265
                else
 
266
                        nbwrite = lo_write(pg_connection_, fd, buff, size_tmp);
 
267
 
 
268
                if(nbwrite <= 0)
 
269
                        return 0;
 
270
 
 
271
                buff += nbwrite;
 
272
                size_tmp -= nbwrite;
 
273
        }
 
274
 
 
275
        if(lo_close(pg_connection_, fd) == 0)
 
276
                return obj_oid;
 
277
 
 
278
        return 0;
 
279
}
 
280
 
 
281
int TePGConnection::getBlob(const Oid& blobId, char *&buff)
 
282
{
 
283
        int fd = lo_open(pg_connection_, blobId, INV_READ);
 
284
 
 
285
        if(fd < 0)
 
286
                return -1;
 
287
 
 
288
        int len = lo_lseek(pg_connection_, fd, 0, SEEK_END);
 
289
 
 
290
        lo_lseek(pg_connection_, fd, 0, SEEK_SET);
 
291
 
 
292
        if(len <= 0)
 
293
                return len;
 
294
 
 
295
        if(!buff)
 
296
                buff = new char[len];
 
297
 
 
298
        char* buffAux = buff;
 
299
 
 
300
        int nbread = 0;
 
301
 
 
302
        while((nbread = lo_read(pg_connection_, fd, buffAux, BUFFSIZE)) > 0)
 
303
                buffAux += nbread;
 
304
 
 
305
        return len;
 
306
}
 
307
 
 
308
bool TePGConnection::beginTransaction(void)
 
309
{
 
310
        if(inTransaction_)
 
311
                return true;
 
312
 
 
313
        if(exec_cmd("BEGIN TRANSACTION") == 0)
 
314
        {
 
315
                inTransaction_ = true;
 
316
 
 
317
                return true;
 
318
        }
 
319
 
 
320
        return false;
 
321
}
 
322
 
 
323
 
 
324
bool TePGConnection::commitTransaction(void)
 
325
{
 
326
        if(exec_cmd("COMMIT TRANSACTION") == 0)
 
327
        {
 
328
                inTransaction_ = false;
 
329
 
 
330
                return true;
 
331
        }
 
332
 
 
333
        return false;
 
334
}
 
335
 
 
336
bool TePGConnection::rollBackTransaction(void)
 
337
{
 
338
        if(exec_cmd("ROLLBACK TRANSACTION") == 0)
 
339
        {
 
340
                inTransaction_ = false;
 
341
 
 
342
                return true;
 
343
        }
 
344
 
 
345
        return false;
 
346
}
 
347
 
 
348
 
 
349
/******************************
 
350
 * Definicao de TePGRecordset *
 
351
 ******************************/
 
352
const int TePGRecordset::int_bof_ = -1;
 
353
int TePGRecordset::openRecordSets_ = 0;
 
354
set<int> TePGRecordset::freeCursorNumbers_;
 
355
//const int TePGRecordset::numRowsToRetrieve_ = 2000;
 
356
 
 
357
TePGRecordset::TePGRecordset(const string& str_qry, TePGConnection* con_x,
 
358
                                         const TeCursorType& cursorType,
 
359
                                             const TeCursorLocation& cursorLocation,
 
360
                                             const TeCursorDataType& cursorDataType,
 
361
                                                 const int& numRowsToRetrieve)
 
362
 : pg_recordset_(0), conn_(con_x), cursorDeclared_(false), int_index_current_(-1),
 
363
   int_eof_(-1), cursorType_(cursorType), cursorLocation_(cursorLocation), 
 
364
   cursorDataType_(cursorDataType), numRowsToRetrieve_(numRowsToRetrieve)
 
365
{
 
366
        // endianness test
 
367
        if(((unsigned int) 1) == htonl((unsigned int) 1))
 
368
                isLittleEndian_ = false;        
 
369
        else
 
370
                isLittleEndian_ = true;
 
371
 
 
372
        if(freeCursorNumbers_.empty())
 
373
        {       // Se n�o houver cursores livres aberto => criar novo id
 
374
                ++openRecordSets_;
 
375
                recordSetId_ = openRecordSets_;
 
376
        }
 
377
        else
 
378
        {
 
379
                set<int>::iterator it = freeCursorNumbers_.begin();
 
380
                recordSetId_ = *it;
 
381
                freeCursorNumbers_.erase(it);
 
382
        }
 
383
 
 
384
        if(!str_qry.empty() && conn_)
 
385
                open(str_qry, conn_, cursorType_, cursorLocation_, cursorDataType_);
 
386
}
 
387
 
 
388
TePGRecordset::~TePGRecordset()
 
389
{       
 
390
        // Deixa o id livre
 
391
        freeCursorNumbers_.insert(recordSetId_);
 
392
 
 
393
        close();
 
394
}
 
395
 
 
396
void TePGRecordset::close(void)
 
397
{
 
398
        if(cursorDeclared_ && conn_)
 
399
        {
 
400
                string sqlCloseCursor  = "CLOSE CURSOR_";
 
401
                   sqlCloseCursor += Te2String(recordSetId_);
 
402
 
 
403
                conn_->exec_cmd(sqlCloseCursor.c_str());
 
404
        }       
 
405
 
 
406
        freeRecordSet();
 
407
 
 
408
        cursorDeclared_ = false;
 
409
 
 
410
        conn_ = 0;
 
411
 
 
412
        return;
 
413
}
 
414
 
 
415
bool TePGRecordset::moveFirst(void)
 
416
{
 
417
        if(!cursorDeclared_)
 
418
                return false;
 
419
 
 
420
        if(cursorLocation_ == TeCLIENTESIDE)
 
421
        {
 
422
                if(recordCount() > 0)
 
423
                {
 
424
                        int_index_current_ = 0;
 
425
                        return true;
 
426
                }
 
427
                else
 
428
                        return false;
 
429
        }
 
430
 
 
431
        firstFetch = false;
 
432
        lastFetch = false;
 
433
 
 
434
        string moveFirstSQL  = "MOVE ABSOLUTE 0 IN CURSOR_";
 
435
                   moveFirstSQL += Te2String(recordSetId_);
 
436
 
 
437
        int res = conn_->exec_cmd(moveFirstSQL.c_str());
 
438
 
 
439
        if(res == 0)
 
440
        {
 
441
                freeRecordSet();
 
442
 
 
443
                string fetchSQL  = "FETCH FORWARD " + Te2String(numRowsToRetrieve_);
 
444
                   fetchSQL += " FROM CURSOR_";
 
445
                       fetchSQL += Te2String(recordSetId_);
 
446
 
 
447
                pg_recordset_ = conn_->exec(fetchSQL.c_str());
 
448
 
 
449
                if(PQresultStatus(pg_recordset_) == PGRES_TUPLES_OK)
 
450
                {
 
451
                        if(recordCount() > 0)
 
452
                        {
 
453
                                int_eof_ = recordCount();
 
454
                                int_index_current_ = 0;
 
455
                                return true;
 
456
                        }
 
457
                }
 
458
                
 
459
                freeRecordSet();
 
460
                return false;
 
461
        }
 
462
 
 
463
        return false;
 
464
}
 
465
 
 
466
bool TePGRecordset::movePrevious(void)
 
467
{       
 
468
        //if(!cursorDeclared_ || (cursorType_ == TeUNIDIRECTIONAL))
 
469
        if(!cursorDeclared_)
 
470
                return false;
 
471
 
 
472
        if(cursorLocation_ == TeCLIENTESIDE)
 
473
        {
 
474
                if(bof())
 
475
                        return false;
 
476
                else
 
477
                {
 
478
                        --int_index_current_;
 
479
                        return true;
 
480
                }
 
481
        }
 
482
 
 
483
        if(recordCount() > 0)
 
484
        {
 
485
                string move = "";
 
486
                string fetchSQL = "";
 
487
 
 
488
                if(!movingBackward_)
 
489
                {
 
490
                         if(bof())
 
491
                                 return false;
 
492
                
 
493
                        --int_index_current_;
 
494
 
 
495
                        if(bof())
 
496
                        {
 
497
                                movingBackward_ = true;
 
498
 
 
499
                                int val = recordCount() - 1;
 
500
 
 
501
                                if(lastFetch)
 
502
                                {
 
503
                                        ++val;
 
504
                                }
 
505
 
 
506
                                move = " MOVE BACKWARD "+Te2String(val)+" FROM CURSOR_"+Te2String(recordSetId_)+";";
 
507
 
 
508
                                fetchSQL = move;
 
509
                                fetchSQL += " FETCH BACKWARD ";
 
510
                                fetchSQL += Te2String(numRowsToRetrieve_);
 
511
                                fetchSQL += " FROM CURSOR_";
 
512
                                fetchSQL += Te2String(recordSetId_);
 
513
                        }
 
514
                        else
 
515
                        {
 
516
                                return true;
 
517
                        }
 
518
                }
 
519
                else
 
520
                {
 
521
                        if(eof())
 
522
                                 return false;
 
523
                
 
524
                        ++int_index_current_;
 
525
 
 
526
                        if(eof())
 
527
                        {       
 
528
                                fetchSQL  = "FETCH BACKWARD ";
 
529
                                fetchSQL += Te2String(numRowsToRetrieve_);
 
530
                                fetchSQL += " FROM CURSOR_";
 
531
                                fetchSQL += Te2String(recordSetId_);
 
532
                        }
 
533
                        else
 
534
                        {
 
535
                                return true;
 
536
                        }
 
537
                }
 
538
                pg_recordset_ = conn_->exec(fetchSQL.c_str());
 
539
 
 
540
                if(PQresultStatus(pg_recordset_) == PGRES_TUPLES_OK)
 
541
                {                       
 
542
                        firstFetch = false;
 
543
                        lastFetch = false;
 
544
                        
 
545
                        if(this->recordCount() > 0)
 
546
                        {
 
547
                                int_eof_ = recordCount();
 
548
                                int_index_current_ = 0;
 
549
 
 
550
                                if(this->recordCount() > 0 != numRowsToRetrieve_)
 
551
                                {
 
552
                                        firstFetch = true;
 
553
                                }
 
554
 
 
555
 
 
556
                                return true;
 
557
                        }
 
558
                        
 
559
                }
 
560
 
 
561
                freeRecordSet();
 
562
        }
 
563
 
 
564
        return false;
 
565
}
 
566
 
 
567
bool TePGRecordset::moveNext(void)
 
568
{
 
569
        if(!cursorDeclared_)
 
570
                return false;
 
571
 
 
572
        if(cursorLocation_ == TeCLIENTESIDE)
 
573
        {
 
574
                if(eof())
 
575
                        return false;
 
576
 
 
577
                ++int_index_current_;
 
578
 
 
579
                return true;
 
580
        }
 
581
 
 
582
        if((recordCount() > 0))
 
583
        {
 
584
                string move = "";
 
585
                string fetchSQL = "";
 
586
 
 
587
                if(!movingBackward_)
 
588
                {       
 
589
                        if(!eof())
 
590
                        {
 
591
                                ++int_index_current_;
 
592
 
 
593
                                if(eof())
 
594
                                {
 
595
                                        fetchSQL  = "FETCH FORWARD ";
 
596
                                        fetchSQL += Te2String(numRowsToRetrieve_);
 
597
                                        fetchSQL += " FROM CURSOR_";
 
598
                                        fetchSQL += Te2String(recordSetId_);
 
599
                                }
 
600
                                else
 
601
                                {
 
602
                                        return true;
 
603
                                }
 
604
                        }
 
605
                }
 
606
                else
 
607
                {
 
608
                        if(!bof())
 
609
                        {
 
610
                                --int_index_current_;
 
611
 
 
612
                                if(bof())
 
613
                                {
 
614
                                        movingBackward_ = false;        
 
615
                                        int val = recordCount() -1;
 
616
                                        if(firstFetch)
 
617
                                        {
 
618
                                                ++val;
 
619
                                        }
 
620
                                        move = " MOVE FORWARD "+Te2String(val)+" FROM CURSOR_"+Te2String(recordSetId_)+";";
 
621
 
 
622
                                        fetchSQL = move;
 
623
 
 
624
                                        fetchSQL += "FETCH FORWARD ";
 
625
                                        fetchSQL += Te2String(numRowsToRetrieve_);
 
626
                                        fetchSQL += " FROM CURSOR_";
 
627
                                        fetchSQL += Te2String(recordSetId_);
 
628
                                }
 
629
                                else
 
630
                                {
 
631
                                        return true;
 
632
                                }
 
633
                        }
 
634
                }
 
635
                freeRecordSet();
 
636
 
 
637
                pg_recordset_ = conn_->exec(fetchSQL.c_str());
 
638
 
 
639
                if(PQresultStatus(pg_recordset_) == PGRES_TUPLES_OK)
 
640
                {
 
641
                        firstFetch = false;
 
642
                        lastFetch = false;
 
643
 
 
644
                        if(recordCount() > 0)
 
645
                        {
 
646
                                int_eof_ = recordCount();
 
647
                                int_index_current_ = 0;
 
648
 
 
649
                                if(this->recordCount() > 0 != numRowsToRetrieve_)
 
650
                                {
 
651
                                        lastFetch = true;
 
652
                                }
 
653
                                
 
654
                                return true;
 
655
                        }
 
656
                }
 
657
                
 
658
                freeRecordSet();
 
659
        }
 
660
 
 
661
        return false;
 
662
}
 
663
 
 
664
bool TePGRecordset::moveLast(void)
 
665
{
 
666
        //if(!cursorDeclared_ || (cursorType_ == TeUNIDIRECTIONAL))
 
667
        if(!cursorDeclared_)
 
668
                return false;
 
669
 
 
670
        if(cursorLocation_ == TeCLIENTESIDE)
 
671
        {
 
672
                if(recordCount() > 0)
 
673
                {
 
674
                        int_index_current_ = recordCount() - 1;
 
675
                        return true;
 
676
                }
 
677
                
 
678
                return false;
 
679
        }
 
680
 
 
681
        firstFetch = false;
 
682
        lastFetch = false;
 
683
 
 
684
        freeRecordSet();
 
685
 
 
686
        string fetchSQL  = "FETCH LAST FROM CURSOR_";
 
687
                   fetchSQL += Te2String(recordSetId_);
 
688
 
 
689
        pg_recordset_ = conn_->exec(fetchSQL.c_str());
 
690
 
 
691
        if(PQresultStatus(pg_recordset_) == PGRES_TUPLES_OK)
 
692
        {
 
693
                if(this->recordCount() > 0)
 
694
                {
 
695
                        int_eof_ = recordCount();
 
696
                        int_index_current_ = 0;
 
697
                        return true;
 
698
                }               
 
699
        }
 
700
        
 
701
        freeRecordSet();
 
702
 
 
703
        return false;
 
704
        
 
705
}
 
706
 
 
707
bool TePGRecordset::moveTo(const int& lin_number)
 
708
{
 
709
        //if(!cursorDeclared_ || (cursorType_ == TeUNIDIRECTIONAL))
 
710
        if(!cursorDeclared_)
 
711
                return false;
 
712
 
 
713
        if(cursorLocation_ == TeCLIENTESIDE)
 
714
        {
 
715
                if((lin_number > int_bof_) && (lin_number < int_eof_))
 
716
                {
 
717
                        int_index_current_ = lin_number;
 
718
                        return true;
 
719
                }
 
720
                
 
721
                return false;           
 
722
        }
 
723
 
 
724
        firstFetch = false;
 
725
        lastFetch = false;
 
726
 
 
727
        freeRecordSet();
 
728
 
 
729
        string fetchSQL  = "FETCH ABSOLUTE ";
 
730
                   fetchSQL += Te2String(lin_number);
 
731
               fetchSQL += " FROM CURSOR_";
 
732
                   fetchSQL += Te2String(recordSetId_);
 
733
 
 
734
        pg_recordset_ = conn_->exec(fetchSQL.c_str());
 
735
 
 
736
        if(PQresultStatus(pg_recordset_) == PGRES_TUPLES_OK)
 
737
        {
 
738
                if(this->recordCount() > 0)
 
739
                {
 
740
                        int_eof_ = recordCount();
 
741
                        int_index_current_ = 0;
 
742
                        return true;
 
743
                }
 
744
        }
 
745
 
 
746
        freeRecordSet();
 
747
 
 
748
        return false;   
 
749
}
 
750
 
 
751
bool TePGRecordset::open(const string& str_qry, TePGConnection* con_x,
 
752
                              const TeCursorType& cursorType,
 
753
                                  const TeCursorLocation& cursorLocation,
 
754
                                  const TeCursorDataType& cursorDataType,
 
755
                                  const int& numRowsToRetrieve)
 
756
{
 
757
        close();
 
758
 
 
759
        if(str_qry.empty() || !con_x)
 
760
                return false;
 
761
 
 
762
        cursorType_ = cursorType;
 
763
        cursorLocation_ = cursorLocation;
 
764
        cursorDataType_ = cursorDataType;
 
765
        numRowsToRetrieve_ = numRowsToRetrieve;
 
766
        cursorDeclared_ = false;
 
767
        conn_ = con_x;
 
768
        movingBackward_ = false;
 
769
        lastFetch = false;
 
770
        firstFetch = false;
 
771
 
 
772
        string sqlCursor  = "DECLARE CURSOR_";
 
773
                   sqlCursor += Te2String(recordSetId_);
 
774
                   sqlCursor += (cursorDataType_  == TeBINARYCURSOR) ? " BINARY " : " ";
 
775
                   //sqlCursor += (cursorType_ == TeUNIDIRECTIONAL) ? " NO " : " ";
 
776
                   sqlCursor += "SCROLL CURSOR WITH HOLD FOR ";
 
777
                   sqlCursor += str_qry;        
 
778
 
 
779
        pg_recordset_ = conn_->exec(sqlCursor.c_str());
 
780
 
 
781
        if(PQresultStatus(pg_recordset_) == PGRES_COMMAND_OK)
 
782
        {
 
783
                cursorDeclared_ = true;
 
784
 
 
785
                string numRows = (cursorLocation_ == TeSERVERSIDE) ? Te2String(numRowsToRetrieve_) : string("ALL");
 
786
                
 
787
                string fetchSQL  = "FETCH FORWARD " + numRows;
 
788
                   fetchSQL += " FROM CURSOR_";
 
789
                       fetchSQL += Te2String(recordSetId_);
 
790
 
 
791
                pg_recordset_ = conn_->exec(fetchSQL.c_str());
 
792
 
 
793
                if(PQresultStatus(pg_recordset_) == PGRES_TUPLES_OK)
 
794
                {
 
795
                        if(recordCount() > 0)
 
796
                        {
 
797
                                int_eof_ = recordCount();
 
798
                                int_index_current_ = 0;                         
 
799
                        }
 
800
 
 
801
                        return true;
 
802
                }
 
803
        }
 
804
        
 
805
        freeRecordSet();
 
806
 
 
807
        return false;
 
808
}
 
809
 
 
810
int TePGRecordset::getBytea(const int& field_num, char*& buff) const
 
811
{
 
812
        if(cursorDataType_ == TeTEXTCURSOR)
 
813
        {
 
814
                size_t newLen;
 
815
 
 
816
                unsigned char* ptData = PQunescapeBytea((unsigned char*)(value(field_num)), &newLen);
 
817
 
 
818
                if(newLen <= 0)
 
819
                        return newLen;
 
820
                
 
821
                if(!buff)
 
822
                        buff = new char[newLen];
 
823
 
 
824
                memcpy(buff, ptData, newLen);
 
825
 
 
826
                TePGConnection::freeMem(ptData);
 
827
 
 
828
                return newLen;
 
829
        }
 
830
        else    // TeBINARYCURSOR
 
831
        {
 
832
                char* ptData = value(field_num);
 
833
 
 
834
                unsigned int numBytes;
 
835
                memcpy(&numBytes, ptData, sizeof(int));
 
836
                numBytes = ntohl(numBytes);
 
837
 
 
838
                if(!buff)
 
839
                        buff = new char[numBytes];
 
840
 
 
841
                memcpy(buff, ptData + sizeof(int), numBytes);
 
842
 
 
843
                return numBytes;
 
844
        }
 
845
}
 
846
 
 
847
void TePGRecordset::getPGLine2D(const int& field_num, TeLine2D& l) const
 
848
{
 
849
        char* polygon = value(field_num);
 
850
 
 
851
        if(cursorDataType_ == TeBINARYCURSOR)
 
852
        {
 
853
                unsigned int numPts;
 
854
                memcpy(&numPts, polygon, sizeof(int));
 
855
                numPts = ntohl(numPts);
 
856
 
 
857
                l.reserve(numPts);
 
858
 
 
859
                // POINT ARRAY IS SUPPOSED ALWAYS IN BIG ENDIAN
 
860
                BIN_PG_POINT* pts = (BIN_PG_POINT*)(polygon + sizeof(int));             
 
861
 
 
862
                // endianness test
 
863
                if(isLittleEndian_)
 
864
                {
 
865
                        union
 
866
                        {
 
867
                                double dWord_;
 
868
                                unsigned int aux_[2];
 
869
                        } swapx1, swapy1, swapx2, swapy2;
 
870
 
 
871
                        // little-endian
 
872
                        for(unsigned int i = 0; i < numPts ; ++i)
 
873
                        {
 
874
                                swapx1.dWord_ = pts[i].x;
 
875
                                swapy1.dWord_ = pts[i].y;
 
876
 
 
877
                                swapx2.aux_[1] = ntohl(swapx1.aux_[0]);
 
878
                                swapx2.aux_[0] = ntohl(swapx1.aux_[1]);
 
879
 
 
880
                                swapy2.aux_[1] = ntohl(swapy1.aux_[0]);
 
881
                                swapy2.aux_[0] = ntohl(swapy1.aux_[1]);
 
882
 
 
883
                                l.add(TeCoord2D(swapx2.dWord_, swapy2.dWord_));
 
884
                        }
 
885
                        
 
886
                }
 
887
                else
 
888
                {
 
889
                        // big-endian!
 
890
                        for(unsigned int i = 0; i < numPts ; ++i)
 
891
                                l.add(TeCoord2D(pts[i].x, pts[i].y));
 
892
                        
 
893
                }
 
894
        }
 
895
        else    //TeTEXTCURSOR
 
896
                l = PgGeomPolygon2Te(polygon);
 
897
}
 
898
 
 
899
char* TePGRecordset::getWKBHeader(char* v, unsigned char &byteOrder, unsigned int &wkbType, unsigned int &numGeometries) const
 
900
{
 
901
        const int byteOrderPlusGeomType = sizeof(unsigned char) + sizeof(unsigned int); 
 
902
 
 
903
        if(cursorDataType_ == TeTEXTCURSOR)
 
904
        {
 
905
                unsigned char header [byteOrderPlusGeomType];
 
906
 
 
907
                for (int t = 0; t < byteOrderPlusGeomType; ++t)
 
908
                {
 
909
                        header[t] =(unsigned char) parse_hex(v) ;
 
910
                        v += 2;
 
911
                }
 
912
 
 
913
                memcpy(&byteOrder, header, sizeof(unsigned char));              
 
914
                memcpy(&wkbType, header + sizeof(unsigned char), sizeof(unsigned int));
 
915
        }
 
916
        else
 
917
        {
 
918
                memcpy(&byteOrder, v, sizeof(unsigned char));           
 
919
                memcpy(&wkbType, v + sizeof(unsigned char), sizeof(unsigned int));
 
920
 
 
921
                v += byteOrderPlusGeomType;
 
922
        }       
 
923
        
 
924
 
 
925
        // 0 = Big Endian (wkbXDR) e 1 = Little Endian (wkbNDR)
 
926
        if((byteOrder == 0) && isLittleEndian_)
 
927
        {
 
928
                wkbType = ntohl(wkbType);
 
929
        }
 
930
        else if((byteOrder == 1) && !isLittleEndian_)
 
931
        {
 
932
                        wkbType = htonl(wkbType);
 
933
        }       
 
934
 
 
935
        numGeometries = 0;
 
936
 
 
937
        if(wkbType > 1 && wkbType <= 7)
 
938
        {
 
939
                if(cursorDataType_ == TeTEXTCURSOR)
 
940
                {
 
941
                        unsigned char qtd[sizeof(unsigned int)];
 
942
 
 
943
                        for(unsigned int t = 0; t < sizeof(unsigned int); ++t)
 
944
                        {
 
945
                                qtd[t] = (unsigned char)parse_hex(v);
 
946
                                v += 2;
 
947
                        }
 
948
 
 
949
                        memcpy(&numGeometries, qtd, sizeof(unsigned int));
 
950
                }
 
951
                else
 
952
                {
 
953
                        memcpy(&numGeometries, v, sizeof(unsigned int));
 
954
                        v += sizeof(unsigned int);
 
955
                }
 
956
 
 
957
                // 0 = Big Endian (wkbXDR) e 1 = Little Endian (wkbNDR)
 
958
                if((byteOrder == 0) && isLittleEndian_)
 
959
                {
 
960
                        numGeometries = ntohl(numGeometries);   
 
961
                }
 
962
                else if((byteOrder == 1) && !isLittleEndian_)
 
963
                {
 
964
                        numGeometries = htonl(numGeometries);
 
965
                }
 
966
        }
 
967
 
 
968
        return v;       
 
969
}
 
970
 
 
971
char* TePGRecordset::getWKBPoint(char* v, TeCoord2D& c) const
 
972
{
 
973
        unsigned char byteOrder;
 
974
        unsigned int wkbType;
 
975
        unsigned int numGeometries;
 
976
 
 
977
        v = getWKBHeader(v, byteOrder, wkbType, numGeometries);
 
978
        
 
979
        if(wkbType != 1)
 
980
                throw logic_error("Binary data doesn't supported!");
 
981
                
 
982
 
 
983
        union
 
984
        {
 
985
                double dWord_;
 
986
                unsigned int aux_[2];
 
987
        } swapx1, swapy1;
 
988
 
 
989
        if(cursorDataType_ == TeTEXTCURSOR)
 
990
        {
 
991
 
 
992
                const int double2Size = 2 * sizeof(double);
 
993
                unsigned char data[double2Size];
 
994
                
 
995
                for(int t = 0; t < double2Size; ++t) // len/2
 
996
                {
 
997
                        data[t] = (unsigned char)parse_hex(v);
 
998
                        v += 2;
 
999
                }
 
1000
                
 
1001
 
 
1002
                memcpy(&swapx1.dWord_, data , sizeof(double));
 
1003
                memcpy(&swapy1.dWord_, data + sizeof(double), sizeof(double));
 
1004
        }
 
1005
        else
 
1006
        {
 
1007
                memcpy(&swapx1.dWord_, v , sizeof(double));
 
1008
                memcpy(&swapy1.dWord_, v + sizeof(double), sizeof(double));
 
1009
 
 
1010
                v += (sizeof(double) + sizeof(double)); // x + y
 
1011
        }
 
1012
 
 
1013
        // 0 = Big Endian (wkbXDR)
 
1014
        if((byteOrder == 0) && isLittleEndian_)
 
1015
        {
 
1016
                union
 
1017
                {
 
1018
                        double dWord_;
 
1019
                        unsigned int aux_[2];
 
1020
                } swapx2, swapy2;
 
1021
 
 
1022
                swapx2.aux_[1] = ntohl(swapx1.aux_[0]);
 
1023
                swapx2.aux_[0] = ntohl(swapx1.aux_[1]);
 
1024
 
 
1025
                swapy2.aux_[1] = ntohl(swapy1.aux_[0]);
 
1026
                swapy2.aux_[0] = ntohl(swapy1.aux_[1]); 
 
1027
                
 
1028
                c.x(swapx2.dWord_);
 
1029
                c.y(swapy2.dWord_);
 
1030
 
 
1031
                return v;
 
1032
        }
 
1033
        else if((byteOrder == 1) && !isLittleEndian_)
 
1034
        {
 
1035
                union
 
1036
                {
 
1037
                        double dWord_;
 
1038
                        unsigned int aux_[2];
 
1039
                } swapx2, swapy2;
 
1040
 
 
1041
                swapx2.aux_[1] = htonl(swapx1.aux_[0]);
 
1042
                swapx2.aux_[0] = htonl(swapx1.aux_[1]);
 
1043
 
 
1044
                swapy2.aux_[1] = htonl(swapy1.aux_[0]);
 
1045
                swapy2.aux_[0] = htonl(swapy1.aux_[1]);
 
1046
                
 
1047
                c.x(swapx2.dWord_);
 
1048
                c.y(swapy2.dWord_);
 
1049
 
 
1050
                return v;
 
1051
 
 
1052
        }
 
1053
 
 
1054
        c.x(swapx1.dWord_);
 
1055
        c.y(swapy1.dWord_);
 
1056
 
 
1057
        return v;
 
1058
}
 
1059
 
 
1060
char* TePGRecordset::getWKBLinearRing(char* v, int byteOrder, TeLine2D &line) const
 
1061
{
 
1062
        unsigned int numPoints;
 
1063
        
 
1064
        const int size2Double = sizeof(double) + sizeof(double); // x + y
 
1065
 
 
1066
        if(cursorDataType_ == TeTEXTCURSOR)
 
1067
        {
 
1068
                unsigned char data[size2Double];
 
1069
 
 
1070
                for(unsigned int n = 0; n < sizeof(unsigned int); ++n)
 
1071
                {
 
1072
                        data[n] = (unsigned char)parse_hex(v);
 
1073
                        v += 2;
 
1074
                }
 
1075
 
 
1076
                memcpy(&numPoints, data , sizeof(unsigned int));
 
1077
        }
 
1078
        else
 
1079
        {
 
1080
                memcpy(&numPoints, v , sizeof(unsigned int));
 
1081
                v += sizeof(unsigned int);
 
1082
        }
 
1083
 
 
1084
        // 0 = Big Endian (wkbXDR) e 1 = Little Endian (wkbNDR)
 
1085
        if((byteOrder == 0) && isLittleEndian_)
 
1086
        {
 
1087
                numPoints = ntohl(numPoints);   
 
1088
        }
 
1089
        else if((byteOrder == 1) && !isLittleEndian_)
 
1090
        {
 
1091
                numPoints = htonl(numPoints);
 
1092
        }
 
1093
 
 
1094
        for(unsigned int i = 0; i < numPoints; ++i)
 
1095
        {
 
1096
                union
 
1097
                {
 
1098
                        double dWord_;
 
1099
                        unsigned int aux_[2];
 
1100
                } swapx1, swapy1;
 
1101
 
 
1102
                if(cursorDataType_ == TeTEXTCURSOR)
 
1103
                {
 
1104
                        unsigned char data[size2Double];
 
1105
 
 
1106
                        for(int t = 0; t < size2Double; ++t) // len/2
 
1107
                        {
 
1108
                                data[t] = (unsigned char)parse_hex(v);
 
1109
                                v += 2;
 
1110
                        }       
 
1111
 
 
1112
                        memcpy(&swapx1.dWord_, data , sizeof(double));
 
1113
                        memcpy(&swapy1.dWord_, data + sizeof(double), sizeof(double));
 
1114
                }
 
1115
                else
 
1116
                {
 
1117
                        memcpy(&swapx1.dWord_, v , sizeof(double));
 
1118
                        memcpy(&swapy1.dWord_, v + sizeof(double), sizeof(double));
 
1119
                        v += size2Double;
 
1120
                }
 
1121
 
 
1122
                // 0 = Big Endian (wkbXDR)
 
1123
                if((byteOrder == 0) && isLittleEndian_)
 
1124
                {
 
1125
                        union
 
1126
                        {
 
1127
                                double dWord_;
 
1128
                                unsigned int aux_[2];
 
1129
                        } swapx2, swapy2;
 
1130
 
 
1131
                        swapx2.aux_[1] = ntohl(swapx1.aux_[0]);
 
1132
                        swapx2.aux_[0] = ntohl(swapx1.aux_[1]);
 
1133
 
 
1134
                        swapy2.aux_[1] = ntohl(swapy1.aux_[0]);
 
1135
                        swapy2.aux_[0] = ntohl(swapy1.aux_[1]); 
 
1136
                        
 
1137
                        line.add(TeCoord2D(swapx2.dWord_, swapy2.dWord_));                      
 
1138
                }
 
1139
                else if((byteOrder == 1) && !isLittleEndian_)   //1 = Little Endian (wkbNDR)
 
1140
                {
 
1141
                        union
 
1142
                        {
 
1143
                                double dWord_;
 
1144
                                unsigned int aux_[2];
 
1145
                        } swapx2, swapy2;
 
1146
 
 
1147
                        swapx2.aux_[1] = htonl(swapx1.aux_[0]);
 
1148
                        swapx2.aux_[0] = htonl(swapx1.aux_[1]);
 
1149
 
 
1150
                        swapy2.aux_[1] = htonl(swapy1.aux_[0]);
 
1151
                        swapy2.aux_[0] = htonl(swapy1.aux_[1]);
 
1152
                        
 
1153
                        line.add(TeCoord2D(swapx2.dWord_, swapy2.dWord_));
 
1154
                }
 
1155
                else
 
1156
                {
 
1157
                        line.add(TeCoord2D(swapx1.dWord_, swapy1.dWord_));
 
1158
                }
 
1159
        }
 
1160
 
 
1161
        return v;
 
1162
 
 
1163
}
 
1164
 
 
1165
char* TePGRecordset::getWKBLine(char* v, TeLine2D& l) const
 
1166
{
 
1167
        unsigned char byteOrder;
 
1168
        unsigned int wkbType;
 
1169
        unsigned int numPoints;
 
1170
 
 
1171
        v = getWKBHeader(v, byteOrder, wkbType, numPoints);
 
1172
        
 
1173
        if(wkbType != 2)
 
1174
                throw logic_error("Binary data doesn't supported!");
 
1175
 
 
1176
        if(cursorDataType_ == TeTEXTCURSOR)
 
1177
        {
 
1178
                // Volta duas vezes o n�mero de bytes do n�mero de geometrias lidos ao chamar getWKBHeader
 
1179
                v = getWKBLinearRing(v - (sizeof(unsigned int) + sizeof(unsigned int)), byteOrder, l);
 
1180
        }
 
1181
        else
 
1182
        {
 
1183
                // Volta o n�mero de bytes do n�mero de geometrias lidos ao chamar getWKBHeader
 
1184
                v = getWKBLinearRing(v - sizeof(unsigned int), byteOrder, l);
 
1185
        }
 
1186
 
 
1187
        return v;
 
1188
 
 
1189
}
 
1190
 
 
1191
char* TePGRecordset::getWKBPolygon(char* v, TePolygon& p) const
 
1192
{
 
1193
        unsigned char byteOrder;
 
1194
        unsigned int wkbType;
 
1195
        unsigned int numRings;
 
1196
 
 
1197
        v = getWKBHeader(v, byteOrder, wkbType, numRings);
 
1198
        
 
1199
        if(wkbType != 3)
 
1200
                throw logic_error("Binary data doesn't supported!");
 
1201
 
 
1202
        for(unsigned int i = 0; i < numRings; ++i)
 
1203
        {
 
1204
                TeLine2D line;
 
1205
                v = getWKBLinearRing(v, byteOrder, line);
 
1206
                p.add(line);
 
1207
        }
 
1208
 
 
1209
        return v;
 
1210
 
 
1211
}
 
1212
 
 
1213
char* TePGRecordset::getWKBMultiPoint(char* v, TePointSet &ps) const
 
1214
{
 
1215
        unsigned char byteOrder; 
 
1216
        unsigned int wkbType; 
 
1217
        unsigned int num_wkbPoints; 
 
1218
 
 
1219
        v = getWKBHeader(v, byteOrder, wkbType, num_wkbPoints);
 
1220
 
 
1221
        if(wkbType != 4)
 
1222
                throw logic_error("Binary data doesn't supported!");
 
1223
 
 
1224
        for(unsigned int i = 0; i < num_wkbPoints; ++i)
 
1225
        {
 
1226
                TeCoord2D coord;
 
1227
                v = getWKBPoint(v, coord);
 
1228
                ps.add(coord);
 
1229
        }
 
1230
 
 
1231
        return v;
 
1232
}
 
1233
 
 
1234
char* TePGRecordset::getWKBMultiLine(char* v, TeLineSet &ls) const
 
1235
{
 
1236
        unsigned char byteOrder; 
 
1237
        unsigned int wkbType; 
 
1238
        unsigned int num_wkbLineStrings; 
 
1239
 
 
1240
        v = getWKBHeader(v, byteOrder, wkbType, num_wkbLineStrings);
 
1241
 
 
1242
        if(wkbType != 5)
 
1243
                throw logic_error("Binary data doesn't supported!");
 
1244
 
 
1245
        for(unsigned int i = 0; i < num_wkbLineStrings; ++i)
 
1246
        {
 
1247
                TeLine2D line;
 
1248
                v = getWKBLine(v, line);
 
1249
                ls.add(line);
 
1250
        }
 
1251
 
 
1252
        return v;
 
1253
}
 
1254
 
 
1255
char* TePGRecordset::getWKBMultiPolygon(char* v, TePolygonSet &ps) const
 
1256
{
 
1257
        unsigned char byteOrder;
 
1258
        unsigned int wkbType;
 
1259
        unsigned int num_wkbPolygons;
 
1260
 
 
1261
        v = getWKBHeader(v, byteOrder, wkbType, num_wkbPolygons);
 
1262
 
 
1263
        if(wkbType != 6)
 
1264
                throw logic_error("Binary data doesn't supported!");
 
1265
 
 
1266
        for(unsigned int i = 0; i < num_wkbPolygons; ++i)
 
1267
        {
 
1268
                TePolygon poly;
 
1269
                v = getWKBPolygon(v, poly);
 
1270
                ps.add(poly);
 
1271
        }
 
1272
 
 
1273
        return v;
 
1274
}
 
1275
 
 
1276
void TePGRecordset::getWKBGeomColl(char* v, TeMultiGeometry &mg) const
 
1277
{
 
1278
        unsigned char byteOrder; 
 
1279
        unsigned int wkbType; 
 
1280
        unsigned int num_wkbGeometries;
 
1281
 
 
1282
        v = getWKBHeader(v, byteOrder, wkbType, num_wkbGeometries);
 
1283
 
 
1284
        if(wkbType != 7)
 
1285
                throw logic_error("Binary data doesn't supported!");
 
1286
 
 
1287
        for(unsigned int i = 0; i < num_wkbGeometries; ++i)
 
1288
        {
 
1289
                unsigned int geomType;
 
1290
                unsigned char geomByteOrder;
 
1291
                unsigned int num_geometries;
 
1292
 
 
1293
                getWKBHeader(v, geomByteOrder, geomType, num_geometries);
 
1294
 
 
1295
                if(geomType == 1)
 
1296
                {
 
1297
                        TeCoord2D coord;
 
1298
 
 
1299
                        v = getWKBPoint(v, coord);
 
1300
 
 
1301
                        mg.addGeometry(coord);
 
1302
                }
 
1303
                else if(geomType == 2)
 
1304
                {
 
1305
                        TeLine2D line;
 
1306
 
 
1307
                        v = getWKBLine(v, line);
 
1308
 
 
1309
                        mg.addGeometry(line);
 
1310
                }
 
1311
                else if(geomType == 3)
 
1312
                {
 
1313
                        TePolygon poly;
 
1314
 
 
1315
                        v = getWKBPolygon(v, poly);
 
1316
 
 
1317
                        mg.addGeometry(poly);
 
1318
                }
 
1319
                else if(geomType == 4)
 
1320
                {
 
1321
                        TePointSet pointSet;
 
1322
 
 
1323
                        v = getWKBMultiPoint(v, pointSet);
 
1324
 
 
1325
                        for(unsigned int a = 0; a < pointSet.size(); ++a)
 
1326
                        {
 
1327
                                TePoint point = pointSet[a];
 
1328
                                mg.addGeometry(point);
 
1329
                        }
 
1330
                }
 
1331
                else if(geomType == 5)
 
1332
                {
 
1333
                        TeLineSet lineSet;
 
1334
 
 
1335
                        v = getWKBMultiLine(v, lineSet);
 
1336
 
 
1337
                        for(unsigned int a = 0; a < lineSet.size(); ++a)
 
1338
                        {
 
1339
                                TeLine2D coord = lineSet[a];
 
1340
 
 
1341
                                mg.addGeometry(coord);
 
1342
                        }
 
1343
                }
 
1344
                else if(geomType == 6)
 
1345
                {
 
1346
                        TePolygonSet polygonSet;
 
1347
                        
 
1348
                        v = getWKBMultiPolygon(v, polygonSet);
 
1349
                        
 
1350
                        for(unsigned int a = 0; a < polygonSet.size(); ++a)
 
1351
                        {
 
1352
                                TePolygon poly = polygonSet[a];
 
1353
 
 
1354
                                mg.addGeometry(poly);
 
1355
                        }
 
1356
                }
 
1357
                else
 
1358
                {
 
1359
                        throw logic_error("The data couldn't be decoded as a valid WKB geometry!");
 
1360
                }
 
1361
        }
 
1362
 
 
1363
}
 
1364
 
 
1365
 
 
1366
void TePGRecordset::getPGISPoint(const int& field_num, TePoint& p) const
 
1367
{
 
1368
        TeCoord2D c;
 
1369
        getWKBPoint(value(field_num), c);
 
1370
        p.add(c);
 
1371
}
 
1372
 
 
1373
 
 
1374
void TePGRecordset::getPGISLine(const int& field_num, TeLine2D& l) const
 
1375
{
 
1376
        getWKBLine(value(field_num), l);                
 
1377
}
 
1378
 
 
1379
 
 
1380
void TePGRecordset::getPGISPolygon(const int& field_num, TePolygon& p) const
 
1381
{
 
1382
        getWKBPolygon(value(field_num), p);             
 
1383
}
 
1384
 
 
1385
 
 
1386
void TePGRecordset::getPGISMultiPoint(const int& field_num, TePointSet& ps) const
 
1387
{
 
1388
        getWKBMultiPoint(value(field_num), ps);         
 
1389
}
 
1390
 
 
1391
 
 
1392
void TePGRecordset::getPGISMultiLine(const int& field_num, TeLineSet& ls) const
 
1393
{
 
1394
        getWKBMultiLine(value(field_num), ls);          
 
1395
}
 
1396
 
 
1397
 
 
1398
void TePGRecordset::getPGISMultiPolygon(const int& field_num, TePolygonSet& ps) const
 
1399
{
 
1400
        getWKBMultiPolygon(value(field_num), ps);       
 
1401
}
 
1402
 
 
1403
 
 
1404
void TePGRecordset::getPGISGeomColl(const int& field_num, TeMultiGeometry& m) const
 
1405
{
 
1406
        getWKBGeomColl(value(field_num), m);
 
1407
}
 
1408
 
 
1409
 
 
1410
 
 
1411
char* TePGRecordset::getData(const int& field_num)
 
1412
{
 
1413
        data_ = "";
 
1414
 
 
1415
        if(cursorDataType_ == TeTEXTCURSOR)
 
1416
                return value(field_num);
 
1417
        else
 
1418
        {
 
1419
                // chamar o conversor de tipo de dado de bin�rio p/ string p/ cada tipo!
 
1420
                switch(fieldType(field_num))
 
1421
                {
 
1422
                        case PG_BOOL_TYPE                       :
 
1423
                        case PG_BYTEA_TYPE                      :
 
1424
                        case PG_CHAR_TYPE                       :
 
1425
                        case PG_INT8_TYPE                       :
 
1426
                        case PG_INT2_TYPE                       : break;
 
1427
 
 
1428
                        case PG_INT4_TYPE                       : data_ = Te2String(getInt(field_num));
 
1429
                                                                                  break;
 
1430
 
 
1431
                        case PG_TEXT_TYPE                       :
 
1432
                        case PG_OID_TYPE                        :
 
1433
                        case PG_POINT_TYPE                      :
 
1434
                        case PG_LSEG_TYPE                       :
 
1435
                        case PG_PATH_TYPE                       :
 
1436
                        case PG_BOX_TYPE                        :
 
1437
                        case PG_POLYGON_TYPE            :
 
1438
                        case PG_LINE_TYPE                       :
 
1439
                        case PG_PG_FLOAT4_TYPE          : break;
 
1440
 
 
1441
                        case PG_FLOAT8_TYPE                     : data_ = Te2String(getDouble(field_num));
 
1442
                                                                                  break;
 
1443
 
 
1444
                        case PG_CIRCLE_TYPE                     :
 
1445
                        case PG_MONEY_TYPE                      :
 
1446
                        case PG_BPCHAR_TYPE                     :
 
1447
                        case PG_VARCHAR_TYPE            :
 
1448
                        case PG_DATE_TYPE                       :
 
1449
                        case PG_TIME_TYPE                       :
 
1450
                        case PG_TIMESTAMP_TYPE          :
 
1451
                        case PG_TIMESTAMPTZ_TYPE        :
 
1452
                        case PG_INTERVAL_TYPE           :
 
1453
                        case PG_TIMETZ_TYPE                     :
 
1454
                        case PG_BIT_TYPE                        :
 
1455
                        case PG_VARBIT_TYPE                     :
 
1456
                        case PG_NUMERIC_TYPE            :
 
1457
                        default                                         : break;
 
1458
                }
 
1459
                
 
1460
                return (char*)data_.c_str();
 
1461
        }
 
1462
}
 
1463
 
 
1464
int TePGRecordset::fieldSize(const int& field_num)
 
1465
{
 
1466
 Oid field_t = this->fieldType(field_num);
 
1467
 Oid field_m = PQfmod(pg_recordset_, field_num);
 
1468
 PGresult *result_temp;
 
1469
 char str_int[5];   //integer part if DECIMAL(p,s) or NUMERIC(p,s)
 
1470
 //int size = -1;
 
1471
 int size = 0;
 
1472
 char str_field_t[50];
 
1473
 char str_field_m[50];
 
1474
 sprintf(str_field_t,"%d", field_t);
 
1475
 sprintf(str_field_m,"%d", field_m);
 
1476
 string str_qry = "SELECT format_type(";
 
1477
        str_qry += str_field_t;
 
1478
        str_qry += ",";
 
1479
        str_qry += str_field_m;
 
1480
        str_qry += ")";
 
1481
 switch(field_t)
 
1482
       {
 
1483
        case 1043:   //VARCHAR(s) or CHARACTER VARYING(s)
 
1484
        case 1700:   //NUMERIC(p,s) or DECIMAL(p,s)
 
1485
                     result_temp = PQexec(conn_->c_ptr(), str_qry.c_str());
 
1486
                     if(PQresultStatus(result_temp) == PGRES_TUPLES_OK)
 
1487
                       {
 
1488
                        char *lin = PQgetvalue(result_temp, 0, 0);  //Don't free lin because the return of PQgetvalue is in the struct PGResult
 
1489
                        int i = 0;
 
1490
                        while(*lin != '\0' && *lin != ',')
 
1491
                             {
 
1492
                              if(*lin >= '0' && *lin <= '9' && i < 4)
 
1493
                                {
 
1494
                                 str_int[i] = *lin;
 
1495
                                 i++;
 
1496
                                }
 
1497
                              lin++;
 
1498
                             }
 
1499
                        str_int[i]='\0';
 
1500
                        size = atoi(str_int);
 
1501
                       }
 
1502
                     PQclear(result_temp);
 
1503
                     break;
 
1504
        default:     //The size of fixed size or for other variable size -1
 
1505
                     return PQfsize(pg_recordset_, field_num);
 
1506
       }
 
1507
 result_temp = 0;
 
1508
 return size;
 
1509
}
 
1510
 
 
1511
int TePGRecordset::fieldSizeFractionaryPart(const int& field_num)
 
1512
{
 
1513
 Oid field_t = this->fieldType(field_num);
 
1514
 Oid field_m = PQfmod(pg_recordset_, field_num);
 
1515
 PGresult *result_temp;
 
1516
 char str_frac[5];   //fractionary part if DECIMAL(p,s) or NUMERIC(p,s)
 
1517
 //int size = -1;
 
1518
 int size = 0;
 
1519
 char str_field_t[50];
 
1520
 char str_field_m[50];
 
1521
 sprintf(str_field_t,"%d", field_t);
 
1522
 sprintf(str_field_m,"%d", field_m);
 
1523
 string str_qry = "SELECT format_type(";
 
1524
        str_qry += str_field_t;
 
1525
        str_qry += ",";
 
1526
        str_qry += str_field_m;
 
1527
        str_qry += ")";
 
1528
 switch(field_t)
 
1529
       {
 
1530
        case 1700:   //NUMERIC(p,s) or DECIMAL(p,s)
 
1531
                     result_temp = PQexec(conn_->c_ptr(), str_qry.c_str());
 
1532
                     if(PQresultStatus(result_temp) == PGRES_TUPLES_OK)
 
1533
                       {
 
1534
                        char *lin = PQgetvalue(result_temp, 0, 0);  //Don't free lin because the return of PQgetvalue is in the struct PGResult
 
1535
                        int i = 0;
 
1536
                        while(*lin != '\0' && *lin != ',')
 
1537
                             {
 
1538
                              lin++;
 
1539
                             }
 
1540
                        if(*lin == ',')
 
1541
                          {
 
1542
                           lin++;
 
1543
                          }
 
1544
                        while(*lin != '\0')
 
1545
                             {
 
1546
                              if(*lin >= '0' && *lin <= '9' && i < 4)
 
1547
                                {
 
1548
                                 str_frac[i] = *lin;
 
1549
                                 i++;
 
1550
                                }
 
1551
                              lin++;
 
1552
                             }
 
1553
                        str_frac[i]='\0';
 
1554
                        size = atoi(str_frac);
 
1555
                       }
 
1556
                     PQclear(result_temp);
 
1557
                     break;
 
1558
        default:     //Others doesn't have a fractionary part
 
1559
                     break;
 
1560
 
 
1561
       }
 
1562
 result_temp = 0;
 
1563
 return size;
 
1564
}
 
1565
 
 
1566
void TePGRecordset::freeRecordSet()
 
1567
{
 
1568
        if(pg_recordset_)
 
1569
                PQclear(pg_recordset_);
 
1570
 
 
1571
 
 
1572
        pg_recordset_ = 0;
 
1573
        int_index_current_ = -1;
 
1574
        int_eof_ = -1;
 
1575
        return;
 
1576
}
 
1577
 
 
1578
 
 
1579
 
 
1580
 
 
1581