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