All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
DataSource.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2008 National Institute For Space Research (INPE) - Brazil.
2 
3  This file is part of the TerraLib - a Framework for building GIS enabled applications.
4 
5  TerraLib is free software: you can redistribute it and/or modify
6  it under the terms of the GNU Lesser General Public License as published by
7  the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  TerraLib is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public License
16  along with TerraLib. See COPYING. If not, write to
17  TerraLib Team at <terralib-team@terralib.org>.
18  */
19 
20 /*!
21  \file terralib/sqlite/DataSource.cpp
22 
23  \brief Implements the DataSource class for the SQLite Data Access Driver.
24 */
25 
26 // TerraLib
27 #include "../common/Translator.h"
28 #include "../dataaccess/datasource/DataSourceCapabilities.h"
29 #include "../dataaccess/query/SQLDialect.h"
30 #include "../dataaccess/Exception.h"
31 #include "Config.h"
32 #include "DataSource.h"
33 #include "DataSourceTransactor.h"
34 #include "Utils.h"
35 
36 // STL
37 #include <cassert>
38 
39 // Boost
40 #include <boost/algorithm/string/case_conv.hpp>
41 #include <boost/filesystem.hpp>
42 #include <boost/format.hpp>
43 
44 // SQLite
45 #include <sqlite3.h>
46 
48 {
49  public:
50 
51  Impl()
52  : m_db(0)
53  {
54  }
55 
57  {
58  int ret = SQLITE_OK;
59  ret = sqlite3_close(m_db);
60  assert(ret == SQLITE_OK);
61  }
62 
63  std::map<std::string, std::string> m_connInfo;
65 
68 };
69 
72 
74  : m_pImpl(0)
75 {
76  m_pImpl = new Impl;
77 }
78 
80 {
81  delete m_pImpl;
82 }
83 
85 {
87 }
88 
89 const std::map<std::string, std::string>& te::sqlite::DataSource::getConnectionInfo() const
90 {
91  return m_pImpl->m_connInfo;
92 }
93 
94 void te::sqlite::DataSource::setConnectionInfo(const std::map<std::string, std::string>& connInfo)
95 {
96  m_pImpl->m_connInfo = connInfo;
97 }
98 
99 std::auto_ptr<te::da::DataSourceTransactor> te::sqlite::DataSource::getTransactor()
100 {
101  std::auto_ptr<te::da::DataSourceTransactor> t(new DataSourceTransactor(this, m_pImpl->m_db));
102  return t;
103 }
104 
106 {
107  close();
108 
109  int flags = GetConnectionFlags(m_pImpl->m_connInfo);
110 
111  if(flags == 0)
112  flags = SQLITE_OPEN_READONLY;
113 
114  std::string fileName;
115 
116  {
117  std::map<std::string, std::string>::const_iterator it = m_pImpl->m_connInfo.find("SQLITE_FILE");
118 
119  if(it != m_pImpl->m_connInfo.end())
120  fileName = it->second;
121  }
122 
123  std::string vfs;
124 
125  {
126  std::map<std::string, std::string>::const_iterator it = m_pImpl->m_connInfo.find("SQLITE_VFS");
127 
128  if(it != m_pImpl->m_connInfo.end())
129  vfs = it->second;
130  }
131 
132  int ret = sqlite3_open_v2(fileName.c_str(), &(m_pImpl->m_db), flags, vfs.empty() ? 0 : vfs.c_str());
133 
134  if(ret != SQLITE_OK)
135  {
136  boost::format errmsg(TR_COMMON("Could not open the SQLite data source due to the following error: %1%."));
137 
138  if(m_pImpl->m_db)
139  errmsg = errmsg % sqlite3_errmsg(m_pImpl->m_db);
140  else
141  errmsg = errmsg % "unknown error";
142 
143  sqlite3_close(m_pImpl->m_db);
144 
145  m_pImpl->m_db = 0;
146 
147  throw te::da::Exception(errmsg.str());
148  }
149 
150  std::auto_ptr<te::da::DataSourceTransactor> transactor(getTransactor());
151 
152  std::auto_ptr<te::da::DataSet> result(transactor->query("SELECT CheckSpatialMetaData()"));
153 
154  if(!result->moveNext())
155  throw te::da::Exception(TR_COMMON("Could not check if SQLite database has spatial metadata tables due to unexpected error!"));
156 
157  int spatialMetaTableType = result->getInt32(0);
158 
159  if(spatialMetaTableType == 0)
160  transactor->execute("SELECT InitSpatialMetadata(1)");
161 }
162 
164 {
165  if(m_pImpl->m_db == 0)
166  return;
167 
168  int ret = sqlite3_close(m_pImpl->m_db);
169 
170  if(ret != SQLITE_OK)
171  {
172  boost::format errmsg(TR_COMMON("Could not close the SQLite data source due to the following error: %1%."));
173 
174  if(m_pImpl->m_db)
175  errmsg = errmsg % sqlite3_errmsg(m_pImpl->m_db);
176  else
177  errmsg = errmsg % "unknown error";
178 
179  throw te::da::Exception(errmsg.str());
180  }
181 
182  m_pImpl->m_db = 0;
183 }
184 
186 {
187  return m_pImpl->m_db != 0;
188 }
189 
191 {
192  return m_pImpl->m_db != 0;
193 }
194 
196 {
197  return *Impl::sm_capabilities;
198 }
199 
201 {
202  return Impl::sm_dialect;
203 }
204 
206 {
207  delete Impl::sm_capabilities;
208  Impl::sm_capabilities = capabilities;
209 }
210 
212 {
213  delete Impl::sm_dialect;
214  Impl::sm_dialect = dialect;
215 }
216 
217 void te::sqlite::DataSource::create(const std::map<std::string, std::string>& dsInfo)
218 {
219  if(Exists(dsInfo))
220  throw te::da::Exception(TR_COMMON("The informed SQLite database already exists!"));
221 
222  {
223  std::map<std::string, std::string>::const_iterator it = dsInfo.find("SQLITE_CREATE_INTERMEDIATE_DIR");
224 
225  if((it != dsInfo.end()) && (boost::to_upper_copy(it->second) == "TRUE"))
226  {
227  it = dsInfo.find("SQLITE_FILE");
228 
229  if(it == dsInfo.end())
230  throw te::da::Exception(TR_COMMON("You must at least provide a database file name if you want to create its intermediate directories!"));
231 
232  boost::filesystem::path fileName(it->second);
233 
234  if(fileName.has_parent_path() &&
235  !boost::filesystem::exists(fileName.parent_path()) &&
236  !boost::filesystem::create_directories(fileName.parent_path()))
237  throw te::da::Exception(TR_COMMON("Could not create directory for SQLite database!"));
238  }
239  }
240 
241  std::map<std::string, std::string> info = dsInfo;
242 
243  info["SQLITE_OPEN_READWRITE"] = "true";
244  info["SQLITE_OPEN_CREATE"] = "true";
245 
246  setConnectionInfo(info);
247  open();
248  close();
249 }
250 
251 void te::sqlite::DataSource::drop(const std::map<std::string, std::string>& dsInfo)
252 {
253  if(!Exists(dsInfo))
254  throw te::da::Exception(TR_COMMON("The informed SQLite database doesn't exist!"));
255 
256  if((dsInfo.find("SQLITE_OPEN_URI") != dsInfo.end()) &&
257  (boost::to_upper_copy(m_pImpl->m_connInfo.find("SQLITE_OPEN_URI")->second) == "TRUE"))
258  throw te::da::Exception(TR_COMMON("Sorry! We don't support removing SQLite database through an URI!"));
259 
260  std::string fileName;
261 
262  {
263  std::map<std::string, std::string>::const_iterator it = dsInfo.find("SQLITE_FILE");
264 
265  if(it != dsInfo.end())
266  fileName = it->second;
267  else
268  throw te::da::Exception(TR_COMMON("To remove an SQLite database you must inform its file name!"));
269  }
270 
271  boost::filesystem::remove(fileName);
272 }
273 
274 bool te::sqlite::DataSource::exists(const std::map<std::string, std::string>& dsInfo)
275 {
276  std::string fileName;
277 
278  std::map<std::string, std::string>::const_iterator it = dsInfo.find("SQLITE_FILE");
279 
280  if(it == dsInfo.end())
281  throw te::da::Exception(TR_COMMON("In order to check the existence of a SQLite database you must inform its file name"));
282 
283  return boost::filesystem::exists(it->second);
284 }
285 
286 std::vector<std::string> te::sqlite::DataSource::getDataSourceNames(const std::map<std::string, std::string>& dsInfo)
287 {
288  return std::vector<std::string>();
289 }
290 
291 std::vector<std::string> te::sqlite::DataSource::getEncodings(const std::map<std::string, std::string>& dsInfo)
292 {
293  std::vector<std::string> encodings;
294  encodings.push_back("UTF-8");
295  return encodings;
296 }
297 
bool isOpened() const
It returns true if the data source is opened, otherwise it returns false.
Definition: DataSource.cpp:185
Configuration flags for the SQLite Data Access driver.
~DataSource()
Virtual destructor.
Definition: DataSource.cpp:79
te::da::SQLDialect * dialect
Definition: WFSDialect.h:1
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:251
struct sqlite3 sqlite3
bool isValid() const
It checks if the data source is valid (available for using).
Definition: DataSource.cpp:190
const te::da::DataSourceCapabilities & getCapabilities() const
It returns the known capabilities of the data source.
Definition: DataSource.cpp:195
It represents the SQL query dialect accepted by a given data source.
Definition: SQLDialect.h:55
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:286
void create(const std::map< std::string, std::string > &dsInfo)
It creates a new data source.
Definition: DataSource.cpp:217
A class that represents the known capabilities of a specific data source, i.e. this class informs all...
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:99
static te::da::SQLDialect * sm_dialect
Definition: DataSource.cpp:66
static void set(te::da::DataSourceCapabilities *capabilities)
Definition: DataSource.cpp:205
te::da::DataSourceCapabilities capabilities
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:94
Utility functions for the TerraLib SQLite Data Access driver.
void open()
It opens the data source and makes it ready for using.
Definition: DataSource.cpp:105
static te::da::DataSourceCapabilities * sm_capabilities
Definition: DataSource.cpp:67
std::string getType() const
It returns the data source type name (in UPPER CASE). Ex: POSTGIS, SQLITE, WFS, WMS, or MYSQL.
Definition: DataSource.cpp:84
const te::da::SQLDialect * getDialect() const
It returns the data source SQL dialect, if there is one.
Definition: DataSource.cpp:200
bool exists(const std::map< std::string, std::string > &dsInfo)
Check the existence of a data source in a driver.
Definition: DataSource.cpp:274
Implements the DataSource class for the SQLite Data Access Driver.
An implementation of DataSourceTransactor class for the TerraLib SQLite Data Access Driver...
std::map< std::string, std::string > m_connInfo
Definition: DataSource.cpp:63
bool Exists(const std::map< std::string, std::string > &dbInfo)
Definition: Utils.cpp:101
#define TE_SQLITE_DRIVER_IDENTIFIER
The SQLite driver identifier string.
Definition: Config.h:33
void close()
It closes the data source and clears all the resources used by its internal communication channel...
Definition: DataSource.cpp:163
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:89
std::vector< std::string > getEncodings(const std::map< std::string, std::string > &dsInfo)
It gets the encodings for the data source.
Definition: DataSource.cpp:291
int GetConnectionFlags(const std::map< std::string, std::string > &connInfo)
Definition: Utils.cpp:63