ConnectedDataSet.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2008 National Institute For Space Research (INPE) - Brazil.
2 
3  This file is part of the TerraLib - a Framework for building GIS enabled applications.
4 
5  TerraLib is free software: you can redistribute it and/or modify
6  it under the terms of the GNU Lesser General Public License as published by
7  the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  TerraLib is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public License
16  along with TerraLib. See COPYING. If not, write to
17  TerraLib Team at <terralib-team@terralib.org>.
18  */
19 
20 /*!
21  \file terralib/postgis/ConnectedDataSet.cpp
22 
23  \brief Implementation of a connected dataset for the PostGIS driver.
24 */
25 
26 // TerraLib
27 #include "../Defines.h"
28 #include "../common/ByteSwapUtils.h"
29 #include "../common/Globals.h"
30 #include "../common/StringUtils.h"
31 #include "../core/translator/Translator.h"
32 #include "../dataaccess/dataset/DataSetType.h"
33 #include "../datatype/Array.h"
34 #include "../datatype/ByteArray.h"
35 #include "../datatype/DateTime.h"
36 #include "../datatype/SimpleData.h"
37 #include "../geometry/Geometry.h"
38 #include "Connection.h"
39 #include "ConnectionPool.h"
40 #include "ConnectedDataSet.h"
41 #include "DataSource.h"
42 #include "EWKBReader.h"
43 #include "Exception.h"
44 #include "ScopedConnection.h"
45 #include "Utils.h"
46 
47 // STL
48 #include <cassert>
49 #include <memory>
50 
51 // Boost
52 #include <boost/dynamic_bitset.hpp>
53 
54 // libpq
55 #include <libpq-fe.h>
56 
57 namespace te
58 {
59  namespace pgis
60  {
61  /*!
62  \brief It retrieves information from an unidimensional array.
63 
64  Requirements on types:
65  <ul>
66  <li>T: the type of basic elements of the array.</li>
67  <li>ALIGN: the size in bytes of pointer alignment for the type T.</li>
68  </ul>
69 
70  \param i The row.
71  \param j The column.
72  \param result The result to extract the array.
73  \param a The output vector.
74 
75  \warning Don't call this method for multidimensional arrays!
76  */
77  template<class T, class ALIGN> inline void GetArray(int i, int j, PGresult* result, std::vector<T>& a)
78  {
79  char* value = PQgetvalue(result, i, j);
80 
81  int ndim = *(reinterpret_cast<int*>(value));
82  value += sizeof(int);
83 
84  int dataoffset = *(reinterpret_cast<int*>(value));
85  value += sizeof(int);
86 
87  unsigned int elemtype = *(reinterpret_cast<unsigned int*>(value));
88  value += sizeof(unsigned int);
89 
90  int dimension = *(reinterpret_cast<int*>(value));
91  value += sizeof(int);
92 
93  int lowerbnds = *(reinterpret_cast<int*>(value));
94  value += (2 * sizeof(int)); //jump null-bitmap field
95 
97  {
99  te::common::SwapBytes(dataoffset);
100  te::common::SwapBytes(elemtype);
101  te::common::SwapBytes(dimension);
102  te::common::SwapBytes(lowerbnds);
103 
104  a.reserve(static_cast<size_t>(dimension));
105 
106  for(int k = 0; k < dimension; ++k)
107  {
108  T v = *(reinterpret_cast<T*>(value));
110  a.push_back(v);
111  value += sizeof(ALIGN);
112  }
113  }
114  else
115  {
116  a.reserve(static_cast<size_t>(dimension));
117 
118  for(int k = 0; k < dimension; ++k)
119  {
120  T v = *(reinterpret_cast<T*>(value));
121  a.push_back(v);
122  value += sizeof(ALIGN);
123  }
124  }
125  }
126 
127  } // end namespace pgis
128 } // end namespace te
129 
131  DataSource* dataSource,
132  const int& connectionId,
133  const std::string& id_cursor,
134  const int& size,
135  const std::vector<int>& ptypes,
136  bool timeIsInteger) :
137  m_iFetch(-1),
138  m_iLayer(-1),
139  m_size(size),
140  m_result(result),
141  m_ds(dataSource),
142  m_connectionId(connectionId),
143  m_idcursor(id_cursor),
144  m_ptypes(ptypes),
145  m_mbr(nullptr),
146  m_timeIsInteger(timeIsInteger)
147 {
148  m_fetchSize = PQntuples(m_result);
149 }
150 
152 {
153  ScopedConnection scopedConnection(m_ds->getConnPool(), m_connectionId);
154 
155  scopedConnection->execute("CLOSE " + m_idcursor + ";");
156 
157  PQclear(m_result);
158 }
159 
161 {
162  return te::common::RANDOM;
163 }
164 
166 {
167  return te::common::RAccess;
168 }
169 
171 {
172  return static_cast<size_t>(PQnfields(m_result));
173 }
174 
176 {
177  return m_ptypes[i];
178 }
179 
180 std::string te::pgis::ConnectedDataSet::getPropertyName(std::size_t i) const
181 {
182  return PQfname(m_result, static_cast<int>(i));
183 }
184 
185 std::string te::pgis::ConnectedDataSet::getDatasetNameOfProperty(std::size_t/* i*/) const
186 {
187  throw Exception(TE_TR("Not implemented yet!"));
188 }
189 
191 {
192  return (m_size == 0);
193 }
194 
196 {
197  return true;
198 }
199 
201 {
202  return static_cast<std::size_t>(m_size);
203 }
204 
205 std::unique_ptr<te::gm::Envelope> te::pgis::ConnectedDataSet::getExtent(std::size_t i)
206 {
207  if(!m_mbr)
208  {
210  throw Exception(TE_TR("This driver only supports the getExtent method over a geometry column!"));
211 
212  m_mbr = new te::gm::Envelope;
213 
214  m_iFetch = -1;
215  while(moveNext())
216  {
217  std::unique_ptr<te::gm::Geometry> geom(getGeometry(i));
218  m_mbr->Union(*(geom->getMBR()));
219  }
220  }
221 
222  m_iFetch = -1;
223 
225 
226  return std::unique_ptr<te::gm::Envelope>(mbr);
227 }
228 
230 {
231  ScopedConnection scopedConnection(m_ds->getConnPool(), m_connectionId);
232 
233  ++m_iLayer;
234  ++m_iFetch;
235 
236  if(m_iFetch >= m_fetchSize && m_iLayer < m_size)
237  {
238  std::string fetch("FETCH FORWARD ");
239  fetch += boost::lexical_cast<std::string>(m_fetchSize);
240  fetch += " FROM ";
241  fetch += m_idcursor;
242 
243  m_iFetch = 0;
244 
245  PQclear(m_result);
246  m_result = scopedConnection->query(fetch);
247  m_fetchSize = PQntuples(m_result);
248 
249  if(m_fetchSize == 0)
250  return false;
251  }
252 
253  return m_iLayer < m_size;
254 }
255 
257 {
258  ScopedConnection scopedConnection(m_ds->getConnPool(), m_connectionId);
259 
260  --m_iLayer;
261  ++m_iFetch;
262 
263  if(m_iFetch >= m_fetchSize && m_iLayer > -1)
264  {
265  std::string fetch("FETCH BACKWARD ");
266  fetch += boost::lexical_cast<std::string>(m_fetchSize);
267  fetch += " FROM ";
268  fetch += m_idcursor;
269 
270  m_iFetch = 0;
271 
272  PQclear(m_result);
273  m_result = scopedConnection->query(fetch);
274  m_fetchSize = PQntuples(m_result);
275 
276  if(m_fetchSize == 0)
277  return false;
278  }
279 
280  return (m_iLayer > -1);
281 }
282 
284 {
285  // Gets the fetch first in -1 index.
286  moveBeforeFirst();
287 
288  // Move the index to the first position.
289  moveNext();
290 
291  return m_fetchSize != 0;
292 }
293 
295 {
296  ScopedConnection scopedConnection(m_ds->getConnPool(), m_connectionId);
297 
298  std::string fetch("FETCH LAST ");
299  fetch += "FROM ";
300  fetch += m_idcursor;
301 
302  PQclear(m_result);
303  m_result = scopedConnection->query(fetch);
304  m_fetchSize = PQntuples(m_result);
305 
306  m_iLayer = m_size - 1;
307  m_iFetch = m_fetchSize - 1;
308 
309  return m_fetchSize != 0;
310 }
311 
313 {
314  ScopedConnection scopedConnection(m_ds->getConnPool(), m_connectionId);
315 
316  std::string fetch("FETCH FIRST ");
317  fetch += "FROM ";
318  fetch += m_idcursor;
319 
320  m_iLayer = -1;
321  m_iFetch = -1;
322 
323  PQclear(m_result);
324  m_result = scopedConnection->query(fetch);
325  m_fetchSize = PQntuples(m_result);
326 
327  return m_fetchSize != 0;
328 }
329 
331 {
332  if(static_cast<int>(i) >= m_size)
333  return false;
334 
335  ScopedConnection scopedConnection(m_ds->getConnPool(), m_connectionId);
336 
337  std::string fetchRelative("FETCH ABSOLUTE ");
338  fetchRelative += boost::lexical_cast<std::string>(i+1);
339  fetchRelative += " FROM ";
340  fetchRelative += m_idcursor;
341 
342  PQclear(m_result);
343  m_result = scopedConnection->query(fetchRelative);
344  m_fetchSize = PQntuples(m_result);
345 
346  m_iLayer = static_cast<int>(i);
347  m_iFetch = m_fetchSize - 1;
348 
349  return (m_iLayer < m_size);
350 }
351 
353 {
354  return m_iLayer == 0;
355 }
356 
358 {
359  return m_iLayer < 0;
360 }
361 
363 {
364  return m_iLayer == (m_size - 1);
365 }
366 
368 {
369  return m_iLayer >= m_size;
370 }
371 
373 {
374  return m_iLayer > -1 && m_iLayer < m_size;
375 }
376 
377 char te::pgis::ConnectedDataSet::getChar(std::size_t i) const
378 {
379  char cval = *(PQgetvalue(m_result, m_iFetch, static_cast<int>(i)));
380  return cval;
381 }
382 
383 unsigned char te::pgis::ConnectedDataSet::getUChar(std::size_t i) const
384 {
385  unsigned char cval = *reinterpret_cast<unsigned char*>((PQgetvalue(m_result, m_iFetch, static_cast<int>(i))));
386  return cval;
387 }
388 
389 boost::int16_t te::pgis::ConnectedDataSet::getInt16(std::size_t i) const
390 {
391  short int ival = *(reinterpret_cast<short int*>(PQgetvalue(m_result, m_iFetch, static_cast<int>(i))));
392 
393 #if TE_MACHINE_BYTE_ORDER == TE_NDR
394  te::common::SwapBytes(ival);
395 #endif
396 
397  return static_cast<boost::int16_t>(ival);
398 }
399 
400 boost::int32_t te::pgis::ConnectedDataSet::getInt32(std::size_t i) const
401 {
402  int ival = *(reinterpret_cast<int*>(PQgetvalue(m_result, m_iFetch, static_cast<int>(i))));
403 
404 #if TE_MACHINE_BYTE_ORDER == TE_NDR
405  te::common::SwapBytes(ival);
406 #endif
407 
408  return static_cast<boost::int32_t>(ival);
409 }
410 
411 boost::int64_t te::pgis::ConnectedDataSet::getInt64(std::size_t i) const
412 {
413  boost::int64_t ival = *(reinterpret_cast<boost::int64_t*>(PQgetvalue(m_result, m_iFetch, static_cast<int>(i))));
414 
415 #if TE_MACHINE_BYTE_ORDER == TE_NDR
416  te::common::SwapBytes(ival);
417 #endif
418 
419  return ival;
420 }
421 
422 bool te::pgis::ConnectedDataSet::getBool(std::size_t i) const
423 {
424  char bval = *(PQgetvalue(m_result, m_iFetch, static_cast<int>(i)));
425  return bval != 0;
426 }
427 
428 float te::pgis::ConnectedDataSet::getFloat(std::size_t i) const
429 {
430  float fval = *(reinterpret_cast<float*>(PQgetvalue(m_result, m_iFetch, static_cast<int>(i))));
431 
432 #if TE_MACHINE_BYTE_ORDER == TE_NDR
433  te::common::SwapBytes(fval);
434 #endif
435 
436  return fval;
437 }
438 
439 double te::pgis::ConnectedDataSet::getDouble(std::size_t i) const
440 {
441  double dval = *(reinterpret_cast<double*>(PQgetvalue(m_result, m_iFetch, static_cast<int>(i))));
442 
443 #if TE_MACHINE_BYTE_ORDER == TE_NDR
444  te::common::SwapBytes(dval);
445 #endif
446 
447  return dval;
448 }
449 
450 std::string te::pgis::ConnectedDataSet::getNumeric(std::size_t i) const
451 {
452  char* val = PQgetvalue(m_result, m_iFetch, static_cast<int>(i));
453 
454 // get number of groups of 2 bytes used to represent the numeric number
455 // each 2 bytes represents 4 digits (ex: 2345678.87654 needs 4 groups. 2 to integer and 2 to decimals)
456  unsigned short totalGroups; // total number of groups
457 
458  totalGroups = *(reinterpret_cast<unsigned short*>(val));
459 
460 #if TE_MACHINE_BYTE_ORDER == TE_NDR
461  te::common::SwapBytes(totalGroups);
462 #endif
463 
464  if(totalGroups == 0)
465  return "0";
466 
467 // get number of groups of 2 bytes used to represent the decimal part of the number
468  unsigned short decimalGroups; // total number of groups
469 
470  decimalGroups = *(reinterpret_cast<unsigned short*>(val+2));
471 
472 #if TE_MACHINE_BYTE_ORDER == TE_NDR
473  te::common::SwapBytes(decimalGroups);
474 #endif
475 
476  ++decimalGroups;
477 
478  decimalGroups = totalGroups - decimalGroups;
479 
480 // get sign of the number
481  unsigned short sign; // sign of the number (positive: sign = 0, negative: sign = 0x4000)
482 
483  sign = *(reinterpret_cast<unsigned short*>(val+4));
484 
485 #if TE_MACHINE_BYTE_ORDER == TE_NDR
486  te::common::SwapBytes(sign);
487 #endif
488 
489  if(!(sign == 0 || sign == 0x4000))
490  return "";
491 
492  std::string intVal;
493 
494  if(sign != 0)
495  intVal = "-";
496 
497 //get integer part
498  unsigned short n;
499 
500  unsigned short ii = 0;
501 
502  while(ii < ((totalGroups - decimalGroups) * 2))
503  {
504  n = *(reinterpret_cast<unsigned short*>(val + ii + 8));
505 
506 #if TE_MACHINE_BYTE_ORDER == TE_NDR
508 #endif
509 
510  std::string v = te::common::Convert2String(static_cast<uint32_t>(n));
511  if(intVal.empty() == false)
512  {
513  if(n < 10)
514  v = "000" + v;
515  else if(n < 100)
516  v = "00" + v;
517  else if(n < 1000)
518  v = "0" + v;
519  }
520 
521  intVal += v;
522  ii += 2;
523  }
524 
525  if(ii == 0)
526  intVal += "0";
527 
528 //get decimal part
529  std::string decVal;
530 
531  if(decimalGroups == 0)
532  decVal = "0";
533  else
534  {
535  while(ii < (totalGroups * 2))
536  {
537  n = *(reinterpret_cast<unsigned short*>(val + ii + 8));
538 
539 #if TE_MACHINE_BYTE_ORDER == TE_NDR
541 #endif
542 
543  std::string newVal = te::common::Convert2String(static_cast<uint32_t>(n));
544 
545  while (newVal.length() < 4) //fill with zeros (ex: .0700 was "700")
546  newVal = "0" + newVal;
547 
548  decVal += newVal;
549 
550  ii += 2;
551  }
552 
553  while(!(decVal.empty()) && (decVal[decVal.length() - 1] == '0'))
554  decVal.erase(decVal.length() - 1);
555  }
556 
557  return intVal + "." + decVal;
558 }
559 
560 std::string te::pgis::ConnectedDataSet::getString(std::size_t i) const
561 {
562  std::string value(PQgetvalue(m_result, m_iFetch, static_cast<int>(i)));
563  return value;
564 }
565 
566 std::unique_ptr<te::dt::ByteArray> te::pgis::ConnectedDataSet::getByteArray(std::size_t i) const
567 {
568  int size = PQgetlength(m_result, m_iFetch, static_cast<int>(i));
569 
570  te::dt::ByteArray* b = new te::dt::ByteArray(static_cast<size_t>(size));
571  b->copy(PQgetvalue(m_result, m_iFetch, static_cast<int>(i)), static_cast<size_t>(size));
572  return std::unique_ptr<te::dt::ByteArray>(b);
573 }
574 
575 std::unique_ptr<te::gm::Geometry> te::pgis::ConnectedDataSet::getGeometry(std::size_t i) const
576 {
577  return std::unique_ptr<te::gm::Geometry>(EWKBReader::read(PQgetvalue(m_result, m_iFetch, static_cast<int>(i))));
578 }
579 
580 std::unique_ptr<te::rst::Raster> te::pgis::ConnectedDataSet::getRaster(std::size_t /*i*/) const
581 {
582  return std::unique_ptr<te::rst::Raster>();
583 }
584 
585 std::unique_ptr<te::dt::DateTime> te::pgis::ConnectedDataSet::getDateTime(std::size_t i) const
586 {
587  Oid tid = PQftype(m_result, static_cast<int>(i));
588  boost::int64_t ival = 0;
589  int iz;
590  double dval;
591 
592  switch(tid)
593  {
594  case PG_TIME_TYPE:
595  {
596  if(m_timeIsInteger)
597  {
598  ival = getInt64(i);
599  }
600  else
601  {
602  dval = getDouble(i);
603  ival = static_cast<boost::int64_t>(dval * 1000000);
604  }
605 
606  return std::unique_ptr<te::dt::DateTime>(Internal2Time(ival));
607  }
608 
609  case PG_DATE_TYPE:
610  {
611  ival = static_cast<boost::int64_t>(getInt32(i));
612 
613  return std::unique_ptr<te::dt::DateTime>(Internal2Date(static_cast<long>(ival)));
614  }
615 
616  case PG_TIMESTAMP_TYPE:
617  {
618  if(m_timeIsInteger)
619  ival = getInt64(i);
620  else
621  {
622  dval = getDouble(i);
623  ival = static_cast<boost::int64_t>(dval * 1000000);
624  }
625 
626  return std::unique_ptr<te::dt::DateTime>(Internal2TimeStamp(ival));
627  }
628 
629  case PG_TIMESTAMPTZ_TYPE:
630  {
631  if(m_timeIsInteger)
632  {
633  ival = getInt64(i);
634  iz = 0;
635  }
636  else
637  {
638  char* c = static_cast<char*>(PQgetvalue(m_result, m_iFetch, static_cast<int>(i)));
639  dval = *(reinterpret_cast<double*>(c));
640  c += 8;
641  iz = *(reinterpret_cast<int*>(c));
642 
643  #if TE_MACHINE_BYTE_ORDER == TE_NDR
644  te::common::SwapBytes(dval);
646  #endif
647 
648  ival = static_cast<boost::int64_t>(dval * 1000000);
649  }
650  iz /= 3600;
651  if(iz < -12)
652  iz = -12;
653  if(iz > 14)
654  iz = 14;
655 
656  return std::unique_ptr<te::dt::DateTime>(Internal2TimeStampTZ(ival, iz));
657  }
658  case PG_TIMETZ_TYPE:
659  {
660  if(m_timeIsInteger)
661  {
662  ival = getInt64(i);
663  iz = 0;
664  }
665  else
666  {
667  char* c = static_cast<char*>(PQgetvalue(m_result, m_iFetch, static_cast<int>(i)));
668  dval = *(reinterpret_cast<double*>(c));
669  c += 8;
670  iz = *(reinterpret_cast<int*>(c));
671 
672  #if TE_MACHINE_BYTE_ORDER == TE_NDR
673  te::common::SwapBytes(dval);
675  #endif
676 
677  ival = static_cast<boost::int64_t>(dval * 1000000);
678  }
679  iz /= 3600;
680  if(iz < -12)
681  iz = -12;
682  if(iz > 14)
683  iz = 14;
684  return std::unique_ptr<te::dt::DateTime>(Internal2TimeTZ(ival, iz));
685  }
686 
687  default:
688  throw Exception(TE_TR("This type is not supported by TerraLib!"));
689  }
690 }
691 
692 std::unique_ptr<te::dt::Array> te::pgis::ConnectedDataSet::getArray(std::size_t i) const
693 {
694  char* value = PQgetvalue(m_result, m_iFetch, static_cast<int>(i));
695 
696  int ndim = *(reinterpret_cast<int*>(value));
697  value += sizeof(int);
698 
699 #if TE_MACHINE_BYTE_ORDER == TE_NDR
700  te::common::SwapBytes(ndim);
701 #endif
702 
703  int dataoffset = *(reinterpret_cast<int*>(value));
704  value += sizeof(int);
705 
706 #if TE_MACHINE_BYTE_ORDER == TE_NDR
707  te::common::SwapBytes(dataoffset);
708 #endif
709 
710  unsigned int elemtype = *(reinterpret_cast<unsigned int*>(value));
711  value += sizeof(unsigned int);
712 
713 #if TE_MACHINE_BYTE_ORDER == TE_NDR
714  te::common::SwapBytes(elemtype);
715 #endif
716 
717  int* dimensions = reinterpret_cast<int*>(value);
718  value += ndim * sizeof(int);
719 
720  int* lowerbounds = reinterpret_cast<int*>(value);
721  value += ndim * sizeof(int);
722 
723  uint32_t* null_bitmap = reinterpret_cast<uint32_t*>(value);
724 
725  boost::dynamic_bitset<size_t> mask;
726 
727  if(dataoffset != 0)
728  {
729  int nmasks = (dataoffset + 3) / 4;
730 
731  mask.resize(static_cast<size_t>(nmasks * 8 * sizeof(uint32_t)));
732 
733  int pos = 0;
734 
735  for(int i = 0; i != nmasks; ++i)
736  {
737  value += sizeof(uint32_t);
738 
739  uint32_t umask = null_bitmap[i];
740 
741 #if TE_MACHINE_BYTE_ORDER == TE_NDR
742  te::common::SwapBytes(umask);
743 #endif
744 
745  for(int j = 0; j != 32; ++j)
746  {
747  mask[pos] = static_cast<unsigned long>(((umask >> j) & 1) == 0);
748  ++pos;
749  }
750  }
751  }
752  else
753  {
754  value += sizeof(uint32_t);
755  }
756 
757  switch(elemtype)
758  {
759  case PG_TEXT_TYPE:
760  case PG_VARCHAR_TYPE:
761  case PG_NAME_TYPE:
762  {
763  std::unique_ptr<te::dt::Array> arr(new te::dt::Array(static_cast<size_t>(ndim), te::dt::STRING_TYPE));
764 
765  std::vector<std::size_t> pos(static_cast<size_t>(ndim), 0);
766 
767  for(int d = 0; d != ndim; ++d)
768  {
769  int d_size = dimensions[d];
770 
771 #if TE_MACHINE_BYTE_ORDER == TE_NDR
772  te::common::SwapBytes(d_size);
773 #endif
774  int d_lower_boundary = lowerbounds[d];
775 
776 #if TE_MACHINE_BYTE_ORDER == TE_NDR
777  te::common::SwapBytes(d_lower_boundary);
778 #endif
779 
780  for(i = 0; i != static_cast<size_t>(d_size); ++i)
781  {
782  if((dataoffset != 0) && (!mask[i]))
783  {
784  arr->insert(nullptr, pos);
785  continue;
786  }
787 
788  pos[d] = i;
789 
790  int text_size = *reinterpret_cast<int*>(value);
791 
792 #if TE_MACHINE_BYTE_ORDER == TE_NDR
793  te::common::SwapBytes(text_size);
794 #endif
795  value += sizeof(int);
796 
797  arr->insert(new te::dt::String(value), pos);
798 
799  value += text_size;
800  }
801  }
802 
803  return std::unique_ptr<te::dt::Array>(arr.release());
804  }
805 
806  case PG_FLOAT8_TYPE:
807  {
808  std::unique_ptr<te::dt::Array> arr(new te::dt::Array(static_cast<size_t>(ndim), te::dt::DOUBLE_TYPE));
809 
810  std::vector<std::size_t> pos(static_cast<size_t>(ndim), 0);
811 
812  for(int d = 0; d != ndim; ++d)
813  {
814  int d_size = dimensions[d];
815 
816 #if TE_MACHINE_BYTE_ORDER == TE_NDR
817  te::common::SwapBytes(d_size);
818 #endif
819  int d_lower_boundary = lowerbounds[d];
820 
821 #if TE_MACHINE_BYTE_ORDER == TE_NDR
822  te::common::SwapBytes(d_lower_boundary);
823 #endif
824 
825  for(i = 0; i != static_cast<size_t>(d_size); ++i)
826  {
827  if((dataoffset != 0) && (!mask[i]))
828  {
829  arr->insert(nullptr, pos);
830  continue;
831  }
832 
833  pos[d] = i;
834 
835  double val = *reinterpret_cast<double*>(value);
836 
837 #if TE_MACHINE_BYTE_ORDER == TE_NDR
839 #endif
840 
841  arr->insert(new te::dt::Double(val), pos);
842 
843  value += sizeof(double);
844  }
845  }
846 
847  return std::unique_ptr<te::dt::Array>(arr.release());
848  }
849 
850  case PG_INT2_TYPE:
851  {
852  std::unique_ptr<te::dt::Array> arr(new te::dt::Array(static_cast<size_t>(ndim), te::dt::INT16_TYPE));
853 
854  std::vector<std::size_t> pos(static_cast<size_t>(ndim), 0);
855 
856  for(int d = 0; d != ndim; ++d)
857  {
858  int d_size = dimensions[d];
859 
860 #if TE_MACHINE_BYTE_ORDER == TE_NDR
861  te::common::SwapBytes(d_size);
862 #endif
863  int d_lower_boundary = lowerbounds[d];
864 
865 #if TE_MACHINE_BYTE_ORDER == TE_NDR
866  te::common::SwapBytes(d_lower_boundary);
867 #endif
868 
869  for(i = 0; i != static_cast<size_t>(d_size); ++i)
870  {
871  if((dataoffset != 0) && (!mask[i]))
872  {
873  arr->insert(nullptr, pos);
874  continue;
875  }
876 
877  pos[d] = i;
878 
879  boost::uint16_t val = *reinterpret_cast<boost::uint16_t*>(value);
880 
881 #if TE_MACHINE_BYTE_ORDER == TE_NDR
883 #endif
884 
885  arr->insert(new te::dt::Int16(static_cast<int16_t>(val)), pos);
886 
887  value += sizeof(uint16_t);
888  }
889  }
890 
891  return std::unique_ptr<te::dt::Array>(arr.release());
892  }
893 
894  default:
895  throw Exception(TE_TR("The array element type is not supported yet!"));
896  }
897 
898  // {
899  // te::common::SwapBytes(ndim);
900  // te::common::SwapBytes(dataoffset);
901  // te::common::SwapBytes(elemtype);
902  // te::common::SwapBytes(dimension);
903  // te::common::SwapBytes(lowerbnds);
904 
905  // a.reserve(dimension);
906 
907  // for(int k = 0; k < dimension; ++k)
908  // {
909  // T v = *((T*)value);
910  // te::common::SwapBytes(v);
911  // a.push_back(v);
912  // value += sizeof(ALIGN);
913  // }
914  // }
915  // else
916  // {
917  // a.reserve(dimension);
918 
919  // for(int k = 0; k < dimension; ++k)
920  // {
921  // T v = *((T*)value);
922  // a.push_back(v);
923  // value += sizeof(ALIGN);
924  // }
925  // }
926 }
927 
928 bool te::pgis::ConnectedDataSet::isNull(std::size_t i) const
929 {
930  return PQgetisnull(m_result, m_iFetch, static_cast<int>(i)) == 1;
931 }
int m_iFetch
The index of the current row of current fetch.
static te::gm::Geometry * read(const char *ewkb)
It returns a valid geometry from a given EWKB.
bool m_timeIsInteger
It indicates if the postgis stores, internally, the time and timestamp as an integer.
te::common::AccessPolicy getAccessPolicy() const
It returns the read and write permission associated to the dataset.
#define PG_TIMETZ_TYPE
A class that control the use of connection to a PostgreSQL database.
char getChar(std::size_t i) const
Method for retrieving a signed character attribute value (1 byte long).
bool moveLast()
It sets the dataset internal pointer to the last item in the collection.
bool isAtEnd() const
It tells if the dataset internal pointer is on the last element of the collection.
te::dt::DateTime * Internal2TimeTZ(boost::int64_t tval, int z)
te::dt::DateTime * Internal2Date(const long dDate)
It returns a DateTime type from a date loaded by PostgreSQL.
bool moveNext()
It moves the internal pointer to the next item of the collection.
Base exception class for plugin module.
int m_connectionId
The connection id used by this dataset.
std::size_t size() const
It returns the collection size, if it is known.
#define PG_TIMESTAMPTZ_TYPE
#define PG_NAME_TYPE
bool getBool(std::size_t i) const
Method for retrieving a boolean attribute value.
struct pg_result PGresult
int m_size
The number of datasets in the collection.
PGresult * m_result
The internal buffer with the result query.
te::dt::DateTime * Internal2TimeStampTZ(boost::int64_t ival, int z)
Utility functions for PostgreSQL.
static const MachineByteOrder sm_machineByteOrder
A flag that indicates the machine byte order (Big Endian or Little Endian).
boost::int32_t getInt32(std::size_t i) const
Method for retrieving a 32-bit integer attribute value (4 bytes long).
#define PG_INT2_TYPE
Implementation of a connected dataset for the PostGIS driver.
te::dt::DateTime * Internal2TimeStamp(boost::int64_t ival)
It returns a DateTime type from a timestamp loaded by PostgreSQL.
std::string m_idcursor
The id of current cursor.
bool isAtBegin() const
It tells if the dataset internal pointer is on the first element of the collection or not...
std::unique_ptr< te::dt::DateTime > getDateTime(std::size_t i) const
Method for retrieving a date and time attribute value.
~ConnectedDataSet()
The destructor will clear the internal PGresult.
#define TE_TR(message)
It marks a string in order to get translated.
Definition: Translator.h:242
bool movePrevious()
It moves the internal pointer to the previous item of the collection.
void execute(const std::string &command)
It executes the given SQL command and throws away the result.
void Union(const Envelope &rhs)
It updates the envelop with coordinates of another envelope.
#define PG_TIMESTAMP_TYPE
bool isConnected() const
It returns true if the dataset is connected and false if it is disconnected. A dataset can be connect...
bool isBeforeBegin() const
It tells if the dataset internal pointer is in a position before the first element of the collection ...
std::unique_ptr< te::rst::Raster > getRaster(std::size_t i) const
Method for retrieving a raster attribute value.
AccessPolicy
Supported data access policies (can be used as bitfield).
int b
Definition: TsRtree.cpp:32
TraverseType
A dataset can be traversed in two ways:
std::unique_ptr< te::gm::Geometry > getGeometry(std::size_t i) const
Method for retrieving a geometric attribute value.
An exception class for the PostGIS driver.
bool moveFirst()
It moves the internal pointer to the first item in the collection.
The type for variable-length multidimensional arrays.
Definition: Array.h:59
bool isNull(std::size_t i) const
It checks if the attribute value is NULL.
#define PG_TEXT_TYPE
An Envelope defines a 2D rectangular region.
URI C++ Library.
Definition: Attributes.h:37
double getDouble(std::size_t i) const
Method for retrieving a double attribute value.
static te::dt::DateTime d(2010, 8, 9, 15, 58, 39)
bool isPositionValid() const
It tells if the dataset internal pointer is on a valid position.
int m_fetchSize
The size of cursor fetch.
te::common::TraverseType getTraverseType() const
It returns the traverse type associated to the dataset.
#define PG_VARCHAR_TYPE
bool isEmpty() const
It returns true if the collection is empty.
float getFloat(std::size_t i) const
Method for retrieving a float attribute value.
std::unique_ptr< te::dt::Array > getArray(std::size_t i) const
Method for retrieving an array.
std::string getNumeric(std::size_t i) const
Method for retrieving a numeric attribute value.
A class that implements a connection to a PostgreSQL database.
void GetArray(int i, int j, PGresult *result, std::vector< T > &a)
It retrieves information from an unidimensional array.
ConnectedDataSet(PGresult *result, DataSource *dataSource, const int &connectionId, const std::string &id_cursor, const int &size, const std::vector< int > &ptypes, bool timeIsInteger=true)
Constructor.
std::string getDatasetNameOfProperty(std::size_t i) const
It returns the underlying dataset name of the property at position pos.
std::unique_ptr< te::gm::Envelope > getExtent(std::size_t i)
It computes the bounding rectangle for a spatial property of the dataset.
DataSource * m_ds
The DataSource to get the connection.
std::size_t getNumProperties() const
It returns the number of properties that composes an item of the dataset.
bool moveBeforeFirst()
It moves the internal pointer to a position before the first item in the collection.
bool move(std::size_t i)
It moves the dataset internal pointer to a given position.
unsigned char getUChar(std::size_t i) const
Method for retrieving an unsigned character attribute value (1 byte long).
#define PG_TIME_TYPE
A class that control the use of the connection to a PostgreSQL database.
ConnectionPool * getConnPool() const
It returns a pointer to the internal connection pool.
int getPropertyDataType(std::size_t i) const
It returns the underlying data type of the property at position pos.
boost::int64_t getInt64(std::size_t i) const
Method for retrieving a 64-bit integer attribute value (8 bytes long).
std::unique_ptr< te::dt::ByteArray > getByteArray(std::size_t i) const
Method for retrieving a byte array.
#define PG_FLOAT8_TYPE
#define PG_DATE_TYPE
std::vector< int > m_ptypes
The list of property types.
std::string getString(std::size_t i) const
Method for retrieving a string value attribute.
An utility class for reading a PostGIS EWKB.
int m_iLayer
The index of total layer of the current row.
te::dt::DateTime * Internal2Time(boost::int64_t tval)
It returns a DateTime type from a time loaded by PostgreSQL.
A template for atomic data types (integers, floats, strings and others).
Definition: SimpleData.h:59
std::string Convert2String(boost::int16_t value)
It converts a short integer value to a string.
Definition: StringUtils.h:56
boost::int16_t getInt16(std::size_t i) const
Method for retrieving a 16-bit integer attribute value (2 bytes long).
te::gm::Envelope * m_mbr
The dataset extent.
void copy(char *data, std::size_t size)
It copies the data from the given pointer to the byte array.
Definition: ByteArray.cpp:128
A class that implements a connection pool for PostGIS.
bool isAfterEnd() const
It tells if the dataset internal pointer is on the sentinel position after the last element of the co...
Implementation of the data source for the PostGIS driver.
std::string getPropertyName(std::size_t i) const
It returns the property name at position pos.
void SwapBytes(T &v)
It swaps the bytes in local.
A class for representing binary data.
Definition: ByteArray.h:51