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" 52 #include <boost/dynamic_bitset.hpp> 77 template<
class T,
class ALIGN>
inline void GetArray(
int i,
int j,
PGresult* result, std::vector<T>& a)
79 char* value = PQgetvalue(result, i, j);
81 int ndim = *(
reinterpret_cast<int*
>(value));
84 int dataoffset = *(
reinterpret_cast<int*
>(value));
87 unsigned int elemtype = *(
reinterpret_cast<unsigned int*
>(value));
88 value +=
sizeof(
unsigned int);
90 int dimension = *(
reinterpret_cast<int*
>(value));
93 int lowerbnds = *(
reinterpret_cast<int*
>(value));
94 value += (2 *
sizeof(int));
104 a.reserve(static_cast<size_t>(dimension));
106 for(
int k = 0; k < dimension; ++k)
108 T v = *(
reinterpret_cast<T*
>(value));
111 value +=
sizeof(ALIGN);
116 a.reserve(static_cast<size_t>(dimension));
118 for(
int k = 0; k < dimension; ++k)
120 T v = *(
reinterpret_cast<T*
>(value));
122 value +=
sizeof(ALIGN);
132 const int& connectionId,
133 const std::string& id_cursor,
135 const std::vector<int>& ptypes,
136 bool timeIsInteger) :
142 m_connectionId(connectionId),
143 m_idcursor(id_cursor),
146 m_timeIsInteger(timeIsInteger)
172 return static_cast<size_t>(PQnfields(
m_result));
182 return PQfname(
m_result, static_cast<int>(i));
202 return static_cast<std::size_t
>(
m_size);
210 throw Exception(
TE_TR(
"This driver only supports the getExtent method over a geometry column!"));
217 std::unique_ptr<te::gm::Geometry> geom(
getGeometry(i));
226 return std::unique_ptr<te::gm::Envelope>(mbr);
238 std::string fetch(
"FETCH FORWARD ");
239 fetch += boost::lexical_cast<std::string>(
m_fetchSize);
246 m_result = scopedConnection->query(fetch);
265 std::string fetch(
"FETCH BACKWARD ");
266 fetch += boost::lexical_cast<std::string>(
m_fetchSize);
273 m_result = scopedConnection->query(fetch);
280 return (m_iLayer > -1);
298 std::string fetch(
"FETCH LAST ");
303 m_result = scopedConnection->query(fetch);
316 std::string fetch(
"FETCH FIRST ");
324 m_result = scopedConnection->query(fetch);
332 if(static_cast<int>(i) >=
m_size)
337 std::string fetchRelative(
"FETCH ABSOLUTE ");
338 fetchRelative += boost::lexical_cast<std::string>(i+1);
339 fetchRelative +=
" FROM ";
343 m_result = scopedConnection->query(fetchRelative);
385 unsigned char cval = *
reinterpret_cast<unsigned char*
>((PQgetvalue(
m_result,
m_iFetch, static_cast<int>(i))));
391 short int ival = *(
reinterpret_cast<short int*
>(PQgetvalue(
m_result,
m_iFetch, static_cast<int>(i))));
393 #if TE_MACHINE_BYTE_ORDER == TE_NDR 397 return static_cast<boost::int16_t
>(ival);
402 int ival = *(
reinterpret_cast<int*
>(PQgetvalue(
m_result,
m_iFetch, static_cast<int>(i))));
404 #if TE_MACHINE_BYTE_ORDER == TE_NDR 408 return static_cast<boost::int32_t
>(ival);
413 boost::int64_t ival = *(
reinterpret_cast<boost::int64_t*
>(PQgetvalue(
m_result,
m_iFetch, static_cast<int>(i))));
415 #if TE_MACHINE_BYTE_ORDER == TE_NDR 430 float fval = *(
reinterpret_cast<float*
>(PQgetvalue(
m_result,
m_iFetch, static_cast<int>(i))));
432 #if TE_MACHINE_BYTE_ORDER == TE_NDR 441 double dval = *(
reinterpret_cast<double*
>(PQgetvalue(
m_result,
m_iFetch, static_cast<int>(i))));
443 #if TE_MACHINE_BYTE_ORDER == TE_NDR 456 unsigned short totalGroups;
458 totalGroups = *(
reinterpret_cast<unsigned short*
>(val));
460 #if TE_MACHINE_BYTE_ORDER == TE_NDR 468 unsigned short decimalGroups;
470 decimalGroups = *(
reinterpret_cast<unsigned short*
>(val+2));
472 #if TE_MACHINE_BYTE_ORDER == TE_NDR 478 decimalGroups = totalGroups - decimalGroups;
483 sign = *(
reinterpret_cast<unsigned short*
>(val+4));
485 #if TE_MACHINE_BYTE_ORDER == TE_NDR 489 if(!(sign == 0 || sign == 0x4000))
500 unsigned short ii = 0;
502 while(ii < ((totalGroups - decimalGroups) * 2))
504 n = *(
reinterpret_cast<unsigned short*
>(val + ii + 8));
506 #if TE_MACHINE_BYTE_ORDER == TE_NDR 511 if(intVal.empty() ==
false)
531 if(decimalGroups == 0)
535 while(ii < (totalGroups * 2))
537 n = *(
reinterpret_cast<unsigned short*
>(val + ii + 8));
539 #if TE_MACHINE_BYTE_ORDER == TE_NDR 545 while (newVal.length() < 4)
546 newVal =
"0" + newVal;
553 while(!(decVal.empty()) && (decVal[decVal.length() - 1] ==
'0'))
554 decVal.erase(decVal.length() - 1);
557 return intVal +
"." + decVal;
572 return std::unique_ptr<te::dt::ByteArray>(
b);
582 return std::unique_ptr<te::rst::Raster>();
587 Oid tid = PQftype(
m_result, static_cast<int>(i));
588 boost::int64_t ival = 0;
603 ival =
static_cast<boost::int64_t
>(dval * 1000000);
606 return std::unique_ptr<te::dt::DateTime>(
Internal2Time(ival));
611 ival =
static_cast<boost::int64_t
>(
getInt32(i));
613 return std::unique_ptr<te::dt::DateTime>(
Internal2Date(static_cast<long>(ival)));
623 ival =
static_cast<boost::int64_t
>(dval * 1000000);
638 char* c =
static_cast<char*
>(PQgetvalue(
m_result,
m_iFetch, static_cast<int>(i)));
639 dval = *(
reinterpret_cast<double*
>(c));
641 iz = *(
reinterpret_cast<int*
>(c));
643 #if TE_MACHINE_BYTE_ORDER == TE_NDR 648 ival =
static_cast<boost::int64_t
>(dval * 1000000);
667 char* c =
static_cast<char*
>(PQgetvalue(
m_result,
m_iFetch, static_cast<int>(i)));
668 dval = *(
reinterpret_cast<double*
>(c));
670 iz = *(
reinterpret_cast<int*
>(c));
672 #if TE_MACHINE_BYTE_ORDER == TE_NDR 677 ival =
static_cast<boost::int64_t
>(dval * 1000000);
688 throw Exception(
TE_TR(
"This type is not supported by TerraLib!"));
696 int ndim = *(
reinterpret_cast<int*
>(value));
697 value +=
sizeof(
int);
699 #if TE_MACHINE_BYTE_ORDER == TE_NDR 703 int dataoffset = *(
reinterpret_cast<int*
>(value));
704 value +=
sizeof(
int);
706 #if TE_MACHINE_BYTE_ORDER == TE_NDR 710 unsigned int elemtype = *(
reinterpret_cast<unsigned int*
>(value));
711 value +=
sizeof(
unsigned int);
713 #if TE_MACHINE_BYTE_ORDER == TE_NDR 717 int* dimensions =
reinterpret_cast<int*
>(value);
718 value += ndim *
sizeof(int);
720 int* lowerbounds =
reinterpret_cast<int*
>(value);
721 value += ndim *
sizeof(int);
723 uint32_t* null_bitmap =
reinterpret_cast<uint32_t*
>(value);
725 boost::dynamic_bitset<size_t> mask;
729 int nmasks = (dataoffset + 3) / 4;
731 mask.resize(static_cast<size_t>(nmasks * 8 *
sizeof(uint32_t)));
735 for(
int i = 0; i != nmasks; ++i)
737 value +=
sizeof(uint32_t);
739 uint32_t umask = null_bitmap[i];
741 #if TE_MACHINE_BYTE_ORDER == TE_NDR 745 for(
int j = 0; j != 32; ++j)
747 mask[pos] =
static_cast<unsigned long>(((umask >> j) & 1) == 0);
754 value +=
sizeof(uint32_t);
765 std::vector<std::size_t> pos(static_cast<size_t>(ndim), 0);
767 for(
int d = 0;
d != ndim; ++
d)
769 int d_size = dimensions[
d];
771 #if TE_MACHINE_BYTE_ORDER == TE_NDR 774 int d_lower_boundary = lowerbounds[
d];
776 #if TE_MACHINE_BYTE_ORDER == TE_NDR 780 for(i = 0; i !=
static_cast<size_t>(d_size); ++i)
782 if((dataoffset != 0) && (!mask[i]))
784 arr->insert(
nullptr, pos);
790 int text_size = *
reinterpret_cast<int*
>(value);
792 #if TE_MACHINE_BYTE_ORDER == TE_NDR 795 value +=
sizeof(int);
803 return std::unique_ptr<te::dt::Array>(arr.release());
810 std::vector<std::size_t> pos(static_cast<size_t>(ndim), 0);
812 for(
int d = 0;
d != ndim; ++
d)
814 int d_size = dimensions[
d];
816 #if TE_MACHINE_BYTE_ORDER == TE_NDR 819 int d_lower_boundary = lowerbounds[
d];
821 #if TE_MACHINE_BYTE_ORDER == TE_NDR 825 for(i = 0; i !=
static_cast<size_t>(d_size); ++i)
827 if((dataoffset != 0) && (!mask[i]))
829 arr->insert(
nullptr, pos);
835 double val = *
reinterpret_cast<double*
>(value);
837 #if TE_MACHINE_BYTE_ORDER == TE_NDR 843 value +=
sizeof(double);
847 return std::unique_ptr<te::dt::Array>(arr.release());
854 std::vector<std::size_t> pos(static_cast<size_t>(ndim), 0);
856 for(
int d = 0;
d != ndim; ++
d)
858 int d_size = dimensions[
d];
860 #if TE_MACHINE_BYTE_ORDER == TE_NDR 863 int d_lower_boundary = lowerbounds[
d];
865 #if TE_MACHINE_BYTE_ORDER == TE_NDR 869 for(i = 0; i !=
static_cast<size_t>(d_size); ++i)
871 if((dataoffset != 0) && (!mask[i]))
873 arr->insert(
nullptr, pos);
879 boost::uint16_t val = *
reinterpret_cast<boost::uint16_t*
>(value);
881 #if TE_MACHINE_BYTE_ORDER == TE_NDR 885 arr->insert(
new te::dt::Int16(static_cast<int16_t>(val)), pos);
887 value +=
sizeof(uint16_t);
891 return std::unique_ptr<te::dt::Array>(arr.release());
895 throw Exception(
TE_TR(
"The array element type is not supported yet!"));
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.
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
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).
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.
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).
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.
bool isNull(std::size_t i) const
It checks if the attribute value is NULL.
An Envelope defines a 2D rectangular region.
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.
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).
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.
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).
std::string Convert2String(boost::int16_t value)
It converts a short integer value to a string.
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.
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.