All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DataSource.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2008-2013 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 byF
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/DataSource.cpp
22 
23  \brief Implementation of the data source for the PostGIS driver.
24 */
25 
26 // TerraLib
27 #include "../common/StringUtils.h"
28 #include "../common/Translator.h"
29 #include "../dataaccess/dataset/CheckConstraint.h"
30 #include "../dataaccess/dataset/DataSet.h"
31 #include "../dataaccess/dataset/ForeignKey.h"
32 #include "../dataaccess/dataset/Index.h"
33 #include "../dataaccess/dataset/PrimaryKey.h"
34 #include "../dataaccess/dataset/Sequence.h"
35 #include "../dataaccess/dataset/UniqueKey.h"
36 #include "../dataaccess/datasource/ScopedTransaction.h"
37 #include "../dataaccess/query/Select.h"
38 #include "../dataaccess/query/SQLDialect.h"
39 #include "../dataaccess/utils/Utils.h"
40 #include "../datatype/Array.h"
41 #include "../datatype/Property.h"
42 #include "../datatype/SimpleData.h"
43 #include "../geometry/GeometryProperty.h"
44 #include "../geometry/Utils.h"
45 #include "../raster/Grid.h"
46 #include "../raster/BandProperty.h"
47 #include "../raster/RasterProperty.h"
48 #include "../geometry/Geometry.h"
49 #include "Connection.h"
50 #include "ConnectionPool.h"
51 #include "DataSource.h"
52 #include "DataSet.h"
53 #include "Exception.h"
54 #include "Globals.h"
55 #include "PreparedQuery.h"
56 #include "SQLVisitor.h"
57 #include "Transactor.h"
58 #include "Utils.h"
59 
60 // STL
61 #include <cassert>
62 //#include <cstring>
63 #include <memory>
64 
65 // Boost
66 //#include <boost/algorithm/string/case_conv.hpp>
67 #include <boost/format.hpp>
68 //#include <boost/lexical_cast.hpp>
69 //#include <boost/thread.hpp>
70 
71 // libpq
72 #include <libpq-fe.h>
73 
75  : m_pool(0),
76  m_geomTypeOid(0),
77  m_rasterTypeOid(0),
78  m_timeIsInteger(true)
79 {
80  m_pool = new ConnectionPool(this);
81 }
82 
84 {
85  delete m_pool;
86 }
87 
88 std::string te::pgis::DataSource::getType() const
89 {
91 }
92 
93 const std::map<std::string, std::string>& te::pgis::DataSource::getConnectionInfo() const
94 {
95  return m_connInfo;
96 }
97 
98 void te::pgis::DataSource::setConnectionInfo(const std::map<std::string, std::string>& connInfo)
99 {
100  m_connInfo = connInfo;
101 }
102 
103 std::auto_ptr<te::da::DataSourceTransactor> te::pgis::DataSource::getTransactor()
104 {
105  Connection* conn = m_pool->getConnection();
106 
107  return std::auto_ptr<te::da::DataSourceTransactor>(new te::pgis::Transactor(this, conn));
108 }
109 
111 {
112  return m_pool->getConnection();
113 }
114 
116 {
117  m_pool->release(conn);
118 }
119 
121 {
122  return m_timeIsInteger;
123 }
124 
126 {
127  m_timeIsInteger = timeIsInteger;
128 }
129 
131 {
132  // Assure we are in a closed state
133  close();
134 
135  m_pool->initialize();
136 
137  std::auto_ptr<te::da::DataSourceTransactor> t = getTransactor();
138  te::pgis::Transactor* pgt = static_cast<te::pgis::Transactor*>(t.get());
139 
140  // Find the PostGIS types
141  m_geomTypeOid = pgt->getGeomTypeId();
142  m_rasterTypeOid = pgt->getRasterTypeId();
143 
144  // Find the PostgreSQL current schema of the connection
145  pgt->getDatabaseInfo(m_currentSchema);
146 }
147 
149 {
150  m_pool->finalize();
151 }
152 
154 {
155  return m_pool->isInitialized();
156 }
157 
159 {
160  return m_pool->isValid();
161 }
162 
164 {
166 }
167 
169 {
171 }
172 
174 {
175  return m_geomTypeOid;
176 }
177 
179 {
180  return m_rasterTypeOid;
181 }
182 
183 const std::string& te::pgis::DataSource::getCurrentSchema() const
184 {
185  return m_currentSchema;
186 }
187 
189 {
190  return m_pool;
191 }
192 
193 void te::pgis::DataSource::create(const std::map<std::string, std::string>& dsInfo)
194 {
195  // Get an auxiliary data source
196  std::auto_ptr<DataSource> ds(new DataSource());
197 
198  ds->setConnectionInfo(dsInfo);
199 
200  ds->open();
201 
202  // Create a database based on the connection information
203  std::string sql = "CREATE DATABASE ";
204 
205  std::map<std::string, std::string>::const_iterator it = dsInfo.find("PG_NEWDB_NAME");
206  std::map<std::string, std::string>::const_iterator it_end = dsInfo.end();
207 
208  if(it != it_end)
209  sql += it->second;
210  else
211  throw Exception(TR_PGIS("The database could not be created due the missing parameter: PG_NEWDB_NAME!"));
212 
213  it = dsInfo.find("PG_NEWDB_TEMPLATE");
214 
215  if(it != it_end)
216  sql += " TEMPLATE = " + it->second;
217 
218  it = dsInfo.find("PG_NEWDB_OWNER");
219 
220  if(it != it_end)
221  sql += " OWNER = " + it->second;
222 
223  it = dsInfo.find("PG_NEWDB_ENCODING");
224 
225  if(it != it_end)
226  sql += " ENCODING = " + it->second;
227 
228  it = dsInfo.find("PG_NEWDB_TABLESPACE");
229 
230  if(it != it_end)
231  sql += " TABLESPACE = " + it->second;
232 
233  it = dsInfo.find("PG_NEWDB_CONN_LIMIT");
234 
235  if(it != it_end)
236  sql += " CONNECTION LIMIT = " + it->second;
237 
238  ds->execute(sql);
239 
240  ds->close();
241 
242  // Copy the database connection parameters to this new data source object.
243  it = dsInfo.find("PG_NEWDB_HOST");
244 
245  if(it == it_end)
246  it = dsInfo.find("PG_HOST");
247 
248  if(it != it_end)
249  m_connInfo["PG_HOST"] = it->second;
250 
251  it = dsInfo.find("PG_NEWDB_HOSTADDR");
252 
253  if(it == it_end)
254  it = dsInfo.find("PG_HOST_ADDR");
255 
256  if(it != it_end)
257  m_connInfo["PG_HOST_ADDR"] = it->second;
258 
259  it = dsInfo.find("PG_NEWDB_PORT");
260 
261  if(it == it_end)
262  it = dsInfo.find("PG_PORT");
263 
264  if(it != it_end)
265  m_connInfo["PG_PORT"] = it->second;
266 
267  it = dsInfo.find("PG_NEWDB_NAME");
268 
269  if(it != it_end)
270  m_connInfo["PG_DB_NAME"] = it->second;
271 
272  it = dsInfo.find("PG_NEWDB_USER");
273 
274  if(it == it_end)
275  it = dsInfo.find("PG_USER");
276 
277  if(it != it_end)
278  m_connInfo["PG_USER"] = it->second;
279 
280  it = dsInfo.find("PG_NEWDB_PASSWORD");
281 
282  if(it == it_end)
283  it = dsInfo.find("PG_PASSWORD");
284 
285  if(it != it_end)
286  m_connInfo["PG_PASSWORD"] = it->second;
287 
288  it = dsInfo.find("PG_NEWDB_CONNECT_TIMEOUT");
289 
290  if(it == it_end)
291  it = dsInfo.find("PG_CONNECT_TIMEOUT");
292 
293  if(it != it_end)
294  m_connInfo["PG_CONNECT_TIMEOUT"] = it->second;
295 
296  it = dsInfo.find("PG_NEWDB_OPTIONS");
297 
298  if(it == it_end)
299  it = dsInfo.find("PG_OPTIONS");
300 
301  if(it != it_end)
302  m_connInfo["PG_OPTIONS"] = it->second;
303 
304  it = dsInfo.find("PG_NEWDB_SSL_MODE");
305 
306  if(it == it_end)
307  it = dsInfo.find("PG_SSL_MODE");
308 
309  if(it != it_end)
310  m_connInfo["PG_SSL_MODE"] = it->second;
311 
312  it = dsInfo.find("PG_NEWDB_KRBSRVNAME");
313 
314  if(it == it_end)
315  it = dsInfo.find("PG_KRBSRVNAME");
316 
317  if(it != it_end)
318  m_connInfo["PG_KRBSRVNAME"] = it->second;
319 
320  it = dsInfo.find("PG_NEWDB_GSSLIB");
321 
322  if(it == it_end)
323  it = dsInfo.find("PG_GSSLIB");
324 
325  if(it != it_end)
326  m_connInfo["PG_GSSLIB"] = it->second;
327 
328  it = dsInfo.find("PG_NEWDB_INITIAL_POOL_SIZE");
329 
330  if(it == it_end)
331  it = dsInfo.find("PG_INITIAL_POOL_SIZE");
332 
333  if(it != it_end)
334  m_connInfo["PG_INITIAL_POOL_SIZE"] = it->second;
335 
336  it = dsInfo.find("PG_NEWDB_MIN_POOL_SIZE");
337 
338  if(it == it_end)
339  it = dsInfo.find("PG_MIN_POOL_SIZE");
340 
341  if(it != it_end)
342  m_connInfo["PG_MIN_POOL_SIZE"] = it->second;
343 
344  it = dsInfo.find("PG_NEW_DB_MAX_POOL_SIZE");
345 
346  if(it == it_end)
347  it = dsInfo.find("PG_MAX_POOL_SIZE");
348 
349  if(it != it_end)
350  m_connInfo["PG_MAX_POOL_SIZE"] = it->second;
351 
352  it = dsInfo.find("PG_NEWDB_MAX_IDLE_TIME");
353 
354  if(it == it_end)
355  it = dsInfo.find("PG_MAX_IDLE_TIME");
356 
357  if(it != it_end)
358  m_connInfo["PG_MAX_IDLE_TIME"] = it->second;
359 
360  it = dsInfo.find("PG_NEWDB_CLIENT_ENCODING");
361 
362  if(it == it_end)
363  it = dsInfo.find("PG_CLIENT_ENCODING");
364 
365  if(it != it_end)
366  m_connInfo["PG_CLIENT_ENCODING"] = it->second;
367 }
368 
369 void te::pgis::DataSource::drop(const std::map<std::string, std::string>& dsInfo)
370 {
371  // Get an auxiliary data source
372  std::auto_ptr<DataSource> ds(new DataSource());
373 
374  ds->setConnectionInfo(dsInfo);
375 
376  ds->open();
377 
378  // Drop the database
379  std::string sql = "DROP DATABASE ";
380 
381  std::map<std::string, std::string>::const_iterator it = dsInfo.find("PG_DB_TO_DROP");
382 
383  if(it == dsInfo.end())
384  throw Exception(TR_PGIS("Could not drop the database due the missing parameter: PG_DB_TO_DROP!"));
385 
386  if((it->second == "postgres") || (it->second == "template_postgis"))
387  throw Exception(TR_PGIS("The database postgres or template_postgis is not allowed to be dropped!"));
388 
389  sql += it->second;
390 
391  ds->execute(sql);
392 
393  ds->close();
394 }
395 
396 bool te::pgis::DataSource::exists(const std::map<std::string, std::string>& dsInfo)
397 {
398  if(dsInfo.count("PG_CHECK_DB_EXISTENCE") == 0)
399  throw Exception(TR_PGIS("Could not check the PostgreSQL database existence due the missing parameter: PG_CHECK_DB_EXISTENCE!"));
400 
401  const std::string& dbName = dsInfo.find("PG_CHECK_DB_EXISTENCE")->second;
402 
403  // Get an auxiliary data source
404  std::auto_ptr<DataSource> ds(new DataSource());
405 
406  ds->setConnectionInfo(dsInfo);
407 
408  ds->open();
409 
410  std::string sql("SELECT * FROM pg_database WHERE datname = '");
411  sql += dbName;
412  sql += "'";
413 
414  std::auto_ptr<te::da::DataSet> database(ds->query(sql));
415 
416  ds->close();
417 
418  return database->moveNext();
419 }
420 
421 std::vector<std::string> te::pgis::DataSource::getDataSourceNames(const std::map<std::string, std::string>& dsInfo)
422 {
423  // Get an auxiliary data source
424  std::auto_ptr<DataSource> ds(new DataSource());
425 
426  ds->setConnectionInfo(dsInfo);
427 
428  ds->open();
429 
430  std::string sql("SELECT datname FROM pg_database");
431 
432  std::auto_ptr<te::da::DataSet> dataset(ds->query(sql));
433 
434  std::vector<std::string> dataSourceNames;
435 
436  while(dataset->moveNext())
437  dataSourceNames.push_back(dataset->getString(0));
438 
439  ds->close();
440 
441  return dataSourceNames;
442 }
443 
444 
445 std::vector<std::string> te::pgis::DataSource::getEncodings(const std::map<std::string, std::string>& dsInfo)
446 {
447  std::vector<std::string> encodings;
448 
449  // Get an auxiliary data source
450  std::auto_ptr<DataSource> ds(new DataSource());
451 
452  ds->setConnectionInfo(dsInfo);
453 
454  ds->open();
455 
456  std::string sql("SELECT DISTINCT pg_catalog.pg_encoding_to_char(conforencoding) FROM pg_catalog.pg_conversion ORDER BY pg_catalog.pg_encoding_to_char(conforencoding)");
457 
458  std::auto_ptr<te::da::DataSet> encs(ds->query(sql));
459 
460  while(encs->moveNext())
461  encodings.push_back(encs->getString(0));
462 
463  ds->close();
464 
465  return encodings;
466 }
unsigned int getGeomTypeId() const
It returns the type id associated to the PostGIS Geometry type.
Definition: DataSource.cpp:173
A class that implements a prepared query for PostgreSQL data access driver.
unsigned int getRasterTypeId()
It will check in the database catalog the number that identifies the PostGIS Raster type...
#define PGIS_DRIVER_IDENTIFIER
The PostGIS driver identifier string.
Definition: Config.h:90
const std::map< std::string, std::string > & getConnectionInfo() const
It returns the set of parameters used to set up the access channel to the underlying repository...
Definition: DataSource.cpp:93
An static class with global definitions.
bool isOpened() const
It returns true if the data source is opened, otherwise it returns false.
Definition: DataSource.cpp:153
const std::string & getCurrentSchema() const
It returns the current schema associated to the database connection, or NULL, if none is set...
Definition: DataSource.cpp:183
void create(const std::map< std::string, std::string > &dsInfo)
It creates a new data source.
Definition: DataSource.cpp:193
void closeConnection(Connection *conn)
Definition: DataSource.cpp:115
A class that implements a connection pool for PostGIS.
void close()
It closes the data source and clears all the resources used by its internal communication channel...
Definition: DataSource.cpp:148
std::string getType() const
It returns the data source type name (in UPPER CASE). Ex: POSTGIS, SQLITE, WFS, WMS, or MYSQL.
Definition: DataSource.cpp:88
This class implements a connection pool for the PostGIS driver.
void drop(const std::map< std::string, std::string > &dsInfo)
It removes the data source with the connection information from a driver.
Definition: DataSource.cpp:369
te::pgis::Connection * getConnection()
Definition: DataSource.cpp:110
void open()
It opens the connection(s) to the PostgreSQL database server.
Definition: DataSource.cpp:130
const te::da::SQLDialect * getDialect() const
It returns the data source SQL dialect, if there is one.
Definition: DataSource.cpp:168
A class that represents the known capabilities of a specific data source, i.e. this class informs all...
bool exists(const std::map< std::string, std::string > &dsInfo)
Check the existence of a data source in a driver.
Definition: DataSource.cpp:396
void setTimeAsInteger(bool timeIsInteger)
Definition: DataSource.cpp:125
An exception class for the PostGIS driver.
ConnectionPool * getConnPool() const
It returns a pointer to the internal connection pool.
Definition: DataSource.cpp:188
#define TR_PGIS(message)
It marks a string in order to get translated. This is a special mark used in the DataAccess module of...
Definition: Config.h:168
bool isValid() const
It checks if the data source is valid (available for using).
Definition: DataSource.cpp:158
It represents the SQL query dialect accepted by a given data source.
Definition: SQLDialect.h:55
void setConnectionInfo(const std::map< std::string, std::string > &connInfo)
It sets the connection information to be used when connecting to the data source. ...
Definition: DataSource.cpp:98
Utility functions for the data access module.
std::vector< std::string > getEncodings(const std::map< std::string, std::string > &dsInfo)
It gets the encodings for the data source.
Definition: DataSource.cpp:445
A visitor for building an SQL statement using PostGIS dialect.
static te::da::DataSourceCapabilities * sm_capabilities
The query dialect supported by PostGIS driver.
Definition: Globals.h:95
unsigned int getGeomTypeId()
It will check in the database catalog the number that identifies the PostGIS Geometry type...
The PostGIS driver.
Definition: DataSource.h:54
A class that implements a connection to a PostgreSQL database.
A class that implements a connection to a PostgreSQL database.
Definition: Connection.h:68
A Transactor can be viewed as a connection to the data source for reading/writing things into it...
The transactor class for the PostGIS driver.
Definition: Transactor.h:62
std::vector< std::string > getDataSourceNames(const std::map< std::string, std::string > &dsInfo)
It gets the data source names available in a driver.
Definition: DataSource.cpp:421
unsigned int getRasterTypeId() const
It returns the type id associated to the PostGIS Raster type.
Definition: DataSource.cpp:178
ConnectionPool * m_pool
The connection pool.
Definition: DataSource.h:165
std::auto_ptr< te::da::DataSourceTransactor > getTransactor()
It returns an object that can execute transactions in the context of a data source.
Definition: DataSource.cpp:103
A dataset is the unit of information manipulated by the data access module of TerraLib.
const te::da::DataSourceCapabilities & getCapabilities() const
It returns the known capabilities of the data source.
Definition: DataSource.cpp:163
static te::da::SQLDialect * sm_queryDialect
The query dialect supported by PostGIS driver.
Definition: Globals.h:94
~DataSource()
Virtual destructor.
Definition: DataSource.cpp:83
void getDatabaseInfo(std::string &currentSchema)
It retrieves some information about the database such as the default schema used when no one is provi...
Implementation of the data source for the PostGIS driver.