OpenASIP  2.0
SQLiteConnection.cc
Go to the documentation of this file.
1 /*
2  Copyright (c) 2002-2014 Tampere University.
3 
4  This file is part of TTA-Based Codesign Environment (TCE).
5 
6  Permission is hereby granted, free of charge, to any person obtaining a
7  copy of this software and associated documentation files (the "Software"),
8  to deal in the Software without restriction, including without limitation
9  the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  and/or sell copies of the Software, and to permit persons to whom the
11  Software is furnished to do so, subject to the following conditions:
12 
13  The above copyright notice and this permission notice shall be included in
14  all copies or substantial portions of the Software.
15 
16  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  DEALINGS IN THE SOFTWARE.
23  */
24 /**
25  * @file SQLiteConnection.cc
26  *
27  * Implementation of SQLiteConnection class.
28  *
29  * @author Pekka Jääskeläinen 2004 (pekka.jaaskelainen-no.spam-tut.fi)
30  *
31  * @note rating: red
32  */
33 
34 #include <string>
35 using std::string;
36 
37 #include "SQLiteConnection.hh"
38 #include "SQLiteQueryResult.hh"
39 
40 /**
41  * Constructor.
42  *
43  * @param connection A pointer to a SQLite connection handle.
44  */
45 SQLiteConnection::SQLiteConnection(sqlite3* connection) :
46  connection_(connection), transactionActive_(false) {
47 }
48 
49 /**
50  * Destructor.
51  *
52  * Closes the connection.
53  */
55  sqlite3_close(connection_);
56 }
57 
58 /**
59  * Performs a query that changes the database (UPDATE/INSERT/DELETE).
60  *
61  * Does not autocommit the changes in case the update is in the middle of
62  * transaction.
63  *
64  * @param queryString The query string.
65  * @return Number of rows affected by the change.
66  * @exception RelationalDBException In case a database error occured.
67  */
68 int
69 SQLiteConnection::updateQuery(const std::string& queryString) {
70  if (connection_ == NULL) {
72  __FILE__, __LINE__, "SQLiteConnection::updateQuery()",
73  "Not connected!");
74  }
75 
76  // "virtual machine" used by SQLite to execute the statements
77  sqlite3_stmt* stmt = compileQuery(queryString);
78 
79  assert(stmt != NULL);
80 
81  throwIfSQLiteError(sqlite3_step(stmt));
82  finalizeQuery(stmt);
83 
84  return sqlite3_changes(connection_);
85 }
86 
87 /**
88  * Performs a SQL Data Definition Language query, that is a query that may
89  * change the structure of the database (CREATE TABLE, etc.).
90  *
91  * Does not autocommit the changes in case the update is in the middle of
92  * transaction.
93  *
94  * @param queryString The query string.
95  * @exception RelationalDBException In case a database error occured.
96  */
97 void
98 SQLiteConnection::DDLQuery(const std::string& queryString) {
99  updateQuery(queryString);
100 }
101 
102 /**
103  * Performs a data retrieval query (SELECT).
104  *
105  * @param queryString The query string.
106  * @return A handle to the query result set.
107  * @exception RelationalDBException In case a database error occured.
108  */
110 SQLiteConnection::query(const std::string& queryString, bool init) {
111  sqlite3_stmt* stmt = compileQuery(queryString);
112  SQLiteQueryResult* result = new SQLiteQueryResult(stmt, this, init);
113  return result;
114 }
115 
116 /**
117  * Starts a new database transaction.
118  *
119  * Also ends the possible previous transaction successfully (commit).
120  *
121  * @exception RelationalDBException In case a database error occured.
122  */
123 void
125  if (transactionActive_) {
126  commit();
127  }
128  updateQuery("BEGIN;");
129  transactionActive_ = true;
130 }
131 
132 /**
133  * Ends the current database transaction unsuccessfully and rollbacks all
134  * the changes the queries in the transaction would have done.
135  *
136  * @exception RelationalDBException In case a database error occured.
137  */
138 void
140  updateQuery("ROLLBACK;");
141  transactionActive_ = false;
142 }
143 
144 /**
145  * Ends the current database transaction successfully and commits all
146  * the changes in the transaction to the database.
147  *
148  * @exception RelationalDBException In case a database error occured.
149  */
150 void
152  updateQuery("COMMIT;");
153  transactionActive_ = false;
154 }
155 
156 /**
157  * Returns the row ID of the most recent insert in the database.
158  *
159  * @return The row ID.
160  */
161 RowID
163  return sqlite3_last_insert_rowid(connection_);
164 }
165 
166 
167 /**
168  * Checks if database has given table by name.
169  *
170  * @param tableName Name of the table
171  * @return True if db has the table. Otherwise false.
172  * @exception RelationalDBException In case a database error occurred or
173  * call was made in the middle of an active
174  * transaction.
175  */
176 bool
177 SQLiteConnection::tableExistsInDB(const std::string& tableName) {
178  if (transactionActive_) {
179  throw RelationalDBException(__FILE__, __LINE__,
180  "SQLiteConnection::tableExistsInDB()",
181  "Illegal call during active transaction.");
182  }
183 
184  string query = "SELECT count(*) "
185  "FROM sqlite_master "
186  "WHERE type = 'table' and name = '" + tableName + "';";
187 
188  RelationalDBQueryResult* result = this->query(query, false);
189  assert(result->hasNext());
190  result->next();
191  const DataObject& count = result->data(0);
192 
193  int intBoolValue = 0;
194 
195  try {
196  intBoolValue = count.integerValue(); // boolValue is zero if DataObject
197  // has NULL value.
198  } catch (NumberFormatException& e) {
199  throw RelationalDBException(__FILE__, __LINE__,
200  "SQLiteConnection::tableExistsInDB()",
201  "Exception from DataObject: " + e.errorMessage());
202  }
203 
204  delete result;
205  return intBoolValue;
206 }
207 
208 /**
209  * Return number of entries in the given table.
210  *
211  * @param tableName Name of the table.
212  * @return Number of entries in table.
213  * @exception RelationalDBException In case a database error occurred,
214  * call was made in the middle of an active transaction or the table does not
215  * exists.
216  */
217 int
218 SQLiteConnection::rowCountInTable(const std::string& tableName) {
219  if (!tableExistsInDB(tableName)) {
220  throw RelationalDBException(__FILE__, __LINE__,
221  "SQLiteConnection::rowCountInTable()",
222  "Table was not found.");
223  }
224  string query = "SELECT count(*) FROM " + tableName + ";";
225 
226  RelationalDBQueryResult* result = this->query(query, false);
227  assert(result->hasNext());
228  result->next();
229  const DataObject& count = result->data(0);
230  int countAsInt = -1;
231 
232  try {
233  countAsInt = count.integerValue(); // boolValue is zero if DataObject
234  // has NULL value.
235  } catch (NumberFormatException& e) {
236  throw RelationalDBException(__FILE__, __LINE__,
237  "SQLiteConnection::tableExistsInDB()",
238  "Exception from DataObject: " + e.errorMessage());
239  }
240 
241  delete result;
242  assert(countAsInt > -1);
243  return countAsInt;
244 }
245 
246 /**
247  * Throws a RelationalDBException if result value indicates an SQLite error.
248  *
249  * @param result The value from a SQLite API call.
250  * @exception RelationalDBException Thrown if result is not SQLITE_OK.
251  */
252 void
254  if (result != SQLITE_OK && result != SQLITE_ROW &&
255  result != SQLITE_DONE) {
256 
257  string error = sqlite3_errmsg(connection_);
258  throw RelationalDBException(__FILE__, __LINE__, "", error);
259  }
260 }
261 
262 /**
263  * Compiles a SQLite query.
264  *
265  * @param queryString The SQL statement to compile.
266  * @return The SQLite virtual machine that should be used to execute the query.
267  * @exception RelationalDBException In case a database error occured.
268  */
269 sqlite3_stmt*
270 SQLiteConnection::compileQuery(const std::string& queryString) {
271  // "virtual machine" used by SQLite to execute the statements
272  sqlite3_stmt* stmt = NULL;
273  const char* dummy = NULL;
274 
275  throwIfSQLiteError(sqlite3_prepare(
276  connection_, queryString.c_str(), queryString.length(),
277  &stmt, &dummy));
278  return stmt;
279 }
280 
281 /**
282  * Finalizes a SQLite query, frees the virtual machine.
283  *
284  * Does nothing if the statement is NULL.
285  *
286  * @param statement The SQLite statement to free.
287  * @exception RelationalDBException In case there was errors (can be
288  * cumulated from a previous sqlite3_step() call).
289  */
290 void
291 SQLiteConnection::finalizeQuery(sqlite3_stmt* statement) {
292  if (statement == NULL) {
293  return;
294  }
295 
296  throwIfSQLiteError(sqlite3_finalize(statement));
297 }
298 
299 /**
300 * Return database version number.
301 *
302 * @return Database version.
303 */
304 int
306  int version = 0;
307 
308  string query = "pragma user_version;";
309 
310  RelationalDBQueryResult* result = this->query(query, false);
311 
312 
313  assert(result->hasNext());
314  result->next();
315  const DataObject& count = result->data(0);
316 
317  try {
318  version = count.integerValue();
319  } catch (NumberFormatException& e) {
320  throw RelationalDBException(__FILE__, __LINE__,
321  "SQLiteConnection::version()",
322  "Exception from DataObject: " + e.errorMessage());
323  }
324 
325  delete result;
326  return version;
327 }
328 
329 /**
330 * Set database version number.
331 *
332 * @param version New database version.
333 */
334 void
336  string query = "pragma user_version = " +
337  std::to_string(version) + ";";
338  this->updateQuery(query);
339 }
SQLiteConnection::rollback
virtual void rollback()
Definition: SQLiteConnection.cc:139
SQLiteConnection::commit
virtual void commit()
Definition: SQLiteConnection.cc:151
SQLiteConnection::rowCountInTable
virtual int rowCountInTable(const std::string &tableName)
Definition: SQLiteConnection.cc:218
NumberFormatException
Definition: Exception.hh:421
RelationalDBException
Definition: Exception.hh:692
DataObject
Definition: DataObject.hh:50
SQLiteConnection::transactionActive_
bool transactionActive_
Definition: SQLiteConnection.hh:80
RelationalDBQueryResult::data
virtual const DataObject & data(std::size_t column) const =0
Definition: RelationalDBQueryResult.cc:96
SQLiteConnection::compileQuery
sqlite3_stmt * compileQuery(const std::string &queryString)
Definition: SQLiteConnection.cc:270
SQLiteConnection.hh
SQLiteConnection::DDLQuery
virtual void DDLQuery(const std::string &queryString)
Definition: SQLiteConnection.cc:98
RowID
int RowID
Type definition of row ID in relational databases.
Definition: DBTypes.hh:37
SQLiteConnection::~SQLiteConnection
virtual ~SQLiteConnection()
Definition: SQLiteConnection.cc:54
SQLiteConnection::beginTransaction
virtual void beginTransaction()
Definition: SQLiteConnection.cc:124
RelationalDBQueryResult::hasNext
virtual bool hasNext()=0
Definition: RelationalDBQueryResult.cc:126
SQLiteConnection::version
virtual int version()
Definition: SQLiteConnection.cc:305
SQLiteConnection::query
virtual RelationalDBQueryResult * query(const std::string &queryString, bool init=true)
Definition: SQLiteConnection.cc:110
assert
#define assert(condition)
Definition: Application.hh:86
DataObject::integerValue
virtual int integerValue() const
Definition: DataObject.cc:204
RelationalDBQueryResult::next
virtual bool next()=0
Definition: RelationalDBQueryResult.cc:138
SQLiteConnection::throwIfSQLiteError
void throwIfSQLiteError(int result)
Definition: SQLiteConnection.cc:253
SQLiteConnection::updateQuery
virtual int updateQuery(const std::string &queryString)
Definition: SQLiteConnection.cc:69
dummy
SimValue dummy(32)
a dummy simvalue which is given for operands that are not bound
RelationalDBQueryResult
Definition: RelationalDBQueryResult.hh:46
SQLiteConnection::finalizeQuery
void finalizeQuery(sqlite3_stmt *statement)
Definition: SQLiteConnection.cc:291
SQLiteQueryResult
Definition: SQLiteQueryResult.hh:50
SQLiteConnection::lastInsertRowID
virtual RowID lastInsertRowID()
Definition: SQLiteConnection.cc:162
Exception::errorMessage
std::string errorMessage() const
Definition: Exception.cc:123
false
find Finds info of the inner loops in the false
Definition: InnerLoopFinder.cc:81
SQLiteConnection::connection_
sqlite3 * connection_
SQLite connection handle is saved to this.
Definition: SQLiteConnection.hh:78
SQLiteConnection::updateVersion
virtual void updateVersion(int version)
Definition: SQLiteConnection.cc:335
SQLiteQueryResult.hh
SQLiteConnection::SQLiteConnection
SQLiteConnection(sqlite3 *connection)
Definition: SQLiteConnection.cc:45
SQLiteConnection::tableExistsInDB
virtual bool tableExistsInDB(const std::string &tableName)
Definition: SQLiteConnection.cc:177