aGrUM  0.16.0
DBInitializerFromSQL_tpl.h
Go to the documentation of this file.
1 
30 #ifdef _ODBC
31 # include <clocale>
32 
33 # ifndef DOXYGEN_SHOULD_SKIP_THIS
34 
36 
37 
38 namespace gum {
39 
40  namespace learning {
41 
42 
44  template < template < typename > class ALLOC >
45  void DBInitializerFromSQL< ALLOC >::__connect(
46  const std::string& connection_string, long timeout) {
47  // analyze the connection string: either this is a user-defined connection
48  // string or this is an aGrUM-constructed one derived from a datasource,
49  // a login and a password
50  bool agrum_connection = (connection_string.size() > 4)
51  && (connection_string.compare(0, 4, "gum ") == 0);
52 
53  // perform the connection to the database
54  if (!agrum_connection) {
55  __connection.connect(connection_string, timeout);
56  } else {
57  std::size_t deb_index, end_index;
58  const std::string delimiter = "|";
59 
60  deb_index = connection_string.find(delimiter, 0);
61  if (deb_index == std::string::npos)
62  GUM_ERROR(DatabaseError,
63  "could not determine the datasource from string "
64  << connection_string);
65  deb_index += std::size_t(1);
66  end_index = connection_string.find(delimiter, deb_index);
67  if (end_index == std::string::npos)
68  GUM_ERROR(DatabaseError,
69  "could not determine the datasource from string "
70  << connection_string);
71  std::string dataSource =
72  connection_string.substr(deb_index, end_index - deb_index);
73 
74  deb_index = connection_string.find(delimiter, end_index + std::size_t(1));
75  if (deb_index == std::string::npos)
76  GUM_ERROR(DatabaseError,
77  "could not determine the database login from string "
78  << connection_string);
79  deb_index += std::size_t(1);
80  end_index = connection_string.find(delimiter, deb_index);
81  if (end_index == std::string::npos)
82  GUM_ERROR(DatabaseError,
83  "could not determine the database login from string "
84  << connection_string);
85  std::string login =
86  connection_string.substr(deb_index, end_index - deb_index);
87 
88  deb_index = connection_string.find(delimiter, end_index + std::size_t(1));
89  if (deb_index == std::string::npos)
90  GUM_ERROR(DatabaseError,
91  "could not determine the database password from string "
92  << connection_string);
93  deb_index += std::size_t(1);
94  end_index = connection_string.find(delimiter, deb_index);
95  if (end_index == std::string::npos)
96  GUM_ERROR(DatabaseError,
97  "could not determine the database password from string "
98  << connection_string);
99  std::string password =
100  connection_string.substr(deb_index, end_index - deb_index);
101 
102  __connection.connect(dataSource, login, password, timeout);
103  }
104  }
105 
106 
108  template < template < typename > class ALLOC >
110  const std::string& connection_string,
111  const std::string& query,
112  long timeout,
113  const typename DBInitializerFromSQL< ALLOC >::allocator_type& alloc) :
114  IDBInitializer< ALLOC >(IDBInitializer< ALLOC >::InputType::STRING, alloc),
115  __connection_string(connection_string), __query(query), __timeout(timeout),
116  __var_names(alloc), __parser(alloc) {
117  // save the current locale because the connection to the database
118  // will change it
119  const std::string current_locale = std::setlocale(LC_NUMERIC, NULL);
120 
121  // perform the connection
122  __connect(connection_string, timeout);
123 
124  // restore the locale
125  std::setlocale(LC_NUMERIC, current_locale.c_str());
126 
127  // ask the parser to execute the query
128  __parser.useNewQuery(__connection, __query);
129 
130  // store the names of the columns into the intializer
131  const std::size_t nb_cols = std::size_t(__parser.nbColumns());
132  for (std::size_t i = 0; i < nb_cols; ++i) {
133  __var_names.push_back(__parser.columnName(i));
134  }
135 
136  GUM_CONSTRUCTOR(DBInitializerFromSQL);
137  }
138 
139 
141  template < template < typename > class ALLOC >
143  const std::string& dataSource,
144  const std::string& login,
145  const std::string& password,
146  const std::string& query,
147  long timeout,
148  const typename DBInitializerFromSQL< ALLOC >::allocator_type& alloc) :
149  DBInitializerFromSQL< ALLOC >("gum datasource=|" + dataSource
150  + "|; login=|" + login + "|; password=|"
151  + password + "|",
152  query,
153  timeout,
154  alloc) {}
155 
156 
158  template < template < typename > class ALLOC >
160  const DBInitializerFromSQL< ALLOC >& from,
161  const typename DBInitializerFromSQL< ALLOC >::allocator_type& alloc) :
162  DBInitializerFromSQL< ALLOC >(
163  from.__connection_string, from.__query, from.__timeout, alloc) {}
164 
165 
167  template < template < typename > class ALLOC >
169  const DBInitializerFromSQL< ALLOC >& from) :
170  DBInitializerFromSQL< ALLOC >(from, from.getAllocator()) {}
171 
172 
174  template < template < typename > class ALLOC >
176  DBInitializerFromSQL< ALLOC >&& from,
177  const typename DBInitializerFromSQL< ALLOC >::allocator_type& alloc) :
178  DBInitializerFromSQL< ALLOC >(
179  from.__connection_string, from.__query, from.__timeout, alloc) {}
180 
182  template < template < typename > class ALLOC >
184  DBInitializerFromSQL< ALLOC >&& from) :
185  DBInitializerFromSQL< ALLOC >(std::move(from), from.getAllocator()) {}
186 
187 
189  template < template < typename > class ALLOC >
190  DBInitializerFromSQL< ALLOC >* DBInitializerFromSQL< ALLOC >::clone(
191  const typename DBInitializerFromSQL< ALLOC >::allocator_type& alloc) const {
192  ALLOC< DBInitializerFromSQL< ALLOC > > allocator(alloc);
193  DBInitializerFromSQL< ALLOC >* new_initializer = allocator.allocate(1);
194  try {
195  allocator.construct(new_initializer, *this, alloc);
196  } catch (...) {
197  allocator.deallocate(new_initializer, 1);
198  throw;
199  }
200 
201  return new_initializer;
202  }
203 
204 
206  template < template < typename > class ALLOC >
207  DBInitializerFromSQL< ALLOC >* DBInitializerFromSQL< ALLOC >::clone() const {
208  return clone(this->getAllocator());
209  }
210 
211 
213  template < template < typename > class ALLOC >
215  GUM_DESTRUCTOR(DBInitializerFromSQL);
216  }
217 
218 
220  template < template < typename > class ALLOC >
221  DBInitializerFromSQL< ALLOC >& DBInitializerFromSQL< ALLOC >::
222  operator=(const DBInitializerFromSQL< ALLOC >& from) {
223  if (this != &from) {
225  // check if the connection parameters have changed
226  const bool connexion_changed =
227  (__connection_string != from.__connection_string);
228 
229  // save the new connection parameters
230  __connection_string = from.__connection_string;
231  __query = from.__query;
232  __timeout = from.__timeout;
233 
234  // recreate the connection if needed
235  if (connexion_changed) {
236  if (__connection.connected()) __connection.disconnect();
237  __connect(__connection_string, __timeout);
238  }
239 
240  // initiate the SQL parser
241  __parser.useNewQuery(__connection, __query);
242 
243  // store the names of the columns into the intializer
244  __var_names.clear();
245  const std::size_t nb_cols = std::size_t(__parser.nbColumns());
246  for (std::size_t i = 0; i < nb_cols; ++i) {
247  __var_names.push_back(__parser.columnName(i));
248  }
249  }
250 
251  return *this;
252  }
253 
254 
256  template < template < typename > class ALLOC >
257  DBInitializerFromSQL< ALLOC >& DBInitializerFromSQL< ALLOC >::
258  operator=(DBInitializerFromSQL< ALLOC >&& from) {
259  return operator=(from);
260  }
261 
262 
264  template < template < typename > class ALLOC >
265  INLINE std::vector< std::string, ALLOC< std::string > >
267  return __var_names;
268  }
269 
270 
272  template < template < typename > class ALLOC >
273  INLINE const std::vector< std::string, ALLOC< std::string > >&
275  return __parser.current();
276  }
277 
278 
280  template < template < typename > class ALLOC >
282  return __parser.next();
283  }
284 
285 
286  } /* namespace learning */
287 
288 } /* namespace gum */
289 
290 # endif /* DOXYGEN_SHOULD_SKIP_THIS */
291 
292 #endif /* _ODBC */
virtual DBInitializerFromSQL< ALLOC > * clone() const
virtual copy constructor
virtual bool _nextRow() final
indicates whether there is a next row to read (and point on it)
DBInitializerFromSQL(const std::string &dataSource, const std::string &login, const std::string &password, const std::string &query, long timeout=0L, const allocator_type &alloc=allocator_type())
default constructor, especially for postgresql databases
ALLOC< std::string > allocator_type
type for the allocators passed in arguments of methods
STL namespace.
allocator_type getAllocator() const
returns the allocator used
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
Definition: agrum.h:25
IDBInitializer< ALLOC > & operator=(const IDBInitializer< ALLOC > &from)
copy operator
virtual std::vector< std::string, ALLOC< std::string > > _variableNames() final
returns the names of the variables
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
virtual ~DBInitializerFromSQL()
destructor
DBInitializerFromSQL< ALLOC > & operator=(const DBInitializerFromSQL< ALLOC > &from)
copy operator
virtual const std::vector< std::string, ALLOC< std::string > > & _currentStringRow() final
returns the content of the current row using strings
#define GUM_ERROR(type, msg)
Definition: exceptions.h:55