CYCLUS
sqlite_db.cc
Go to the documentation of this file.
1 #include "sqlite_db.h"
2 
3 #include <fstream>
4 #include <sqlite3.h>
5 
6 #include "datum.h"
7 #include "error.h"
8 #include "logger.h"
9 
10 namespace cyclus {
11 
13  Must(sqlite3_finalize(stmt_));
14 }
15 
17  Must(sqlite3_step(stmt_));
18  Reset();
19 }
20 
22  Must(sqlite3_reset(stmt_));
23  Must(sqlite3_clear_bindings(stmt_));
24 }
25 
27  int status = sqlite3_step(stmt_);
28  if (status == SQLITE_ROW) {
29  return true;
30  }
31  Must(status);
32  return false;
33 }
34 
35 int SqlStatement::GetInt(int col) {
36  return sqlite3_column_int(stmt_, col);
37 }
38 
39 double SqlStatement::GetDouble(int col) {
40  return sqlite3_column_double(stmt_, col);
41 }
42 
43 char* SqlStatement::GetText(int col, int* n) {
44  char* v = const_cast<char*>(reinterpret_cast<const char *>(
45  sqlite3_column_text(stmt_, col)));
46  if (n != NULL) {
47  *n = sqlite3_column_bytes(stmt_, col);
48  }
49  return v;
50 }
51 
52 void SqlStatement::BindInt(int i, int val) {
53  Must(sqlite3_bind_int(stmt_, i, val));
54 }
55 
56 void SqlStatement::BindDouble(int i, double val) {
57  Must(sqlite3_bind_double(stmt_, i, val));
58 }
59 
60 void SqlStatement::BindText(int i, const char* val) {
61  Must(sqlite3_bind_text(stmt_, i, val, -1, SQLITE_TRANSIENT));
62 }
63 
64 void SqlStatement::BindBlob(int i, const void* val, int n) {
65  Must(sqlite3_bind_blob(stmt_, i, val, n, SQLITE_TRANSIENT));
66 }
67 
68 SqlStatement::SqlStatement(sqlite3* db, std::string zSql)
69  : db_(db),
70  zSql_(zSql),
71  stmt_(NULL) {
72  Must(sqlite3_prepare_v2(db_, zSql.c_str(), -1, &stmt_, NULL));
73 }
74 
75 void SqlStatement::Must(int status) {
76  if (status != SQLITE_OK && status != SQLITE_DONE && status != SQLITE_ROW) {
77  std::string err = sqlite3_errmsg(db_);
78  throw IOError("SQL error [" + zSql_ + "]: " + err);
79  }
80 }
81 
82 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
83 SqliteDb::SqliteDb(std::string path, bool readonly)
84  : db_(NULL),
85  isOpen_(false),
86  path_(path),
87  readonly_(readonly),
88  overwrite_(false) {}
89 
90 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
92 
93 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
95  overwrite_ = true;
96 }
97 
98 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
100  if (isOpen_) {
101  if (sqlite3_close(db_) == SQLITE_OK) {
102  isOpen_ = false;
103  }
104  }
105 }
106 
107 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
109  if (isOpen_) {
110  return;
111  }
112 
113  // if the file already exists, delete it
114  if (overwrite_) {
115  std::ifstream ifile(path_.c_str());
116  if (ifile) {
117  remove(path_.c_str());
118  }
119  }
120 
121  if (readonly_ && sqlite3_open_v2(path_.c_str(), &db_, SQLITE_OPEN_READONLY,
122  NULL) == SQLITE_OK) {
123  isOpen_ = true;
124  } else if (sqlite3_open(path_.c_str(), &db_) == SQLITE_OK) {
125  isOpen_ = true;
126  } else {
127  sqlite3_close(db_);
128  throw IOError("Unable to create/open database " + path_);
129  }
130 }
131 
132 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
134  open();
135  return SqlStatement::Ptr(new SqlStatement(db_, sql));
136 }
137 
138 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
140  open();
141 
142  sqlite3_stmt* statement;
143  int result =
144  sqlite3_prepare_v2(db_, sql.c_str(), -1, &statement, NULL);
145  if (result != SQLITE_OK) {
146  std::string error = sqlite3_errmsg(db_);
147  throw IOError("SQL error: " + sql + " " + error);
148  }
149 
150  result = sqlite3_step(statement);
151  if (result != SQLITE_DONE && result != SQLITE_ROW && result != SQLITE_OK) {
152  std::string error = sqlite3_errmsg(db_);
153  throw IOError("SQL error: " + sql + " " + error);
154  }
155 
156  sqlite3_finalize(statement);
157 }
158 
159 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
160 std::vector<StrList> SqliteDb::Query(std::string sql) {
161  open();
162  sqlite3_stmt* statement;
163  // query the database
164  int check_query =
165  sqlite3_prepare_v2(db_, sql.c_str(), -1, &statement, NULL);
166  if (check_query != SQLITE_OK) {
167  std::string error = sqlite3_errmsg(db_);
168  throw IOError("SQL error: " + error);
169  }
170 
171  std::vector<StrList> results;
172  int cols = sqlite3_column_count(statement);
173  int result = 0;
174  while (true) {
175  result = sqlite3_step(statement);
176  if (result != SQLITE_ROW) {
177  break;
178  }
179 
180  StrList values;
181  for (int col = 0; col < cols; col++) {
182  std::string val;
183  char* ptr = (char*)sqlite3_column_text(statement, col);
184  if (ptr) {
185  val = ptr;
186  } else {
187  val = "";
188  }
189  values.push_back(val); // now we will never push NULL
190  }
191  results.push_back(values);
192  }
193 
194  // collect errors
195  if (result != SQLITE_DONE && result != SQLITE_OK) {
196  std::string error = sqlite3_errmsg(db_);
197  throw IOError("SQL error: " + error);
198  }
199  sqlite3_finalize(statement);
200  return results;
201 }
202 
203 } // namespace cyclus
void BindText(int i, const char *val)
Binds the templated sql parameter at index i to val.
Definition: sqlite_db.cc:60
int GetInt(int col)
Returns an int value for the specified column of the current query row.
Definition: sqlite_db.cc:35
SqlStatement::Ptr Prepare(std::string sql)
Creates a sqlite prepared statement for the given sql.
Definition: sqlite_db.cc:133
void Overwrite()
Instead of opening a file of the specified name (if it already exists), overwrite it with a new empty...
Definition: sqlite_db.cc:94
void BindBlob(int i, const void *val, int n)
Binds the templated sql parameter at index i to the value pointed to by val.
Definition: sqlite_db.cc:64
void open()
Opens the sqlite database by either opening/creating a file (default) or creating/overwriting a file ...
Definition: sqlite_db.cc:108
SqliteDb(std::string path, bool readonly=false)
Creates a new Sqlite database to be stored at the specified path.
Definition: sqlite_db.cc:83
for failed reading/writing to files, network connections, etc..
Definition: error.h:59
bool Step()
Step to next row of previously executed query.
Definition: sqlite_db.cc:26
double GetDouble(int col)
Returns a double value for the specified column of the current query row.
Definition: sqlite_db.cc:39
void BindInt(int i, int val)
Binds the templated sql parameter at index i to val.
Definition: sqlite_db.cc:52
boost::shared_ptr< SqlStatement > Ptr
Definition: sqlite_db.h:25
std::vector< std::string > StrList
Definition: sqlite_db.h:15
Code providing rudimentary logging capability for the Cyclus core.
taken directly from OsiSolverInterface.cpp on 2/17/14 from https://projects.coin-or.org/Osi/browser/trunk.
Definition: agent.cc:14
void Exec()
Executes the prepared statement.
Definition: sqlite_db.cc:16
std::vector< StrList > Query(std::string cmd)
Execute an SQL query and return its results.
Definition: sqlite_db.cc:160
void BindDouble(int i, double val)
Binds the templated sql parameter at index i to val.
Definition: sqlite_db.cc:56
void close()
Finishes any incomplete operations and closes the database.
Definition: sqlite_db.cc:99
char * GetText(int col, int *n)
Returns a byte array value for the specified column of the current query row.
Definition: sqlite_db.cc:43
void Reset()
Executes the prepared statement.
Definition: sqlite_db.cc:21
const char * sqlite3()
Definition: version.cc:46
void Execute(std::string cmd)
Execute an SQL command.
Definition: sqlite_db.cc:139
Thin wrapper class over sqlite3 prepared statements.
Definition: sqlite_db.h:22
virtual ~SqliteDb()
Definition: sqlite_db.cc:91