ado/DataSet.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/ado/DataSet.cpp
22 
23  \brief DataSet class implementation for Microsoft Access driver.
24 */
25 
26 // TerraLib
27 #include "../common/ByteSwapUtils.h"
28 #include "../common/Exception.h"
29 #include "../common/Globals.h"
30 #include "../common/StringUtils.h"
31 #include "../core/translator/Translator.h"
32 #include "../dataaccess/dataset/DataSetType.h"
33 #include "../datatype/Array.h"
34 #include "../datatype/ByteArray.h"
35 #include "../datatype/DateTimeProperty.h"
36 #include "../datatype/SimpleData.h"
37 #include "../datatype/TimeInstant.h"
38 #include "../geometry/Envelope.h"
39 #include "../geometry/Geometry.h"
40 #include "../geometry/WKBReader.h"
41 #include "Connection.h"
42 #include "DataSet.h"
43 #include "DataSource.h"
44 
45 #include "Transactor.h"
46 #include "Utils.h"
47 
48 // STL
49 #include <memory>
50 
51 // Boost
52 #include <boost/dynamic_bitset.hpp>
53 #include <boost/lexical_cast.hpp>
54 
55 inline void TESTHR( HRESULT hr )
56 {
57  if( FAILED(hr) ) _com_issue_error( hr );
58 }
59 
60 te::ado::DataSet::DataSet(Transactor* t, _RecordsetPtr result)
61  : m_result(result),
62  m_t(t),
63  m_i(-1),
64  m_size(-1),
65  m_ncols(-1)
66 {
67  m_size = m_result->GetRecordCount();
68 
69  m_ncols = m_result->GetFields()->GetCount();
70 
71 // convert data types from ADO to TerraLib
72  FieldsPtr fields = m_result->GetFields();
73 
74  for(int i = 0; i != m_ncols; ++i)
75  {
76  FieldPtr field = fields->GetItem((long)i);
77 
78  std::string columnName = field->GetName();
79 
80  m_colNames.push_back(columnName);
81 
82  int terralib_data_type = te::ado::Convert2Terralib(field->GetType());
83 
84 // if it is a byte array it may be a geometric column!
85  if(terralib_data_type == te::dt::BYTE_ARRAY_TYPE)
86  {
87  std::string tableName = (LPCSTR)(_bstr_t)field->GetProperties()->GetItem("BASETABLENAME")->GetValue();
88 
89  bool is_geom = m_t->getAdoDataSource()->isGeometryColumn(tableName, columnName);
90 
91  if(is_geom)
93  else
94  m_datatypes.push_back(terralib_data_type);
95  }
96  else
97  {
98  m_datatypes.push_back(terralib_data_type);
99  }
100  }
101 }
102 
104 {
105  m_result->Close();
106 }
107 
109 {
110  return te::common::RANDOM;
111 }
112 
114 {
115  return te::common::RAccess;
116 }
117 
118 std::unique_ptr<te::gm::Envelope> te::ado::DataSet::getExtent(std::size_t /*i*/)
119 {
120  throw te::common::Exception(TE_TR("Method getExtent: not implemented yet!"));
121 }
122 
124 {
125  return m_ncols;
126 }
127 
129 {
130  return m_datatypes[i];
131 }
132 
133 std::string te::ado::DataSet::getPropertyName(std::size_t i) const
134 {
135  return m_colNames[i];
136 }
137 
138 std::string te::ado::DataSet::getDatasetNameOfProperty(std::size_t /*i*/) const
139 {
140  throw te::common::Exception(TE_TR("Method getDatasetNameOfProperty: not implemented yet!"));
141 }
142 
144 {
145  return (m_size == 0);
146 }
147 
149 {
150  return true;
151 }
152 
153 std::size_t te::ado::DataSet::size() const
154 {
155  return m_size;
156 }
157 
159 {
160  if(m_i != -1)
161  TESTHR(m_result->MoveNext());
162 
163  ++m_i;
164  return (m_i < m_size);
165 }
166 
168 {
169  if(m_i != m_size)
170  m_result->MovePrevious();
171 
172  --m_i;
173  return (m_i > -1);
174 }
175 
177 {
178  if(m_result->BOF != 0)
179  return true;
180 
181  TESTHR(m_result->MoveFirst());
182  m_i = -1;
183 
184  return m_size != 0;
185 }
186 
188 {
189  m_result->MoveFirst();
190  m_i = 0;
191  return m_size != 0;
192 }
193 
195 {
196  TESTHR(m_result->MoveLast());
197  m_i = m_size - 1;
198  return (m_i < m_size);
199 }
200 
201 bool te::ado::DataSet::move(std::size_t i)
202 {
203  if(i == 0)
204  return moveFirst();
205 
206  if(m_i == i)
207  return true;
208 
209  long p = static_cast<long>(i-m_i);
210 
211  TESTHR(m_result->Move(p));
212 
213  m_i += p;
214  return (m_i < m_size);
215 }
216 
218 {
219  return m_i == 0;
220 }
221 
223 {
224  return m_i < 0;
225 }
226 
228 {
229  return m_i == (m_size - 1);
230 }
231 
233 {
234  return m_i >= m_size;
235 }
236 
238 {
239  return m_i > -1 && m_i < m_size;
240 }
241 
242 char te::ado::DataSet::getChar(std::size_t i) const
243 {
244  _variant_t vtIndex;
245  vtIndex.vt = VT_I4;
246  vtIndex.lVal = (long)i;
247 
248  char ival;
249 
250  try
251  {
252  ival = (char)m_result->GetFields()->GetItem(vtIndex)->GetValue();
253  }
254  catch(_com_error& e)
255  {
256  throw te::common::Exception((LPCSTR)e.ErrorMessage());
257  }
258 
259  return ival;
260 }
261 
262 unsigned char te::ado::DataSet::getUChar(std::size_t i) const
263 {
264  return (unsigned char)getChar(i);
265 }
266 
267 boost::int16_t te::ado::DataSet::getInt16(std::size_t i) const
268 {
269  _variant_t vtIndex;
270  vtIndex.vt = VT_I4;
271  vtIndex.lVal = (long)i;
272 
273  int16_t ival;
274 
275  try
276  {
277  ival = (int16_t)m_result->GetFields()->GetItem(vtIndex)->GetValue();
278  }
279  catch(_com_error& e)
280  {
281  throw te::common::Exception((LPCSTR)e.ErrorMessage());
282  }
283 
284  return ival;
285 }
286 
287 boost::int32_t te::ado::DataSet::getInt32(std::size_t i) const
288 {
289  _variant_t vtIndex;
290  vtIndex.vt = VT_I4;
291  vtIndex.lVal = (long)i;
292 
293  int32_t ival;
294 
295  try
296  {
297  ival = (int32_t)m_result->GetFields()->GetItem(vtIndex)->GetValue();
298  }
299  catch(_com_error& e)
300  {
301  throw te::common::Exception((LPCSTR)e.ErrorMessage());
302  }
303 
304  return ival;
305 }
306 
307 boost::int64_t te::ado::DataSet::getInt64(std::size_t i) const
308 {
309  _variant_t vtIndex;
310  vtIndex.vt = VT_I4;
311  vtIndex.lVal = (long)i;
312 
313  int64_t ival;
314 
315  try
316  {
317  ival = (int64_t)m_result->GetFields()->GetItem(vtIndex)->GetValue();
318  }
319  catch(_com_error& e)
320  {
321  throw te::common::Exception((LPCSTR)e.ErrorMessage());
322  }
323 
324  return ival;
325 }
326 
327 bool te::ado::DataSet::getBool(std::size_t i) const
328 {
329  _variant_t vtIndex;
330  vtIndex.vt = VT_I4;
331  vtIndex.lVal = (long)i;
332 
333  bool ival;
334 
335  try
336  {
337  ival = (bool)m_result->GetFields()->GetItem(vtIndex)->GetValue();
338  }
339  catch(_com_error& e)
340  {
341  throw te::common::Exception((LPCSTR)e.ErrorMessage());
342  }
343 
344  return ival;
345 }
346 
347 float te::ado::DataSet::getFloat(std::size_t i) const
348 {
349  float value;
350 
351  _variant_t vtIndex;
352  vtIndex.vt = VT_I4;
353  vtIndex.lVal = (long)i;
354 
355  try
356  {
357  value = (float)m_result->GetFields()->GetItem(vtIndex)->GetValue();
358  }
359  catch(_com_error& e)
360  {
361  throw te::common::Exception((LPCSTR)e.ErrorMessage());
362  }
363 
364  return value;
365 }
366 
367 double te::ado::DataSet::getDouble(std::size_t i) const
368 {
369  double value;
370 
371  _variant_t vtIndex;
372  vtIndex.vt = VT_I4;
373  vtIndex.lVal = (long)i;
374 
375  try
376  {
377  value = (double)m_result->GetFields()->GetItem(vtIndex)->GetValue();
378  }
379  catch(_com_error& e)
380  {
381  throw te::common::Exception((LPCSTR)e.ErrorMessage());
382  }
383 
384  return value;
385 }
386 
387 std::string te::ado::DataSet::getNumeric(std::size_t /*i*/) const
388 {
389  throw te::common::Exception(TE_TR("Method getNumeric: not implemented yet!"));
390 }
391 
392 std::string te::ado::DataSet::getString(std::size_t i) const
393 {
394  _variant_t vtIndex;
395  vtIndex.vt = VT_I4;
396  vtIndex.lVal = (long)i;
397 
398  std::string ival;
399 
400  try
401  {
402  ival = (LPCSTR)(_bstr_t)m_result->GetFields()->GetItem(vtIndex)->GetValue();
403  }
404  catch(_com_error& e)
405  {
406  throw te::common::Exception((LPCSTR)e.ErrorMessage());
407  }
408 
409  return ival;
410 }
411 
412 std::unique_ptr<te::dt::ByteArray> te::ado::DataSet::getByteArray(std::size_t i) const
413 {
414  _variant_t vtIndex;
415  vtIndex.vt = VT_I4;
416  vtIndex.lVal = (long)i;
417 
418  _variant_t varBLOB;
419  char *cdata = 0;
420  long size;
421  char* data = 0;
422 
423  try
424  {
425  ::Field15Ptr field;
426 
427  if(m_result->MoveNext() == S_OK)
428  m_result->MovePrevious();
429  else if(m_result->MovePrevious() == S_OK)
430  m_result->MoveNext();
431  else
432  {
433  _RecordsetPtr copy = m_result->Clone(adLockReadOnly);
434 
435  field = copy->GetFields()->GetItem(vtIndex);
436  }
437 
438  field = m_result->GetFields()->GetItem(vtIndex);
439 
440  size = field->ActualSize;
441  if(size > 0)
442  {
443  VariantInit(&varBLOB);
444 
445  varBLOB = field->GetChunk(size);
446 
447  if(varBLOB.vt == (VT_ARRAY | VT_UI1))
448  {
449  SafeArrayAccessData(varBLOB.parray,(void **)&cdata);
450  data = new char[size];
451  memcpy(data, cdata, size);
452  SafeArrayUnaccessData(varBLOB.parray);
453  }
454  }
455  }
456  catch(_com_error& e)
457  {
458  throw te::common::Exception((LPCSTR)e.ErrorMessage());
459  }
460 
461  return std::unique_ptr<te::dt::ByteArray>(new te::dt::ByteArray(data, size));
462 }
463 
464 std::unique_ptr<te::gm::Geometry> te::ado::DataSet::getGeometry(std::size_t i) const
465 {
466  std::unique_ptr<te::dt::ByteArray> ba(getByteArray(i));
467 
468  std::unique_ptr<te::gm::Geometry> geom(te::gm::WKBReader::read(ba->getData()));
469 
470  std::size_t wkb_size = geom->getWkbSize();
471 
472  if(ba->bytesUsed() - wkb_size >= 4)
473  geom->setSRID(*((int*)(ba->getData() + wkb_size)));
474 
475  return geom;
476 }
477 
478 std::unique_ptr<te::rst::Raster> te::ado::DataSet::getRaster(std::size_t /*i*/) const
479 {
480  throw te::common::Exception(TE_TR("Method getRaster: not implemented yet!"));
481 }
482 
483 std::unique_ptr<te::dt::DateTime> te::ado::DataSet::getDateTime(std::size_t i) const
484 {
485  _variant_t vtIndex;
486  _variant_t value;
487 
488  vtIndex.vt = VT_I4;
489  vtIndex.lVal = (long)i;
490 
491  std::string strDate;
492  try
493  {
494  value = m_result->GetFields()->GetItem(vtIndex)->Value;
495  }
496  catch(_com_error &e)
497  {
498  throw te::common::Exception((LPCSTR)e.ErrorMessage());
499  }
500 
501  if(value.vt == VT_NULL)
502  return std::unique_ptr<te::dt::DateTime>();
503 
504  strDate = (LPCSTR)(_bstr_t)value;
505 
506  // Getting system format
507  std::string indAM;
508  std::string indPM;
509  std::string sepD;
510  std::string sepT;
511 
512  std::string mask = te::ado::GetSystemDateTimeFormat(indAM, indPM, sepD, sepT);
513 
514  std::unique_ptr<te::dt::DateTime> result = te::ado::GetDateTime(strDate, mask, sepD, sepT);
515 
516  return result;
517 }
518 
519 std::unique_ptr<te::dt::Array> te::ado::DataSet::getArray(std::size_t /*i*/) const
520 {
521  throw te::common::Exception(TE_TR("Method getArray: not implemented yet!"));
522 }
523 
524 bool te::ado::DataSet::isNull(std::size_t i) const
525 {
526  _variant_t value;
527 
528  std::string propertyName = getPropertyName(i);
529 
530  try
531  {
532  value = m_result->GetFields()->GetItem(static_cast<long>(i))->GetValue();
533  }
534 
535  catch(_com_error& e)
536  {
537  throw te::common::Exception((LPCSTR)e.ErrorMessage());
538  }
539 
540  if(value.vt == VT_NULL)
541  return true;
542 
543  return false;
544 }
The transactor class for the Microsoft Access driver.
std::unique_ptr< te::rst::Raster > getRaster(std::size_t i) const
Method for retrieving a raster attribute value.
void TESTHR(HRESULT hr)
Definition: ado/DataSet.cpp:55
DataSet class implementation for Microsoft Access driver.
bool moveNext()
It moves the internal pointer to the next item of the collection.
int m_ncols
The number of properties in the collection.
Definition: ado/DataSet.h:153
std::unique_ptr< te::dt::DateTime > getDateTime(std::size_t i) const
Method for retrieving a date and time attribute value.
bool moveFirst()
It moves the internal pointer to the first item in the collection.
int Convert2Terralib(ADOX::DataTypeEnum adoType)
Bind ADOX Type to TerraLib Type.
Utility functions for ADO.
bool move(std::size_t i)
It moves the dataset internal pointer to a given position.
DataSet()
Default constructor.
double getDouble(std::size_t i) const
Method for retrieving a double attribute value.
bool movePrevious()
It moves the internal pointer to the previous item of the collection.
std::vector< int > m_datatypes
A vector of data types.
Definition: ado/DataSet.h:149
std::unique_ptr< te::dt::ByteArray > getByteArray(std::size_t i) const
Method for retrieving a byte array.
bool moveBeforeFirst()
It moves the internal pointer to a position before the first item in the collection.
float getFloat(std::size_t i) const
Method for retrieving a float attribute value.
std::string GetSystemDateTimeFormat(std::string &indAM, std::string &indPM, std::string &sepD, std::string &sepT)
It gets the system Date and Time format.
#define TE_TR(message)
It marks a string in order to get translated.
Definition: Translator.h:242
std::unique_ptr< te::gm::Geometry > getGeometry(std::size_t i) const
Method for retrieving a geometric attribute value.
bool isAfterEnd() const
It tells if the dataset internal pointer is on the sentinel position after the last element of the co...
bool isPositionValid() const
It tells if the dataset internal pointer is on a valid position.
std::size_t size() const
It returns the collection size, if it is known.
boost::int16_t getInt16(std::size_t i) const
Method for retrieving a 16-bit integer attribute value (2 bytes long).
int m_size
The number of datasets in the collection.
Definition: ado/DataSet.h:152
AccessPolicy
Supported data access policies (can be used as bitfield).
TraverseType
A dataset can be traversed in two ways:
std::unique_ptr< te::dt::DateTime > GetDateTime(std::string &value, std::string &mask, std::string &sepD, std::string &sepT)
It gets the DateTime TerraLib 5 from string.
bool getBool(std::size_t i) const
Method for retrieving a boolean attribute value.
bool isEmpty() const
It returns true if the collection is empty.
std::vector< std::string > m_colNames
A vector of columns names.
Definition: ado/DataSet.h:150
~DataSet()
The destructor will clear the internal ADO _RecordsetPtr.
std::string getNumeric(std::size_t i) const
Method for retrieving a numeric attribute value.
int getPropertyDataType(std::size_t i) const
It returns the underlying data type of the property at position pos.
unsigned char getUChar(std::size_t i) const
Method for retrieving an unsigned character attribute value (1 byte long).
te::gm::Polygon * p
bool isConnected() const
It returns true if the dataset is connected and false if it is disconnected. A dataset can be connect...
Implementation of the data source class for the ADO driver.
This class is designed to declare objects to be thrown as exceptions by TerraLib. ...
char getChar(std::size_t i) const
Method for retrieving a signed character attribute value (1 byte long).
DataSource * getAdoDataSource() const
te::common::TraverseType getTraverseType() const
It returns the traverse type associated to the dataset.
bool isGeometryColumn(const std::string &datasetName, const std::string &colName) const
bool moveLast()
It sets the dataset internal pointer to the last item in the collection.
std::string getString(std::size_t i) const
Method for retrieving a string value attribute.
bool isBeforeBegin() const
It tells if the dataset internal pointer is in a position before the first element of the collection ...
std::unique_ptr< te::gm::Envelope > getExtent(std::size_t i)
It computes the bounding rectangle for a spatial property of the dataset.
Transactor * m_t
The DataSet Transactor.
Definition: ado/DataSet.h:148
std::size_t getNumProperties() const
It returns the number of properties that composes an item of the dataset.
A class that implements a connection to a ADO database.
boost::int64_t getInt64(std::size_t i) const
Method for retrieving a 64-bit integer attribute value (8 bytes long).
_RecordsetPtr m_result
The internal buffer with the result query.
Definition: ado/DataSet.h:147
std::string getDatasetNameOfProperty(std::size_t i) const
It returns the underlying dataset name of the property at position pos.
bool isNull(std::size_t i) const
It checks if the attribute value is NULL.
te::common::AccessPolicy getAccessPolicy() const
It returns the read and write permission associated to the dataset.
DataSourceTransactor class implementation for Microsoft Access driver.
boost::int32_t getInt32(std::size_t i) const
Method for retrieving a 32-bit integer attribute value (4 bytes long).
bool isAtBegin() const
It tells if the dataset internal pointer is on the first element of the collection or not...
std::unique_ptr< te::dt::Array > getArray(std::size_t i) const
Method for retrieving an array.
std::string getPropertyName(std::size_t i) const
It returns the property name at position pos.
A class for representing binary data.
Definition: ByteArray.h:51
static Geometry * read(const char *wkb)
It returns a valid geometry from a given WKB.
Definition: WKBReader.cpp:48
int m_i
The index of the current row.
Definition: ado/DataSet.h:151
bool isAtEnd() const
It tells if the dataset internal pointer is on the last element of the collection.