attic/src/sqlite/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 "../core/filesystem/FileSystem.h"
28 #include "../core/translator/Translator.h"
29 #include "../dataaccess/datasource/DataSourceCapabilities.h"
30 #include "../dataaccess/query/SQLDialect.h"
31 #include "../dataaccess/Exception.h"
32 #include "Config.h"
33 #include "DataSource.h"
34 #include "DataSourceTransactor.h"
35 #include "Utils.h"
36 
37 // STL
38 #include <cassert>
39 
40 // Boost
41 #include <boost/algorithm/string/case_conv.hpp>
42 #include <boost/filesystem.hpp>
43 #include <boost/format.hpp>
44 
45 // SQLite
46 #include <sqlite3.h>
47 
49 {
50  public:
51 
52  Impl()
53  : m_db(0)
54  {
55  }
56 
58  {
59  int ret = SQLITE_OK;
60  ret = sqlite3_close(m_db);
61  assert(ret == SQLITE_OK);
62  }
63 
64  std::map<std::string, std::string> m_connInfo;
66 
69 };
70 
73 
75  : m_pImpl(0)
76 {
77  m_pImpl = new Impl;
78 }
79 
81 {
82  delete m_pImpl;
83 }
84 
86 {
88 }
89 
90 const std::map<std::string, std::string>& te::sqlite::DataSource::getConnectionInfo() const
91 {
92  return m_pImpl->m_connInfo;
93 }
94 
95 void te::sqlite::DataSource::setConnectionInfo(const std::map<std::string, std::string>& connInfo)
96 {
97  m_pImpl->m_connInfo = connInfo;
98 }
99 
100 std::auto_ptr<te::da::DataSourceTransactor> te::sqlite::DataSource::getTransactor()
101 {
102  std::auto_ptr<te::da::DataSourceTransactor> t(new DataSourceTransactor(this, m_pImpl->m_db));
103  return t;
104 }
105 
107 {
108  close();
109 
110  int flags = GetConnectionFlags(m_pImpl->m_connInfo);
111 
112  if(flags == 0)
113  flags = SQLITE_OPEN_READONLY;
114 
115  std::string fileName;
116 
117  {
118  std::map<std::string, std::string>::const_iterator it = m_pImpl->m_connInfo.find("SQLITE_FILE");
119 
120  if(it != m_pImpl->m_connInfo.end())
121  fileName = it->second;
122  }
123 
124  std::string vfs;
125 
126  {
127  std::map<std::string, std::string>::const_iterator it = m_pImpl->m_connInfo.find("SQLITE_VFS");
128 
129  if(it != m_pImpl->m_connInfo.end())
130  vfs = it->second;
131  }
132 
133  int ret = sqlite3_open_v2(fileName.c_str(), &(m_pImpl->m_db), flags, vfs.empty() ? 0 : vfs.c_str());
134 
135  if(ret != SQLITE_OK)
136  {
137  boost::format errmsg(TR_COMMON("Could not open the SQLite data source due to the following error: %1%."));
138 
139  if(m_pImpl->m_db)
140  errmsg = errmsg % sqlite3_errmsg(m_pImpl->m_db);
141  else
142  errmsg = errmsg % "unknown error";
143 
144  sqlite3_close(m_pImpl->m_db);
145 
146  m_pImpl->m_db = 0;
147 
148  throw te::da::Exception(errmsg.str());
149  }
150 
151  std::auto_ptr<te::da::DataSourceTransactor> transactor(getTransactor());
152 
153  std::auto_ptr<te::da::DataSet> result(transactor->query("SELECT CheckSpatialMetaData()"));
154 
155  if(!result->moveNext())
156  throw te::da::Exception(TR_COMMON("Could not check if SQLite database has spatial metadata tables due to unexpected error!"));
157 
158  int spatialMetaTableType = result->getInt32(0);
159 
160  if(spatialMetaTableType == 0)
161  transactor->execute("SELECT InitSpatialMetadata(1)");
162 }
163 
165 {
166  if(m_pImpl->m_db == 0)
167  return;
168 
169  int ret = sqlite3_close(m_pImpl->m_db);
170 
171  if(ret != SQLITE_OK)
172  {
173  boost::format errmsg(TR_COMMON("Could not close the SQLite data source due to the following error: %1%."));
174 
175  if(m_pImpl->m_db)
176  errmsg = errmsg % sqlite3_errmsg(m_pImpl->m_db);
177  else
178  errmsg = errmsg % "unknown error";
179 
180  throw te::da::Exception(errmsg.str());
181  }
182 
183  m_pImpl->m_db = 0;
184 }
185 
187 {
188  return m_pImpl->m_db != 0;
189 }
190 
192 {
193  return m_pImpl->m_db != 0;
194 }
195 
197 {
198  return *Impl::sm_capabilities;
199 }
200 
202 {
203  return Impl::sm_dialect;
204 }
205 
207 {
208  delete Impl::sm_capabilities;
210 }
211 
213 {
214  delete Impl::sm_dialect;
216 }
217 
218 void te::sqlite::DataSource::create(const std::map<std::string, std::string>& dsInfo)
219 {
220  if(Exists(dsInfo))
221  throw te::da::Exception(TR_COMMON("The informed SQLite database already exists!"));
222 
223  {
224  std::map<std::string, std::string>::const_iterator it = dsInfo.find("SQLITE_CREATE_INTERMEDIATE_DIR");
225 
226  if((it != dsInfo.end()) && (boost::to_upper_copy(it->second) == "TRUE"))
227  {
228  it = dsInfo.find("SQLITE_FILE");
229 
230  if(it == dsInfo.end())
231  throw te::da::Exception(TR_COMMON("You must at least provide a database file name if you want to create its intermediate directories!"));
232 
233  boost::filesystem::path fileName(it->second);
234 
235  if(fileName.has_parent_path() &&
236  !te::core::FileSystem::exists(fileName.parent_path().string()) &&
237  !te::core::FileSystem::createDirectories(fileName.parent_path()))
238  throw te::da::Exception(TR_COMMON("Could not create directory for SQLite database!"));
239  }
240  }
241 
242  std::map<std::string, std::string> info = dsInfo;
243 
244  info["SQLITE_OPEN_READWRITE"] = "true";
245  info["SQLITE_OPEN_CREATE"] = "true";
246 
247  setConnectionInfo(info);
248  open();
249  close();
250 }
251 
252 void te::sqlite::DataSource::drop(const std::map<std::string, std::string>& dsInfo)
253 {
254  if(!Exists(dsInfo))
255  throw te::da::Exception(TR_COMMON("The informed SQLite database doesn't exist!"));
256 
257  if((dsInfo.find("SQLITE_OPEN_URI") != dsInfo.end()) &&
258  (boost::to_upper_copy(m_pImpl->m_connInfo.find("SQLITE_OPEN_URI")->second) == "TRUE"))
259  throw te::da::Exception(TR_COMMON("Sorry! We don't support removing SQLite database through an URI!"));
260 
261  std::string fileName;
262 
263  {
264  std::map<std::string, std::string>::const_iterator it = dsInfo.find("SQLITE_FILE");
265 
266  if(it != dsInfo.end())
267  fileName = it->second;
268  else
269  throw te::da::Exception(TR_COMMON("To remove an SQLite database you must inform its file name!"));
270  }
271 
273 }
274 
275 bool te::sqlite::DataSource::exists(const std::map<std::string, std::string>& dsInfo)
276 {
277  std::string fileName;
278 
279  std::map<std::string, std::string>::const_iterator it = dsInfo.find("SQLITE_FILE");
280 
281  if(it == dsInfo.end())
282  throw te::da::Exception(TR_COMMON("In order to check the existence of a SQLite database you must inform its file name"));
283 
284  return te::core::FileSystem::exists(it->second);
285 }
286 
287 std::vector<std::string> te::sqlite::DataSource::getDataSourceNames(const std::map<std::string, std::string>& dsInfo)
288 {
289  return std::vector<std::string>();
290 }
291 
292 std::vector<std::string> te::sqlite::DataSource::getEncodings(const std::map<std::string, std::string>& dsInfo)
293 {
294  std::vector<std::string> encodings;
295  encodings.push_back("UTF-8");
296  return encodings;
297 }
298 
bool isOpened() const
It returns true if the data source is opened, otherwise it returns false.
struct sqlite3 sqlite3
void DataSourceTransactor()
Definition: GDALExample.cpp:92
te::da::SQLDialect * dialect
Definition: WFSDialect.h:1
void drop(const std::map< std::string, std::string > &dsInfo)
static bool exists(const std::string &path)
Checks if a given path in UTF-8 exists.
Definition: FileSystem.cpp:142
static bool createDirectories(const std::string &path)
Creates a directory for any element of path that does not exist.
Definition: FileSystem.cpp:153
bool isValid() const
It checks if the data source is valid (available for using).
const te::da::DataSourceCapabilities & getCapabilities() const
It returns the known capabilities of the data source.
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)
void create(const std::map< std::string, std::string > &dsInfo)
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 the set of parameters used to set up the access channel to the underlying repository...
std::map< std::string, std::string > m_connInfo
static void set(te::da::DataSourceCapabilities *capabilities)
static bool remove(const std::string &path)
Removes a file or directory from a given path in UTF-8.
Definition: FileSystem.cpp:166
te::da::DataSourceCapabilities capabilities
void setConnectionInfo(const std::map< std::string, std::string > &connInfo)
void open()
It opens the data source and makes it ready for using.
std::string getType() const
It returns the data source type name (in UPPER CASE). Ex: POSTGIS, SQLITE, WFS, WMS, or MYSQL.
const te::da::SQLDialect * getDialect() const
It returns the data source SQL dialect, if there is one.
static te::da::DataSourceCapabilities * sm_capabilities
bool exists(const std::map< std::string, std::string > &dsInfo)
bool Exists(const std::map< std::string, std::string > &dbInfo)
void close()
It closes the data source and clears all the resources used by its internal communication channel...
#define TE_SQLITE_DRIVER_IDENTIFIER
The SQLite driver identifier string.
const std::map< std::string, std::string > & getConnectionInfo() const
std::vector< std::string > getEncodings(const std::map< std::string, std::string > &dsInfo)
int GetConnectionFlags(const std::map< std::string, std::string > &connInfo)