Utils.h
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/Utils.h
22 
23  \brief Utility functions for PostgreSQL.
24 */
25 
26 #ifndef __TERRALIB_POSTGIS_INTERNAL_UTILS_H
27 #define __TERRALIB_POSTGIS_INTERNAL_UTILS_H
28 
29 // TerraLib
30 #include "../common/ByteSwapUtils.h"
31 #include "../common/Globals.h"
32 #include "../common/StringUtils.h"
33 #include "../dataaccess/Enums.h"
34 #include "../datatype/ArrayProperty.h"
35 #include "../datatype/Date.h"
36 #include "../datatype/DateTimeProperty.h"
37 #include "../datatype/NumericProperty.h"
38 #include "../datatype/SimpleProperty.h"
39 #include "../datatype/StringProperty.h"
40 #include "../datatype/TimeDuration.h"
41 #include "../datatype/TimeInstant.h"
42 #include "../datatype/TimeInstantTZ.h"
43 #include "../geometry/Envelope.h"
44 #include "../geometry/Geometry.h"
45 #include "../geometry/GeometryProperty.h"
46 #include "../raster/RasterProperty.h"
47 #include "Config.h"
48 
49 // STL
50 #include <cstdlib>
51 #include <cstring>
52 #include <string>
53 #include <vector>
54 
55 #include <boost/date_time/time_zone_base.hpp>
56 
57 // Forward declaration for libpq
58 extern "C"
59 {
60  struct pg_conn;
61  typedef struct pg_conn PGconn;
62 
63  struct pg_result;
64  typedef struct pg_result PGresult;
65 }
66 
67 namespace te
68 {
69  // Forward declarations
70  namespace core { class URI; }
71 
72  namespace da
73  {
74  class DataSet;
75  class DataSetType;
76  }
77 
78  namespace pgis
79  {
80  /*!
81  \brief It returns the geometry names as usual for PostGIS.
82 
83  \param t The TerraLib geometry type.
84 
85  \return The geometry names as usual for PostGIS.
86  */
87  const std::string& GetGeometryName(te::gm::GeomType t);
88 
89  /*!
90  \brief It writes the PostgreSQL column definition to the output string.
91 
92  \param s The string to output the column definition.
93  \param p The TerraLib propoerty type.
94 
95  \return It returns true if the property type is an autonumber.
96 
97  \exception Exception It throws an exception if the data type is not mapped to the PostgreSQL type system.
98  */
99  bool SetColumnDef(std::string& s, const te::dt::Property* p, bool justDataType = false);
100 
101  /*!
102  \brief It converts the PostgreSQL foreign key modifier to a TerraLib data type.
103 
104  <ul>
105  <li>a: NO_ACTION</li>
106  <li>r: RESTRICT</li>
107  <li>c: CASCADE</li>
108  <li>n: SET_NULL</li>
109  <li>d: SET_DEFAULT</li>
110  </ul>
111 
112  \param a PostgreSQL foreign key modifier type.
113 
114  \retun The equivalent TerraLib foreign key modifier type.
115  */
117  {
118  switch(a)
119  {
120  case 'a' : return te::da::NO_ACTION;
121  case 'r' : return te::da::RESTRICT;
122  case 'c' : return te::da::CASCADE;
123  case 'n' : return te::da::SET_NULL;
124  case 'd' : return te::da::SET_DEFAULT;
125  }
126 
127  return te::da::NO_ACTION;
128  }
129 
130  /*!
131  \brief It converts the PostgreSQL index string to a TerraLib index type.
132 
133  <ul>
134  <li>btree: BTreeType</li>
135  <li>gist: RTreeType</li>
136  <li>gin: BTreeType</li>
137  <li>hash: HashType</li>
138  </ul>
139 
140  \param t PostgreSQL index name (A NULL terminated string).
141 
142  \retun The equivalent TerraLib foreign key modifier type.
143  */
144  inline te::da::IndexType GetIndexType(const char* t)
145  {
146  if(strcmp(t, "btree") == 0)
147  {
148  return te::da::B_TREE_TYPE;
149  }
150  else if(strcmp(t, "gist") == 0)
151  {
152  return te::da::R_TREE_TYPE;
153  }
154  else if(strcmp(t, "gin") == 0)
155  {
156  return te::da::B_TREE_TYPE;
157  }
158  else //if(strcmp(t, "hash") == 0)
159  {
160  return te::da::HASH_TYPE;
161  }
162  }
163 
164  /*!
165  \brief It converts the pgType to a valid TerraLib data type.
166 
167  \param cols An array with column numbers.
168  \param dt The DataSetType to look for the property.
169 
170  \return The next.
171  */
172  inline te::gm::Envelope* GetEnvelope(const char* str)
173  {
174  std::string enve(str);
175  size_t st = enve.find(",");
176  if(st != std::string::npos)
177  enve.replace(st, 1, ";");
178  double dval = atof("1,2");
179  if(dval == 1.2) // if decimal separator is ','
180  {
181  st = enve.find(".");
182  while(st != std::string::npos)
183  {
184  enve.replace(st, 1, ",");
185  st = enve.find(".");
186  }
187  }
188  const char* enveStr = enve.c_str();
189 
191 
192  enveStr += 4;
193  mbr->m_llx = atof(enveStr);
194 
195  while(*enveStr != ' ')
196  ++enveStr;
197 
198  ++enveStr;
199 
200  mbr->m_lly = atof(enveStr);
201 
202  while(*enveStr != ';')
203  ++enveStr;
204 
205  ++enveStr;
206 
207  mbr->m_urx = atof(enveStr);
208 
209  while(*enveStr != ' ')
210  ++enveStr;
211 
212  ++enveStr;
213 
214  mbr->m_ury = atof(enveStr);
215 
216  return mbr;
217  }
218 
219  /*!
220  \brief It converts the envelope into a PostGIS BOX3D.
221 
222  \param e The envelope to be converted.
223  \param srid The envelope coordinates SRS.
224  \param output The string to output the result.
225 
226  \todo Toda chamada de rotinas de conversao de double para string deveria dizer a precisao!
227  */
228  inline void Convert2PostGIS(const te::gm::Envelope* e, int srid, std::string& output)
229  {
230  output += "ST_MakeEnvelope(";
231  output += te::common::Convert2String(e->m_llx, 15);
232  output += ", ";
233  output += te::common::Convert2String(e->m_lly, 15);
234  output += ", ";
235  output += te::common::Convert2String(e->m_urx, 15);
236  output += ", ";
237  output += te::common::Convert2String(e->m_ury, 15);
238  output += ", ";
239  output += te::common::Convert2String(srid);
240  output += ")";
241  }
242 
243  /*!
244  \brief It converts the geometry into a PostGIS geometry.
245 
246  \param conn The connection to be used with bytearray.
247  \param g The geometry to be converted.
248  \param output The string to output the result.
249  */
250  void Convert2PostGIS(PGconn* conn, const te::gm::Geometry* g, std::string& output);
251 
252  /*!
253  \brief It escapes a string for use within an SQL command.
254 
255  \param conn The connection to be used with bytearray.
256  \param s The string to be scapaded.
257  \param output The string to output the result.
258  */
259  void ScapeString(PGconn* conn, const std::string& s, std::string& output);
260 
261  /*!
262  \brief It returns a julian date (in seconds) from a gregorian date.
263 
264  It returns a julian date (in seconds) from a gregorian date.
265  Internally, postgresql stores julian dates.
266 
267  \param y A year of a gregorian date.
268  \param m A month of a gregorian date.
269  \param d A day of a gregorian date.
270 
271  \return a julian date in seconds from the informed gregorian date.
272  */
273  inline int Date2Julian(int y, int m, const int d)
274  {
275  int julian = 0;
276  int century = 0;
277 
278  if(m > 2)
279  {
280  m += 1;
281  y += 4800;
282  }
283  else
284  {
285  m += 13;
286  y += 4799;
287  }
288 
289  century = y / 100;
290  julian = y * 365 - 32167;
291  julian += y / 4 - century + century / 4;
292  julian += 7834 * m / 256 + d;
293 
294  return julian;
295  }
296 
297  /*!
298  \brief It returns a gregorian date from a julian date (in seconds).
299 
300  It returns a gregorian date from a julian date (in seconds).
301 
302  \param jd A julian date in seconds (INPUT).
303  \param year The year of a gregorian date that will be filled by this function (OUTPUT).
304  \param month The month of a gregorian date that will be filled by this function (OUTPUT).
305  \param day The day of a gregorian date that will be filled by this function (OUTPUT).
306  */
307  inline void Julian2Date(const int jd, int* year, int* month, int* day)
308  {
309  unsigned int julian = 0;
310  unsigned int quad = 0;
311  unsigned int extra = 0;
312  int y = 0;
313 
314  julian = jd;
315  julian += 32044;
316  quad = julian / 146097;
317  extra = (julian - quad * 146097) * 4 + 3;
318  julian += 60 + quad * 3 + extra / 146097;
319  quad = julian / 1461;
320  julian -= quad * 1461;
321  y = julian * 4 / 1461;
322  julian = ((y != 0) ? ((julian + 305) % 365) : ((julian + 306) % 366)) + 123;
323  y += quad * 4;
324  *year = y - 4800;
325  quad = julian * 2141 / 65536;
326  *day = julian - 7834 * quad / 256;
327  *month = (quad + 10) % 12 + 1;
328 
329  return;
330  }
331 
332  /*!
333  \brief It returns a DateTime type from a date loaded by PostgreSQL.
334 
335  It returns a DateTime type from a date loaded by PostgreSQL. Internelly,
336  PostgreSQL stores julian dates in 4 bytes, so this function has to convert it
337  to gregorian date. Besides that, PostgreSQL stores date as seconds before
338  or after midnight 2000-01-01. Therefore, this function has to sum the number
339  of seconds (2451545 seconds) between 01-01-01 00:00:00 and 01-01-2000 00:00:00
340  to the date.
341 
342  \param dDate A julian date in seconds loaded by PostgreSQL.
343 
344  \param return A gregorian date from the input julian date.
345  */
346  inline te::dt::DateTime* Internal2Date(const long dDate)
347  {
348  int year, month, day;
349  //2451545: number of seconds between 01-01-01 00:00:00 and 01-01-2000 00:00:00
350  Julian2Date(dDate + 2451545, &year, &month, &day);
351  te::dt::DateTime* result = new te::dt::Date(static_cast<unsigned short>(year), static_cast<unsigned short>(month), static_cast<unsigned short>(day));
352  return result;
353  }
354 
355  /*!
356  \brief It returns a DateTime type from a time loaded by PostgreSQL.
357 
358  It returns a DateTime type from a time loaded by PostgreSQL. Internelly,
359  PostgreSQL stores time as seconds.
360 
361  \param tval The amount of seconds loaded by PostgreSQL.
362 
363  \param return A time (hour, minute, second) from the input amount of seconds.
364  */
365  inline te::dt::DateTime* Internal2Time(boost::int64_t tval)
366  {
367  int hour = (int)(tval / 3600000000UL);
368  boost::int64_t timeval = tval - hour * (boost::int64_t)3600000000UL;
369  int min = (int)(timeval / 60000000);
370  timeval -= min * (boost::int64_t)60000000;
371  int sec = (int)(timeval / 1000000);
372  timeval -= sec * (boost::int64_t)1000000;
373  int fsec = (int) timeval;
374 
375  boost::posix_time::time_duration td(hour, min, sec, fsec);
376  te::dt::DateTime* result = new te::dt::TimeDuration(td);
377  return result;
378  }
379 
380  inline te::dt::DateTime* Internal2TimeTZ(boost::int64_t tval, int z)
381  {
382  int hour = (int)(tval / 3600000000UL);
383  boost::int64_t timeval = tval - hour * (boost::int64_t)3600000000UL;
384  int min = (int)(timeval / 60000000);
385  timeval -= min * (boost::int64_t)60000000;
386  int sec = (int)(timeval / 1000000);
387  timeval -= sec * (boost::int64_t)1000000;
388  int fsec = (int) timeval;
389 
390  boost::posix_time::time_duration td(hour, min, sec, fsec);
391  char buf[10];
392  sprintf(buf, "%d", z);
393  std::string sz = "OFF";
394  if(z >= 0)
395  sz += "+";
396  sz += buf;
397  boost::local_time::time_zone_ptr zp(new boost::local_time::posix_time_zone(sz));
398 
399  boost::posix_time::ptime pt(boost::gregorian::date(2000, 01, 01), td);
400  boost::local_time::local_date_time tz(pt, zp);
402 
403  return result;
404  }
405 
406  /*!
407  \brief It returns a DateTime type from a timestamp loaded by PostgreSQL.
408 
409  It returns a DateTime type from a timestamp loaded by PostgreSQL. Internelly,
410  PostgreSQL stores timestamp as seconds before or after midnight 2000-01-01.
411 
412  \param ival The timestamp, in seconds, loaded by PostgreSQL.
413 
414  \param return A time instant from the input timestamp.
415  */
416  inline te::dt::DateTime* Internal2TimeStamp(boost::int64_t ival)
417  {
418  boost::int64_t dateval;
419  boost::int64_t timeval = ival;
420 
421  //1 day has 86400 seconds (* 1000000)
422  dateval = timeval / 86400000000LL;
423  if(dateval != 0)
424  timeval -= dateval * 86400000000LL;
425 
426  if (timeval < 0)
427  {
428  timeval += 86400000000LL;
429  dateval -= 1;
430  }
431 
432  te::dt::DateTime* aux1 = Internal2Date((long)dateval);
433  te::dt::DateTime* aux2 = Internal2Time(timeval);
434  te::dt::DateTime* result = new te::dt::TimeInstant(*static_cast<te::dt::Date*>(aux1), *static_cast<te::dt::TimeDuration*>(aux2));
435  delete aux1;
436  delete aux2;
437  return result;
438  }
439 
440  inline te::dt::DateTime* Internal2TimeStampTZ(boost::int64_t ival, int z)
441  {
442  boost::int64_t dateval;
443  boost::int64_t timeval = ival;
444 
445  //1 day has 86400 seconds (* 1000000)
446  dateval = timeval / 86400000000LL;
447  if(dateval != 0)
448  timeval -= dateval * 86400000000LL;
449 
450  if (timeval < 0)
451  {
452  timeval += 86400000000LL;
453  dateval -= 1;
454  }
455 
456  te::dt::Date* aux1 = static_cast<te::dt::Date*>(Internal2Date((long)dateval));
457  te::dt::TimeInstantTZ* aux2 = static_cast<te::dt::TimeInstantTZ*>(Internal2TimeTZ(timeval, z));
458 
459  boost::local_time::local_date_time tz(aux1->getDate(), aux2->getTimeInstantTZ().local_time().time_of_day(), aux2->getTimeInstantTZ().zone(), true);
460 
462  delete aux1;
463  delete aux2;
464  return result;
465  }
466 
467 
468  /*!
469  \brief It creates a PropertyType from a PostgreSQL attribute description.
470 
471  \param attNum The column number (a number in the range [1, num-columns]).
472  \param attName The column name.
473  \param attType The column type
474  \param attLen The column size (depends on column type).
475  \param attNotNull If the column is not null.
476  \param fmt Column formats: Numeric(20, 30), VARCHAR(30), CHAR(10).
477  \param attHasDefault True if the column has a default value.
478  \param attDefValue The default value expression if attHasDefValue is true otherwise this has no meaning.
479  \param pgisGeomTypeOid The oid of PostGIS geometry type.
480 
481  \return The TerraLib equivalent datatype.
482 
483  \note The caller of this function will take the ownership of the returned PropertyType.
484  \note This method is valid just for types different from Array. For array types, see the method below (Convert2TerraLib) where the dimension info must be available.
485  */
486  inline te::dt::Property* Convert2TerraLib(unsigned int attNum, const char* attName, unsigned int attType,
487  bool attNotNull, const char* fmt,
488  bool attHasDefault, const char* attDefValue,
489  unsigned int pgisGeomTypeOid,
490  unsigned int pgisRasterTypeOid)
491  {
492  te::dt::Property* p = 0;
493  te::dt::SimpleProperty* simpleP = 0;
494 
495  std::string* defaultValue = (attHasDefault ? new std::string(attDefValue) : 0);
496  std::string name = std::string(attName);
497 
498  if(attType == pgisGeomTypeOid)
499  return new te::gm::GeometryProperty(name, attNotNull, defaultValue, attNum);
500  else if(attType == pgisRasterTypeOid)
501  return new te::rst::RasterProperty(name, attNotNull, attNum);
502 
503  switch(attType)
504  {
505  case PG_INT2_TYPE:
506  p = new te::dt::SimpleProperty(name, te::dt::INT16_TYPE, attNotNull, defaultValue, attNum);
507  break;
508 
509  case PG_INT4_TYPE:
510  simpleP = new te::dt::SimpleProperty(name, te::dt::INT32_TYPE, attNotNull, defaultValue, attNum);
511 
512  if(defaultValue != 0 && defaultValue->find("nextval(") == 0)
513  simpleP->setAutoNumber(true);
514 
515  p = simpleP;
516  break;
517 
518  case PG_INT8_TYPE:
519  simpleP = new te::dt::SimpleProperty(name, te::dt::INT64_TYPE, attNotNull, defaultValue, attNum);
520 
521  if(defaultValue != 0 && defaultValue->find("nextval(") == 0)
522  simpleP->setAutoNumber(true);
523 
524  p = simpleP;
525  break;
526 
527  case PG_OID_TYPE:
528  p = new te::dt::SimpleProperty(name, te::dt::INT32_TYPE, attNotNull, defaultValue, attNum);
529  break;
530 
531  case PG_FLOAT8_TYPE:
532  p = new te::dt::SimpleProperty(name, te::dt::DOUBLE_TYPE, attNotNull, defaultValue, attNum);
533  break;
534 
535  case PG_NUMERIC_TYPE:
536  {
537  unsigned int precision = (fmt && (*(fmt + 7) != '\0') ? atoi(fmt + 8) : 0);
538  const char* sprecision = fmt ? strstr(fmt,",") : 0;
539  unsigned int scale = (sprecision ? atoi(sprecision + 1) : 0);
540 
541  p = new te::dt::NumericProperty(name, precision, scale, attNotNull, defaultValue, attNum);
542  }
543  break;
544 
545  case PG_VARCHAR_TYPE:
546  {
547  unsigned int size = fmt ? atoi(fmt + 18) : 0;
548 
549  p = new te::dt::StringProperty(name, te::dt::VAR_STRING, size, attNotNull, defaultValue, attNum);
550  }
551  break;
552 
553  case PG_TEXT_TYPE:
554  p = new te::dt::StringProperty(name, te::dt::STRING, 0, attNotNull, defaultValue, attNum);
555  break;
556 
557  case PG_DATE_TYPE:
558  p = new te::dt::DateTimeProperty(name, te::dt::DATE, attNotNull, defaultValue, attNum);
559  break;
560 
561  case PG_TIME_TYPE:
562  p = new te::dt::DateTimeProperty(name, te::dt::TIME_DURATION, attNotNull, defaultValue, attNum);
563  break;
564 
565  case PG_TIMETZ_TYPE:
566  case PG_TIMESTAMPTZ_TYPE:
567  case PG_TIMESTAMP_TYPE:
568  p = new te::dt::DateTimeProperty(name, te::dt::TIME_INSTANT, attNotNull, defaultValue, attNum);
569  break;
570 
571  case PG_BOOL_TYPE:
572  p = new te::dt::SimpleProperty(name, te::dt::BOOLEAN_TYPE, attNotNull, defaultValue, attNum);
573  break;
574 
575  case PG_BYTEA_TYPE:
576  p = new te::dt::SimpleProperty(name, te::dt::BYTE_ARRAY_TYPE, attNotNull, defaultValue, attNum);
577  break;
578 
579  case PG_FLOAT4_TYPE:
580  p = new te::dt::SimpleProperty(name, te::dt::FLOAT_TYPE, attNotNull, defaultValue, attNum);
581  break;
582 
583  case PG_CHARACTER_TYPE:
584  case PG_NAME_TYPE:
585  {
586  unsigned int size = (fmt && (*(fmt + 9) != '\0') ? atoi(fmt + 10) : 0);
587 
588  p = new te::dt::StringProperty(name, te::dt::FIXED_STRING, size, attNotNull, defaultValue, attNum);
589  }
590  break;
591 
592  case PG_CHAR_TYPE:
593  p = new te::dt::SimpleProperty(name, te::dt::CHAR_TYPE, attNotNull, defaultValue, attNum);
594  break;
595 
596  default:
597  p = new te::dt::SimpleProperty(name, te::dt::UNKNOWN_TYPE, attNotNull, defaultValue, attNum);
598  }
599 
600  return p;
601  }
602 
603  /*!
604  \brief It creates a PropertyType from a PostgreSQL attribute description.
605 
606  \param attNum The column number.
607  \param attName The column name.
608  \param attType The column type.
609  \param attNotNull If the column is not null.
610  \param fmt Column formats: Numeric(20, 30), VARCHAR(30), CHAR(10).
611  \param attHasDefault True, if the column has a default value.
612  \param attDefValue The default value expression, if attHasDefValue is true; otherwise, it has no meaning.
613  \param ndims If different of 0, it indicates an array type.
614  \param pgisGeomTypeOid The oid of the PostGIS geometry type.
615 
616  \return The TerraLib equivalent PropertyType.
617 
618  \note The caller of this method will take the ownership of the returned PropertyType.
619  \note This method may be used for array types also.
620  */
621  inline te::dt::Property* Convert2TerraLib(unsigned int attNum, const char* attName, unsigned int attType,
622  bool attNotNull, const char* fmt,
623  bool attHasDefault, const char* attDefValue,
624  int ndims, unsigned int pgisGeomTypeOid,
625  unsigned int pgisRasterTypeOid)
626  {
627  if(ndims == 0)
628  return Convert2TerraLib(attNum, attName, attType, attNotNull, fmt,
629  attHasDefault, attDefValue,
630  pgisGeomTypeOid, pgisRasterTypeOid);
631 
632  std::string* defaultValue = (attHasDefault ? new std::string(attDefValue) : 0);
633  std::string name = std::string(attName);
634 
635  te::dt::ArrayProperty* arrayElementProperty = 0;
636 
637  for(int i = 0; i < ndims - 1; ++i)
638  arrayElementProperty = new te::dt::ArrayProperty(std::string(), arrayElementProperty);
639 
640  te::dt::ArrayProperty* at = new te::dt::ArrayProperty(name, arrayElementProperty, attNotNull, defaultValue, attNum);
641 
642  switch(attType)
643  {
644  case PG_BOOL_ARRAY_TYPE:
645  {
646  te::dt::Property* p = Convert2TerraLib(attNum, attName, PG_BOOL_TYPE, attNotNull, fmt, attHasDefault, attDefValue, pgisGeomTypeOid, pgisRasterTypeOid);
647  if(arrayElementProperty)
648  arrayElementProperty->setElementType(p);
649  else
650  at->setElementType(p);
651  break;
652  }
653 
654  case PG_BYTEA_ARRAY_TYPE:
655  {
656  te::dt::Property* p = Convert2TerraLib(attNum, attName, PG_BYTEA_TYPE, attNotNull, fmt, attHasDefault, attDefValue, pgisGeomTypeOid, pgisRasterTypeOid);
657  if(arrayElementProperty)
658  arrayElementProperty->setElementType(p);
659  else
660  at->setElementType(p);
661  break;
662  }
663 
664  case PG_CHAR_ARRAY_TYPE:
665  {
666  te::dt::Property* p = Convert2TerraLib(attNum, attName, PG_CHAR_TYPE, attNotNull, fmt, attHasDefault, attDefValue, pgisGeomTypeOid, pgisRasterTypeOid);
667  if(arrayElementProperty)
668  arrayElementProperty->setElementType(p);
669  else
670  at->setElementType(p);
671  break;
672  }
673 
674  case PG_INT8_ARRAY_TYPE:
675  {
676  te::dt::Property* p = Convert2TerraLib(attNum, attName, PG_INT8_TYPE, attNotNull, fmt, attHasDefault, attDefValue, pgisGeomTypeOid, pgisRasterTypeOid);
677  if(arrayElementProperty)
678  arrayElementProperty->setElementType(p);
679  else
680  at->setElementType(p);
681  break;
682  }
683 
684  case PG_INT2_ARRAY_TYPE:
685  case PG_INT2_VECTOR_TYPE:
687  {
688  te::dt::Property* p = Convert2TerraLib(attNum, attName, PG_INT2_TYPE, attNotNull, fmt, attHasDefault, attDefValue, pgisGeomTypeOid, pgisRasterTypeOid);
689  if(arrayElementProperty)
690  arrayElementProperty->setElementType(p);
691  else
692  at->setElementType(p);
693  break;
694  }
695 
696  case PG_INT4_ARRAY_TYPE:
697  case PG_OID_ARRAY_TYPE:
698  case PG_OID_VECTOR_TYPE:
699  {
700  te::dt::Property* p = Convert2TerraLib(attNum, attName, PG_INT4_TYPE, attNotNull, fmt, attHasDefault, attDefValue, pgisGeomTypeOid, pgisRasterTypeOid);
701  if(arrayElementProperty)
702  arrayElementProperty->setElementType(p);
703  else
704  at->setElementType(p);
705  break;
706  }
707 
708  case PG_TEXT_ARRAY_TYPE:
709  {
710  te::dt::Property* p = Convert2TerraLib(attNum, attName, PG_TEXT_TYPE, attNotNull, fmt, attHasDefault, attDefValue, pgisGeomTypeOid, pgisRasterTypeOid);
711  if(arrayElementProperty)
712  arrayElementProperty->setElementType(p);
713  else
714  at->setElementType(p);
715  break;
716  }
717 
719  {
720  te::dt::Property* p = Convert2TerraLib(attNum, attName, PG_FLOAT4_TYPE, attNotNull, fmt, attHasDefault, attDefValue, pgisGeomTypeOid, pgisRasterTypeOid);
721  if(arrayElementProperty)
722  arrayElementProperty->setElementType(p);
723  else
724  at->setElementType(p);
725  break;
726  }
727 
729  {
730  te::dt::Property* p = Convert2TerraLib(attNum, attName, PG_FLOAT8_TYPE, attNotNull, fmt, attHasDefault, attDefValue, pgisGeomTypeOid, pgisRasterTypeOid);
731  if(arrayElementProperty)
732  arrayElementProperty->setElementType(p);
733  else
734  at->setElementType(p);
735  break;
736  }
737 
739  case PG_NAME_ARRAY_TYPE:
740  {
741  te::dt::Property* p = Convert2TerraLib(attNum, attName, PG_CHARACTER_TYPE, attNotNull, fmt, attHasDefault, attDefValue, pgisGeomTypeOid, pgisRasterTypeOid);
742  if(arrayElementProperty)
743  arrayElementProperty->setElementType(p);
744  else
745  at->setElementType(p);
746  break;
747  }
748 
750  {
751  te::dt::Property* p = Convert2TerraLib(attNum, attName, PG_VARCHAR_TYPE, attNotNull, fmt, attHasDefault, attDefValue, pgisGeomTypeOid, pgisRasterTypeOid);
752  if(arrayElementProperty)
753  arrayElementProperty->setElementType(p);
754  else
755  at->setElementType(p);
756  break;
757  }
758 
759  case PG_DATE_ARRAY_TYPE:
760  {
761  te::dt::Property* p = Convert2TerraLib(attNum, attName, PG_DATE_TYPE, attNotNull, fmt, attHasDefault, attDefValue, pgisGeomTypeOid, pgisRasterTypeOid);
762  if(arrayElementProperty)
763  arrayElementProperty->setElementType(p);
764  else
765  at->setElementType(p);
766  break;
767  }
768 
769  case PG_TIME_ARRAY_TYPE:
770  {
771  te::dt::Property* p = Convert2TerraLib(attNum, attName, PG_TIME_TYPE, attNotNull, fmt, attHasDefault, attDefValue, pgisGeomTypeOid, pgisRasterTypeOid);
772  if(arrayElementProperty)
773  arrayElementProperty->setElementType(p);
774  else
775  at->setElementType(p);
776  break;
777  }
778 
780  {
781  te::dt::Property* p = Convert2TerraLib(attNum, attName, PG_TIMETZ_TYPE, attNotNull, fmt, attHasDefault, attDefValue, pgisGeomTypeOid, pgisRasterTypeOid);
782  if(arrayElementProperty)
783  arrayElementProperty->setElementType(p);
784  else
785  at->setElementType(p);
786  break;
787  }
788 
790  {
791  te::dt::Property* p = Convert2TerraLib(attNum, attName, PG_TIMESTAMP_TYPE, attNotNull, fmt, attHasDefault, attDefValue, pgisGeomTypeOid, pgisRasterTypeOid);
792  if(arrayElementProperty)
793  arrayElementProperty->setElementType(p);
794  else
795  at->setElementType(p);
796  break;
797  }
798 
800  {
801  te::dt::Property* p = Convert2TerraLib(attNum, attName, PG_TIMESTAMPTZ_TYPE, attNotNull, fmt, attHasDefault, attDefValue, pgisGeomTypeOid, pgisRasterTypeOid);
802  if(arrayElementProperty)
803  arrayElementProperty->setElementType(p);
804  else
805  at->setElementType(p);
806  break;
807  }
808 
810  {
811  te::dt::Property* p = Convert2TerraLib(attNum, attName, PG_NUMERIC_TYPE, attNotNull, fmt, attHasDefault, attDefValue, pgisGeomTypeOid, pgisRasterTypeOid);
812  if(arrayElementProperty)
813  arrayElementProperty->setElementType(p);
814  else
815  at->setElementType(p);
816  break;
817  }
818 
819  default:
820  return Convert2TerraLib(attNum, attName, attType, attNotNull, fmt, attHasDefault, attDefValue, pgisGeomTypeOid, pgisRasterTypeOid);
821  }
822 
823  return at;
824  }
825 
826  /*!
827  \brief It converts the spatial relationship to PostGIS dialect.
828 
829  \param rel The spatial relationship.
830 
831  \return The PostGIS relationship name.
832  */
834  {
835  switch(rel)
836  {
837  case te::gm::INTERSECTS:
838  return "ST_Intersects";
839 
840  case te::gm::DISJOINT:
841  return "ST_Disjoint";
842 
843  case te::gm::TOUCHES:
844  return "ST_Touches";
845 
846  case te::gm::OVERLAPS:
847  return "ST_Overlaps";
848 
849  case te::gm::CROSSES:
850  return "ST_Crosses";
851 
852  case te::gm::WITHIN:
853  return "ST_Within";
854 
855  case te::gm::CONTAINS:
856  return "ST_Contains";
857 
858  case te::gm::COVERS:
859  return "ST_Covers";
860 
861  case te::gm::COVEREDBY:
862  return "ST_CoveredBy";
863 
864  case te::gm::EQUALS:
865  return "ST_Equals";
866 
867  default:
868  return "";
869  }
870  }
871 
872  /*!
873  \brief It converts the spatial relationship to PostGIS dialect.
874 
875  \param rel The spatial relationship.
876 
877  \return The PostGIS relationship name.
878  */
880  {
881  switch(rel)
882  {
883  case te::gm::INTERSECTS:
884  return " && ";
885 
886  case te::gm::OVERLAPS:
887  return " && ";
888 
889  case te::gm::WITHIN:
890  return " @ ";
891 
892  case te::gm::CONTAINS:
893  return " ~ ";
894 
895  case te::gm::COVERS:
896  return " ~ ";
897 
898  case te::gm::COVEREDBY:
899  return " @ ";
900 
901  case te::gm::EQUALS:
902  return " = ";
903 
904  default:
905  return "";
906  }
907  }
908 
909  /*!
910  \brief It creates a data set type from a PostGIS internal result.
911 
912  \param result A PostGIS internal result.
913  \param pgisGeomTypeOid The oid of PostGIS geometry type.
914 
915  \return The data set type created.
916  */
917  void Convert2TerraLib(PGresult* result,
918  unsigned int pgisGeomTypeOid,
919  unsigned int pgisRasterTypeOid,
920  std::vector<int>& teTypes);
921 
922  /*!
923  \brief It converts the PostGIS geometry type to a pure OGC WKB code.
924 
925  This function will turn off the PostGIS flags and will turn on
926  the right bits for OGC WKB type.
927 
928  \param gType A value that can have some flags set by PostGIS.
929  */
930  inline void Convert2OGCWKBType(unsigned int& gType)
931  {
932  if(gType & 0xF0000000) // Is PostGIS?
933  {
934  if((gType & TE_EWKB_ZM_OFFSET) == 0xC0000000) // z and m is on
935  {
936  gType = (gType & 0x0FFFFFFF) | 0xBB8;
937  }
938  else if(gType & TE_EWKB_Z_OFFSET)
939  {
940  gType = (gType & 0x0FFFFFFF) | 0x3E8;
941  }
942  else if(gType & TE_EWKB_M_OFFSET)
943  {
944  gType = (gType & 0x0FFFFFFF) | 0x7D0;
945  }
946  else
947  {
948  gType = (gType & 0x0FFFFFFF);
949  }
950  }
951  }
952 
953  std::string MakeConnectionStr(const te::core::URI& connInfo);
954 
955  void SplitTableName(const std::string& fullName,
956  const std::string* defaultSchema,
957  std::string& schemaName,
958  std::string& tableName);
959 
960  inline void Convert2PostGISWKBType(unsigned int& gType)
961  {
962  if((gType & 0xF00) == 0xB00) // it is zm
963  {
964  gType -= 3000;
965  gType |= TE_EWKB_ZM_OFFSET;
966  }
967  else if((gType & 0x0F00) == 0x300)
968  {
969  gType -= 1000;
970  gType |= TE_EWKB_Z_OFFSET;
971  }
972  else if((gType & 0xF00) == 0x700)
973  {
974  gType -= 2000;
975  gType |= TE_EWKB_M_OFFSET;
976  }
977  }
978 
979  /*!
980  \brief Given a list of properties it creates an AND connected expression with bindable parameters ($n).
981 
982  \param itBegin The start property.
983  \param itEnd The mark of end of properties.
984 
985  \return An AND connected expression with bindable parameters ($n) that can be used in WHERE expressions.
986  */
987  std::string GetBindableWhereSQL(const std::vector<te::dt::Property*>& properties, const std::size_t offset = 0);
988 
989  std::string GetSQLBindValues(std::size_t nproperties);
990 
991  /*!
992  \brief Given a list of properties it constructs a string with bindable parameters that can be used inside an update query.
993 
994  \param properties A vector with property names that will be used to create the expression.
995 
996  \return A comma (',') connected expression with bindable parameters ($1) that can be used in an UPDATE query.
997  */
998  std::string GetBindableUpdateSQL(const std::vector<te::dt::Property*>& properties);
999 
1000  std::string GetSQLValues(const te::da::DataSetType* dt, te::da::DataSet* d, PGconn *conn);
1001 
1002  std::string GetSQLValue(const te::dt::Property* p, std::size_t propertyPos, te::da::DataSet* d, PGconn *conn);
1003 
1004  std::string GetLoadDataRow(const te::da::DataSetType* dt, te::da::DataSet* d, PGconn *conn);
1005 
1006  } // end namespace pgis
1007 } // end namespace te
1008 
1009 #endif // __TERRALIB_POSTGIS_INTERNAL_UTILS_H
void setAutoNumber(bool a)
It tells if the property is an autonumber or not.
#define PG_CHAR_TYPE
Definition: Config.h:111
std::string MakeConnectionStr(const te::core::URI &connInfo)
Geometric property.
GeomType
Each enumerated type is compatible with a Well-known Binary (WKB) type code.
Definition: Enums.h:41
void SplitTableName(const std::string &fullName, const std::string *defaultSchema, std::string &schemaName, std::string &tableName)
#define PG_OID_ARRAY_TYPE
Definition: Config.h:138
void ScapeString(PGconn *conn, const std::string &s, std::string &output)
It escapes a string for use within an SQL command.
#define PG_TIME_ARRAY_TYPE
Definition: Config.h:145
An atomic property like an integer or double.
std::string GetBindableUpdateSQL(const std::vector< te::dt::Property * > &properties)
Given a list of properties it constructs a string with bindable parameters that can be used inside an...
#define PG_FLOAT8_TYPE
Definition: Config.h:120
te::dt::DateTime * Internal2TimeTZ(boost::int64_t tval, int z)
Definition: Utils.h:380
te::dt::DateTime * Internal2Date(const long dDate)
It returns a DateTime type from a date loaded by PostgreSQL.
Definition: Utils.h:346
A class that models the description of a dataset.
Definition: DataSetType.h:72
FKActionType
Type of action performed on the foreign key data.
Definition: Enums.h:93
#define PG_INT2_TYPE
Definition: Config.h:114
#define PG__INT2_VECTOR_TYPE
Definition: Config.h:135
#define PG_CHAR_ARRAY_TYPE
Definition: Config.h:131
struct pg_result PGresult
Definition: Connection.h:48
#define PG_BYTEA_ARRAY_TYPE
Definition: Config.h:130
te::dt::DateTime * Internal2TimeStampTZ(boost::int64_t ival, int z)
Definition: Utils.h:440
double m_urx
Upper right corner x-coordinate.
Definition: Envelope.h:346
SpatialRelation
Spatial relations between geometric objects.
Definition: Enums.h:127
#define PG_TEXT_TYPE
Definition: Config.h:117
te::dt::DateTime * Internal2TimeStamp(boost::int64_t ival)
It returns a DateTime type from a timestamp loaded by PostgreSQL.
Definition: Utils.h:416
#define PG_TEXT_ARRAY_TYPE
Definition: Config.h:137
te::gm::Envelope * GetEnvelope(const char *str)
It converts the pgType to a valid TerraLib data type.
Definition: Utils.h:172
#define PG_FLOAT4_ARRAY_TYPE
Definition: Config.h:140
#define PG_INT2_ARRAY_TYPE
Definition: Config.h:134
std::string GetLoadDataRow(const te::da::DataSetType *dt, te::da::DataSet *d, PGconn *conn)
#define PG_TIME_TYPE
Definition: Config.h:124
#define PG_TIMETZ_ARRAY_TYPE
Definition: Config.h:146
#define PG_TIMESTAMPTZ_ARRAY_TYPE
Definition: Config.h:148
It models a property definition.
Definition: Property.h:59
Raster property.
A class to represent time instant.
Definition: TimeInstant.h:55
std::string GetSQLValues(const te::da::DataSetType *dt, te::da::DataSet *d, PGconn *conn)
#define TE_EWKB_M_OFFSET
Definition: Config.h:160
#define PG_TIMESTAMP_TYPE
Definition: Config.h:126
#define PG_TIMETZ_TYPE
Definition: Config.h:125
int Date2Julian(int y, int m, const int d)
It returns a julian date (in seconds) from a gregorian date.
Definition: Utils.h:273
struct pg_conn PGconn
Definition: Connection.h:45
The type for arbitrary precison numbers, like numeric(p, q).
double m_llx
Lower left corner x-coordinate.
Definition: Envelope.h:344
bool SetColumnDef(std::string &s, const te::dt::Property *p, bool justDataType=false)
It writes the PostgreSQL column definition to the output string.
#define TE_EWKB_Z_OFFSET
Definition: Config.h:159
#define PG_INT8_TYPE
Definition: Config.h:113
const boost::gregorian::date & getDate() const
It returns the internal boost date type.
Definition: Date.h:83
An Envelope defines a 2D rectangular region.
Definition: Envelope.h:51
A base class for date data types.
Definition: Date.h:53
#define PG_BYTEA_TYPE
Definition: Config.h:110
Configuration flags for the PostGIS Driver Implementation of TerraLib.
void Convert2PostGIS(const te::gm::Envelope *e, int srid, std::string &output)
It converts the envelope into a PostGIS BOX3D.
Definition: Utils.h:228
URI C++ Library.
IndexType
Index type.
Definition: Enums.h:107
#define PG_NAME_ARRAY_TYPE
Definition: Config.h:132
#define PG_CHARACTER_ARRAY_TYPE
Definition: Config.h:142
const boost::local_time::local_date_time & getTimeInstantTZ() const
It returns the boost time instant with time zone type.
Definition: TimeInstantTZ.h:68
#define PG_CHARACTER_TYPE
Definition: Config.h:121
#define PG_NUMERIC_TYPE
Definition: Config.h:128
The type for string types: FIXED_STRING, VAR_STRING or STRING.
#define PG_FLOAT4_TYPE
Definition: Config.h:119
#define PG_INT8_ARRAY_TYPE
Definition: Config.h:133
#define TE_EWKB_ZM_OFFSET
Definition: Config.h:158
Geometry is the root class of the geometries hierarchy, it follows OGC and ISO standards.
Definition: Geometry.h:74
#define PG_DATE_TYPE
Definition: Config.h:123
#define PG_VARCHAR_ARRAY_TYPE
Definition: Config.h:143
#define PG_BOOL_TYPE
Definition: Config.h:109
double m_lly
Lower left corner y-coordinate.
Definition: Envelope.h:345
void setElementType(Property *t)
It sets the type of array elements.
A class for representing an Uniform Resource Identifier (URI).
Definition: URI.h:49
void Julian2Date(const int jd, int *year, int *month, int *day)
It returns a gregorian date from a julian date (in seconds).
Definition: Utils.h:307
const std::string & GetGeometryName(te::gm::GeomType t)
It returns the geometry names as usual for PostGIS.
A dataset is the unit of information manipulated by the data access module of TerraLib.
Definition: DataSet.h:112
The type for variable-length multidimensional arrays.
Definition: ArrayProperty.h:45
#define PG_INT2_VECTOR_TYPE
Definition: Config.h:115
double m_ury
Upper right corner y-coordinate.
Definition: Envelope.h:347
std::string GetSpatialRelation(te::gm::SpatialRelation rel)
It converts the spatial relationship to PostGIS dialect.
Definition: Utils.h:833
A class to represent time duration with nano-second/micro-second resolution.
Definition: TimeDuration.h:51
#define PG_DATE_ARRAY_TYPE
Definition: Config.h:144
void Convert2OGCWKBType(unsigned int &gType)
It converts the PostGIS geometry type to a pure OGC WKB code.
Definition: Utils.h:930
#define PG_NAME_TYPE
Definition: Config.h:112
The type for date and time types: date, date period, date duration, time duration, time instant, time period, time instant with time zone or time period with time zone.
te::dt::Property * Convert2TerraLib(unsigned int attNum, const char *attName, unsigned int attType, bool attNotNull, const char *fmt, bool attHasDefault, const char *attDefValue, unsigned int pgisGeomTypeOid, unsigned int pgisRasterTypeOid)
It creates a PropertyType from a PostgreSQL attribute description.
Definition: Utils.h:486
#define PG_INT4_ARRAY_TYPE
Definition: Config.h:136
#define PG_VARCHAR_TYPE
Definition: Config.h:122
#define PG_OID_VECTOR_TYPE
Definition: Config.h:139
std::string GetSQLValue(const te::dt::Property *p, std::size_t propertyPos, te::da::DataSet *d, PGconn *conn)
void Convert2PostGISWKBType(unsigned int &gType)
Definition: Utils.h:960
#define PG_NUMERIC_ARRAY_TYPE
Definition: Config.h:149
std::string GetBoxSpatialRelation(te::gm::SpatialRelation rel)
It converts the spatial relationship to PostGIS dialect.
Definition: Utils.h:879
te::da::IndexType GetIndexType(const char *t)
It converts the PostgreSQL index string to a TerraLib index type.
Definition: Utils.h:144
te::dt::DateTime * Internal2Time(boost::int64_t tval)
It returns a DateTime type from a time loaded by PostgreSQL.
Definition: Utils.h:365
te::da::FKActionType GetAction(char a)
It converts the PostgreSQL foreign key modifier to a TerraLib data type.
Definition: Utils.h:116
#define PG_TIMESTAMP_ARRAY_TYPE
Definition: Config.h:147
std::string Convert2String(boost::int16_t value)
It converts a short integer value to a string.
Definition: StringUtils.h:56
#define PG_OID_TYPE
Definition: Config.h:118
#define PG_FLOAT8_ARRAY_TYPE
Definition: Config.h:141
A class to represent time instant with time zone.
Definition: TimeInstantTZ.h:52
#define PG_BOOL_ARRAY_TYPE
Definition: Config.h:129
std::string GetSQLBindValues(std::size_t nproperties)
#define PG_TIMESTAMPTZ_TYPE
Definition: Config.h:127
#define PG_INT4_TYPE
Definition: Config.h:116
std::string GetBindableWhereSQL(const std::vector< te::dt::Property * > &properties, const std::size_t offset=0)
Given a list of properties it creates an AND connected expression with bindable parameters ($n)...