attic/src/sqlite/PreparedQuery.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/PreparedQuery.cpp
22 
23  \brief A class that implements a prepared query for the TerraLib SQLite Data Access Driver.
24 */
25 
26 // TerraLib
27 #include "../common/Globals.h"
28 #include "../core/translator/Translator.h"
29 #include "../dataaccess/dataset/DataSet.h"
30 #include "../dataaccess/dataset/DataSetType.h"
31 #include "../dataaccess/query/Query.h"
32 #include "../datatype/ByteArray.h"
33 #include "../datatype/DateTime.h"
34 #include "../geometry/Geometry.h"
35 #include "../memory/DataSet.h"
36 #include "DataSource.h"
37 #include "DataSourceTransactor.h"
38 #include "EWKBSize.h"
39 #include "EWKBWriter.h"
40 #include "FwDataSet.h"
41 #include "PreparedQuery.h"
42 #include "SQLVisitor.h"
43 
44 // STL
45 #include <memory>
46 
47 // Boost
48 #include <boost/date_time.hpp>
49 #include <boost/format.hpp>
50 
51 // SQLite
52 #include <sqlite3.h>
53 
54 namespace te
55 {
56  namespace sqlite
57  {
58 
59  inline void BindValue(sqlite3_stmt* stmt, te::da::DataSet* d, std::size_t i, std::size_t propertyPos)
60  {
61  int retval = SQLITE_OK;
62 
63  const int propertyDataType = d->getPropertyDataType(propertyPos);
64 
65  if(d->isNull(propertyPos))
66  {
67  retval = sqlite3_bind_null(stmt, i + 1);
68 
69  if(retval != SQLITE_OK)
70  throw te::common::Exception(TR_COMMON("SQLite driver couldn't bind a NULL value!"));
71 
72  return;
73  }
74 
75  switch(propertyDataType)
76  {
77  case te::dt::CHAR_TYPE :
78  retval = sqlite3_bind_int(stmt, i + 1, d->getChar(propertyPos));
79  break;
80 
81  case te::dt::UCHAR_TYPE :
82  retval = sqlite3_bind_int(stmt, i + 1, d->getUChar(propertyPos));
83  break;
84 
85  case te::dt::INT16_TYPE :
86  retval = sqlite3_bind_int(stmt, i + 1, d->getInt16(propertyPos));
87  break;
88 
89  case te::dt::INT32_TYPE :
90  retval = sqlite3_bind_int(stmt, i + 1, d->getInt32(propertyPos));
91  break;
92 
93  case te::dt::INT64_TYPE :
94  retval = sqlite3_bind_int64(stmt, i + 1, d->getInt64(propertyPos));
95  break;
96 
98  retval = sqlite3_bind_int(stmt, i + 1, d->getBool(propertyPos) ? TE_SQLITE_BOOL_TRUE : TE_SQLITE_BOOL_FALSE);
99  break;
100 
101  case te::dt::FLOAT_TYPE :
102  retval = sqlite3_bind_double(stmt, i + 1, static_cast<double>(d->getFloat(propertyPos)));
103  break;
104 
105  case te::dt::DOUBLE_TYPE :
106  retval = sqlite3_bind_double(stmt, i + 1, d->getDouble(propertyPos));
107  break;
108 
109  case te::dt::NUMERIC_TYPE :
110  {
111  std::string value = d->getNumeric(propertyPos);
112  retval = sqlite3_bind_text(stmt, i + 1, value.c_str(), value.size(), SQLITE_TRANSIENT);
113  }
114  break;
115 
116  case te::dt::STRING_TYPE :
117  {
118  std::string value = d->getString(propertyPos);
119  retval = sqlite3_bind_text(stmt, i + 1, value.c_str(), value.size(), SQLITE_TRANSIENT);
120  }
121  break;
122 
123  //case te::dt::BYTE_ARRAY_TYPE :
124  // {
125  // std::auto_ptr<te::dt::ByteArray> b(d->getByteArray(propertyPos));
126 
127  // retval = sqlite3_bind_blob(stmt, i + 1, b->getData(), b->bytesUsed(), SQLITE_TRANSIENT);
128  // }
129  //break;
130 
131  case te::dt::GEOMETRY_TYPE :
132  {
133  std::auto_ptr<te::gm::Geometry> g(d->getGeometry(propertyPos));
134 
135  std::size_t ewkbSize = EWKBSize::getEWKBSize(g.get());
136 
137  unsigned char* ewkb = new unsigned char[ewkbSize];
138 
139  EWKBWriter::write(g.get(), ewkb, te::common::Globals::sm_machineByteOrder);
140 
141  retval = sqlite3_bind_blob(stmt, i + 1, ewkb, ewkbSize, SQLITE_TRANSIENT);
142 
143  delete [] ewkb;
144  }
145  break;
146 
147  case te::dt::DATETIME_TYPE :
148  {
149  std::auto_ptr<te::dt::DateTime> dt(d->getDateTime(propertyPos));
150 
151  std::string sdate = dt->toString();
152 
153  retval = sqlite3_bind_text(stmt, i + 1, sdate.c_str(), sdate.size(), SQLITE_TRANSIENT);
154 
155  //const te::dt::DateTimeProperty* dtp = static_cast<const te::dt::DateTimeProperty*>(p);
156 
157  //if(dtp->getSubType() == te::dt::DateTimeProperty::TIME_INSTANT)
158  //{
159  //
160  //}
161  //else //if(dtp->getSubType() == te::dt::DateTimeProperty::DATE)
162  //{
163  //
164  //}
165  }
166  break;
167 
168  default:
169  throw te::common::Exception(TR_COMMON("There is a TerraLib data type that can not be mapped to SQLite type system!"));
170  }
171 
172  if(retval != SQLITE_OK)
173  throw te::common::Exception(TR_COMMON("Could not bind a value!"));
174  }
175 
176  } // end namespace sqlite
177 } // end namespace te
178 
180  : m_t(parent),
181  m_stmt(0),
182  m_db(db)
183 {
184 }
185 
187 {
188  sqlite3_finalize(m_stmt);
189 }
190 
192 {
193  return "UNAMED";
194 }
195 
196 void te::sqlite::PreparedQuery::prepare(const te::da::Query& query, const std::vector<te::dt::Property*>& /*paramTypes*/)
197 {
198  assert(m_t && m_t->getDataSource() && m_t->getDataSource()->getDialect());
199  std::string sql;
200 
201  SQLVisitor visitor(*(m_t->getDataSource()->getDialect()), sql);
202  query.accept(visitor);
203 
204  prepare(sql);
205 }
206 
207 void te::sqlite::PreparedQuery::prepare(const std::string& query, const std::vector<te::dt::Property*>& /*paramTypes*/)
208 {
209  sqlite3_finalize(m_stmt);
210 
211  m_stmt = 0;
212 
213  int ret = sqlite3_prepare_v2(m_db, query.c_str(), -1, &m_stmt, 0);
214 
215  if(ret != SQLITE_OK)
216  {
217  if(m_stmt)
218  sqlite3_finalize(m_stmt);
219 
220  m_stmt = 0;
221 
222  throw te::common::Exception((boost::format(TR_COMMON("Could not excute the given query due to the following error: %1%.")) % sqlite3_errmsg(m_db)).str());
223  }
224 }
225 
227 {
228  int retval = sqlite3_step(m_stmt);
229 
230  if(retval != SQLITE_DONE)
231  {
232  boost::format errmsg(TR_COMMON("Could not execute prepared query due to the following error: %1%."));
233 
234  const char* litemsg = sqlite3_errmsg(m_db);
235 
236  if(litemsg != 0)
237  errmsg = errmsg % litemsg;
238 
239  throw te::common::Exception(errmsg.str());
240  }
241 
242  retval = sqlite3_reset(m_stmt);
243 
244  if(retval != SQLITE_OK)
245  {
246  boost::format errmsg(TR_COMMON("Could not reset the prepared query to its initial state due to the following error: %1%."));
247 
248  const char* litemsg = sqlite3_errmsg(m_db);
249 
250  if(litemsg)
251  errmsg = errmsg % litemsg;
252 
253  throw te::common::Exception(errmsg.str());
254  }
255 }
256 
258  te::common::AccessPolicy /*rwRole*/)
259 {
260  //int retval = sqlite3_step(m_stmt);
261 
262  te::mem::DataSet* dataset = 0;
263 
264  //if(retval == SQLITE_ROW)
265  //{
266  // FwDataSet fwdataset(m_stmt, m_t, false);
267 
268  // dataset = new te::mem::DataSet(fwdataset);
269  //}
270  //else if(retval != SQLITE_DONE)
271  //{
272  // boost::format errmsg(TR_COMMON("Could not excute prepared query due to the following error: %1%."));
273 
274  // const char* litemsg = sqlite3_errmsg(m_t->getLiteDataSource()->getDB());
275 
276  // if(litemsg)
277  // errmsg = errmsg % litemsg;
278 
279  // throw te::common::Exception(errmsg.str());
280  //}
281  //else
282  //{
283  // dataset = new te::mem::DataSet(0);
284  //}
285 
286  //retval = sqlite3_reset(m_stmt);
287  //
288  //if(retval != SQLITE_OK)
289  //{
290  // boost::format errmsg(TR_COMMON("Could not reset the prepared query to its initial state due to the following error: %1%."));
291 
292  // const char* litemsg = sqlite3_errmsg(m_t->getLiteDataSource()->getDB());
293 
294  // if(litemsg)
295  // errmsg = errmsg % litemsg;
296 
297  // throw te::common::Exception(errmsg.str());
298  //}
299 
300  return dataset;
301 }
302 
303 void te::sqlite::PreparedQuery::bind(int i, char value)
304 {
305  int retval = sqlite3_bind_int(m_stmt, i + 1, value);
306 
307  if(retval != SQLITE_OK)
308  throw te::common::Exception(TR_COMMON("Could not bind a char value!"));
309 }
310 
311 void te::sqlite::PreparedQuery::bind(int i, unsigned char value)
312 {
313  int retval = sqlite3_bind_int(m_stmt, i + 1, value);
314 
315  if(retval != SQLITE_OK)
316  throw te::common::Exception(TR_COMMON("Could not bind a unsigned char value!"));
317 }
318 
319 void te::sqlite::PreparedQuery::bind(int i, boost::int16_t value)
320 {
321  int retval = sqlite3_bind_int(m_stmt, i + 1, value);
322 
323  if(retval != SQLITE_OK)
324  throw te::common::Exception(TR_COMMON("Could not bind a 16-bit integer value!"));
325 }
326 
327 void te::sqlite::PreparedQuery::bind(int i, boost::int32_t value)
328 {
329  int retval = sqlite3_bind_int(m_stmt, i + 1, value);
330 
331  if(retval != SQLITE_OK)
332  throw te::common::Exception(TR_COMMON("Could not bind a 32-bit integer value!"));
333 }
334 
335 void te::sqlite::PreparedQuery::bind(int i, boost::int64_t value)
336 {
337  int retval = sqlite3_bind_int64(m_stmt, i + 1, value);
338 
339  if(retval != SQLITE_OK)
340  throw te::common::Exception(TR_COMMON("Could not bind a 64-bit integer value!"));
341 }
342 
343 void te::sqlite::PreparedQuery::bind(int i, bool value)
344 {
345  int retval = sqlite3_bind_int(m_stmt, i + 1, value ? TE_SQLITE_BOOL_TRUE : TE_SQLITE_BOOL_FALSE);
346 
347  if(retval != SQLITE_OK)
348  throw te::common::Exception(TR_COMMON("Could not bind a boolean value!"));
349 }
350 
351 void te::sqlite::PreparedQuery::bind(int i, float value)
352 {
353  int retval = sqlite3_bind_double(m_stmt, i + 1, static_cast<double>(value));
354 
355  if(retval != SQLITE_OK)
356  throw te::common::Exception(TR_COMMON("Could not bind a float value!"));
357 }
358 
359 void te::sqlite::PreparedQuery::bind(int i, double value)
360 {
361  int retval = sqlite3_bind_double(m_stmt, i + 1, value);
362 
363  if(retval != SQLITE_OK)
364  throw te::common::Exception(TR_COMMON("Could not bind a double value!"));
365 }
366 
367 void te::sqlite::PreparedQuery::bindNumeric(int i, const std::string& value)
368 {
369  int retval = sqlite3_bind_text(m_stmt, i + 1, value.c_str(), value.size(), SQLITE_TRANSIENT);
370 
371  if(retval != SQLITE_OK)
372  throw te::common::Exception(TR_COMMON("Could not bind a numeric value!"));
373 }
374 
375 void te::sqlite::PreparedQuery::bind(int i, const std::string& value)
376 {
377  int retval = sqlite3_bind_text(m_stmt, i + 1, value.c_str(), value.size(), SQLITE_TRANSIENT);
378 
379  if(retval != SQLITE_OK)
380  throw te::common::Exception(TR_COMMON("Could not bind a string value!"));
381 }
382 
384 {
385  int retval = sqlite3_bind_blob(m_stmt, i + 1, value.getData(), value.bytesUsed(), SQLITE_TRANSIENT);
386 
387  if(retval != SQLITE_OK)
388  throw te::common::Exception(TR_COMMON("Could not bind a byte array value!"));
389 }
390 
392 {
393  std::size_t ewkbSize = EWKBSize::getEWKBSize(&value);
394 
395  unsigned char* ewkb = new unsigned char[ewkbSize];
396 
397  EWKBWriter::write(&value, ewkb, te::common::Globals::sm_machineByteOrder);
398 
399  int retval = sqlite3_bind_blob(m_stmt, i + 1, ewkb, ewkbSize, SQLITE_TRANSIENT);
400 
401  delete [] ewkb;
402 
403  if(retval != SQLITE_OK)
404  throw te::common::Exception(TR_COMMON("Could not bind a geometry value!"));
405 }
406 
407 void te::sqlite::PreparedQuery::bind(int /*i*/, const te::rst::Raster& /*value*/)
408 {
409  throw te::common::Exception(TR_COMMON("Not implemented yet!"));
410 }
411 
413 {
414  std::string sdate = value.toString();
415 
416  int retval = sqlite3_bind_text(m_stmt, i + 1, sdate.c_str(), sdate.size(), SQLITE_TRANSIENT);
417 
418  if(retval != SQLITE_OK)
419  throw te::common::Exception(TR_COMMON("Could not bind a date-time value!"));
420 }
421 
422 void te::sqlite::PreparedQuery::bind(int /*i*/, const te::da::DataSet& /*value*/)
423 {
424  throw te::common::Exception(TR_COMMON("Not implemented yet!"));
425 }
426 
428 {
429  throw te::common::Exception(TR_COMMON("Not implemented yet!"));
430 }
431 
433 {
434  return m_t;
435 }
436 
437 // SQLite specific
439 {
440  sqlite3_finalize(m_stmt);
441 
442  m_stmt = 0;
443 
444  sqlite3_finalize(m_stmt);
445 
446  m_stmt = 0;
447 
448  int ret = sqlite3_prepare_v2(m_db, query.c_str(), -1, &m_stmt, 0);
449 
450  if(ret != SQLITE_OK)
451  {
452  if(m_stmt)
453  sqlite3_finalize(m_stmt);
454 
455  m_stmt = 0;
456 
457  throw te::common::Exception((boost::format(TR_COMMON("Could not excute the given query due to the following error: %1%.")) % sqlite3_errmsg(m_db)).str());
458  }
459 }
460 
461 void te::sqlite::PreparedQuery::bind(const std::vector<std::size_t>& propertiesPos,
462  std::size_t offset,
464 {
465  const std::size_t nparams = propertiesPos.size();
466 
467  for(std::size_t i = 0; i != nparams; ++i)
468  BindValue(m_stmt, d, i + offset, propertiesPos[i]);
469 }
470 
471 void te::sqlite::PreparedQuery::bind(const std::vector<std::size_t>& propertiesPos,
473 {
474  const std::size_t nparams = propertiesPos.size();
475 
476  for(std::size_t i = 0; i != nparams; ++i)
477  BindValue(m_stmt, d, i, propertiesPos[i]);
478 }
479 
481 {
482  const std::size_t nparams = d->getNumProperties();
483 
484  for(std::size_t i = 0; i != nparams; ++i)
485  BindValue(m_stmt, d, i, i);
486 }
487 
488 
489 
490 
491 
virtual std::unique_ptr< te::gm::Geometry > getGeometry(std::size_t i) const =0
Method for retrieving a geometric attribute value.
virtual unsigned char getUChar(std::size_t i) const =0
Method for retrieving an unsigned character attribute value (1 byte long).
struct sqlite3 sqlite3
void BindValue(sqlite3_stmt *stmt, te::da::DataSet *d, std::size_t i, std::size_t propertyPos)
virtual double getDouble(std::size_t i) const =0
Method for retrieving a double attribute value.
std::size_t bytesUsed() const
It returns the number of used bytes in the internal buffer.
Definition: ByteArray.cpp:169
void prepare(const te::da::Query &query, const std::vector< te::dt::Property * > &paramTypes)
It prepares the query that may be used for commands that are used mutiple times (select, insert, update and delete).
virtual std::string getNumeric(std::size_t i) const =0
Method for retrieving a numeric attribute value.
virtual float getFloat(std::size_t i) const =0
Method for retrieving a float attribute value.
te::da::DataSet * query(te::common::TraverseType travType=te::common::FORWARDONLY, te::common::AccessPolicy rwRole=te::common::RAccess)
std::string toString() const
It returns the time duration in the ISO textual format (hh:mm:ss,ss).
static const MachineByteOrder sm_machineByteOrder
A flag that indicates the machine byte order (Big Endian or Little Endian).
virtual ReturnType accept(VisitorType &guest) const =0
It call the visit method from the guest object.
AccessPolicy
Supported data access policies (can be used as bitfield).
TraverseType
A dataset can be traversed in two ways:
Implementation of a random-access dataset class for the TerraLib In-Memory Data Access driver...
virtual std::string toString() const =0
It returns the data value in a string notation.
te::da::DataSource * getDataSource() const
It returns the parent data source of the transactor.
virtual boost::int16_t getInt16(std::size_t i) const =0
Method for retrieving a 16-bit integer attribute value (2 bytes long).
virtual int getPropertyDataType(std::size_t i) const =0
It returns the underlying data type of the property at position pos.
An abstract class for raster data strucutures.
char * getData() const
It returns the data array.
Definition: ByteArray.cpp:105
URI C++ Library.
Definition: Attributes.h:37
virtual boost::int32_t getInt32(std::size_t i) const =0
Method for retrieving a 32-bit integer attribute value (4 bytes long).
static te::dt::DateTime d(2010, 8, 9, 15, 58, 39)
static te::dt::TimeDuration dt(20, 30, 50, 11)
std::string getName() const
It returns the prepared query name.
#define TE_SQLITE_BOOL_FALSE
A flag that indicates a false value (boolean).
A base class for values that can be retrieved from the data access module.
Definition: AbstractData.h:57
void bind(int i, char value)
Binds the i-th parameter of the query to a value.
A DataSourceTransactor can be viewed as a connection to the data source for reading/writing things in...
This class is designed to declare objects to be thrown as exceptions by TerraLib. ...
Geometry is the root class of the geometries hierarchy, it follows OGC and ISO standards.
A visitor for building an SQL statement using SQLite dialect.
virtual std::unique_ptr< te::dt::DateTime > getDateTime(std::size_t i) const =0
Method for retrieving a date and time attribute value.
A dataset is the unit of information manipulated by the data access module of TerraLib.
virtual char getChar(std::size_t i) const =0
Method for retrieving a signed character attribute value (1 byte long).
virtual const SQLDialect * getDialect() const =0
It returns the data source SQL dialect, if there is one.
void bindNumeric(int i, const std::string &value)
Binds the i-th parameter of the query to a value.
virtual bool getBool(std::size_t i) const =0
Method for retrieving a boolean attribute value.
virtual bool isNull(std::size_t i) const =0
It checks if the attribute value is NULL.
struct sqlite3_stmt sqlite3_stmt
Definition: FwDataSet.h:35
virtual boost::int64_t getInt64(std::size_t i) const =0
Method for retrieving a 64-bit integer attribute value (8 bytes long).
virtual std::size_t getNumProperties() const =0
It returns the number of properties that composes an item of the dataset.
#define TE_SQLITE_BOOL_TRUE
A flag that indicates a false value (boolean).
static std::size_t getEWKBSize(const te::gm::Geometry *g)
Definition: EWKBSize.cpp:49
te::da::DataSourceTransactor * getTransactor() const
It returns a pointer to the underlying data source transactor.
A Query is independent from the data source language/dialect.
Definition: Query.h:46
virtual std::string getString(std::size_t i) const =0
Method for retrieving a string value attribute.
A class for representing binary data.
Definition: ByteArray.h:51