7#include <boost/lexical_cast.hpp>
8#include <boost/uuid/uuid_io.hpp>
9#include <boost/algorithm/string.hpp>
10#include <boost/archive/tmpdir.hpp>
11#include <boost/archive/xml_iarchive.hpp>
12#include <boost/archive/xml_oarchive.hpp>
13#include <boost/serialization/base_object.hpp>
14#include <boost/serialization/utility.hpp>
15#include <boost/serialization/list.hpp>
16#include <boost/serialization/set.hpp>
17#include <boost/serialization/vector.hpp>
18#include <boost/serialization/map.hpp>
19#include <boost/serialization/assume_abstract.hpp>
29std::vector<std::string>
split(
const std::string& s,
char delim) {
30 std::vector<std::string> elems;
31 std::stringstream ss(s);
33 while (std::getline(ss, item, delim)) {
34 elems.push_back(item);
52 db_.
Execute(
"PRAGMA synchronous=OFF;");
53 db_.
Execute(
"PRAGMA journal_mode=MEMORY;");
54 db_.
Execute(
"PRAGMA temp_store=MEMORY;");
58 stmt = db_.
Prepare(
"SELECT name FROM sqlite_master WHERE type='table';");
60 for (
int i = 0; stmt->Step(); ++i) {
61 tbl_names_.insert(stmt->GetText(0, NULL));
64 if (tbl_names_.count(
"FieldTypes") == 0) {
65 std::string cmd =
"CREATE TABLE IF NOT EXISTS FieldTypes";
66 cmd +=
"(TableName TEXT,Field TEXT,Type INTEGER);";
72 db_.
Execute(
"BEGIN TRANSACTION;");
74 for (DatumList::iterator it = data.begin(); it != data.end(); ++it) {
75 std::string tbl = (*it)->title();
76 if (tbl_names_.count(tbl) == 0) {
79 if (stmts_.count(tbl) == 0) {
85 db_.
Execute(
"END TRANSACTION;");
88 db_.
Execute(
"END TRANSACTION;");
94std::list<ColumnInfo> SqliteBack::Schema(std::string table) {
95 std::list<ColumnInfo> schema;
97 for (
int i = 0; i < qr.
fields.size(); ++i) {
99 schema.push_back(info);
107 std::stringstream sql;
108 sql <<
"SELECT * FROM " << table;
111 for (
int i = 0; i < conds->size(); ++i) {
115 Cond c = (*conds)[i];
116 sql << c.
field <<
" " << c.
op <<
" ?";
124 for (
int i = 0; i < conds->size(); ++i) {
126 Bind(v, Type(v), stmt, i+1);
130 for (
int i = 0; stmt->Step(); ++i) {
132 for (
int j = 0; j < q.
fields.size(); ++j) {
133 r.push_back(ColAsVal(stmt, j, q.
types[j]));
142 std::map<std::string, DbTypes> rtn;
143 for (
int i = 0; i < qr.
fields.size(); ++i)
152 std::string sql =
"SELECT name FROM sqlite_master WHERE type='table';";
155 while (stmt->Step()) {
156 rtn.insert(stmt->GetText(0, NULL));
158 rtn.erase(
"FieldTypes");
166QueryResult SqliteBack::GetTableInfo(std::string table) {
167 std::string sql =
"SELECT Field,Type FROM FieldTypes WHERE TableName = '" +
174 for (i = 0; stmt->Step(); ++i) {
175 info.
fields.push_back(stmt->GetText(0, NULL));
179 throw ValueError(
"Invalid table name " + table);
188void SqliteBack::BuildStmt(
Datum* d) {
189 std::string name = d->
title();
191 std::vector<DbTypes> schema;
193 schema.push_back(Type(vals[0].second));
194 std::string insert =
"INSERT INTO " + name +
" VALUES (?";
195 for (
int i = 1; i < vals.size(); ++i) {
196 schema.push_back(Type(vals[i].second));
201 schemas_[name] = schema;
202 stmts_[name] = db_.
Prepare(insert);
205void SqliteBack::CreateTable(Datum* d) {
206 std::string
name = d->title();
207 tbl_names_.insert(name);
210 Datum::Vals::iterator it = vals.begin();
212 std::stringstream types;
213 types <<
"INSERT INTO FieldTypes VALUES ('"
214 <<
name <<
"','" << it->first <<
"','"
215 << Type(it->second) <<
"');";
218 std::string cmd =
"CREATE TABLE " +
name +
" (";
219 cmd += std::string(it->first) +
" " + SqlType(it->second);
222 while (it != vals.end()) {
223 cmd +=
", " + std::string(it->first) +
" " + SqlType(it->second);
224 std::stringstream types;
225 types <<
"INSERT INTO FieldTypes VALUES ('"
226 <<
name <<
"','" << it->first <<
"','"
227 << Type(it->second) <<
"');";
236void SqliteBack::WriteDatum(Datum* d) {
239 std::vector<DbTypes> schema = schemas_[d->title()];
241 for (
int i = 0; i < vals.size(); ++i) {
243 Bind(v, schema[i], stmt, i+1);
257#define CYCLUS_COMMA ,
258#define CYCLUS_BINDVAL(D, T) \
260 T vect = v.cast<T>(); \
261 std::stringstream ss; \
262 ss.imbue(std::locale("")); \
264 boost::archive::xml_oarchive ar(ss); \
265 ar & BOOST_SERIALIZATION_NVP(vect); \
268 std::string s = ss.str(); \
269 stmt->BindBlob(index, s.c_str(), s.size()); \
275 stmt->BindInt(index, v.
cast<
int>());
279 stmt->BindInt(index, v.
cast<
bool>());
283 stmt->BindDouble(index, v.
cast<
double>());
287 stmt->BindDouble(index, v.
cast<
float>());
291 std::string s = v.
cast<Blob>().str();
292 stmt->BindBlob(index, s.c_str(), s.size());
296 stmt->BindText(index, v.
cast<std::string>().c_str());
300 boost::uuids::uuid ui = v.
cast<boost::uuids::uuid>();
301 stmt->BindBlob(index, ui.data, 16);
317 std::map<std::string CYCLUS_COMMA std::string>);
319 std::map<std::string
CYCLUS_COMMA std::vector<double> >);
322 std::map<std::string
CYCLUS_COMMA std::map<int CYCLUS_COMMA double> >);
325 double CYCLUS_COMMA std::map<int CYCLUS_COMMA double> > >);
328 std::map<std::string CYCLUS_COMMA double> >);
333 std::pair<std::string CYCLUS_COMMA std::string> > > >);
338 std::pair<std::string
CYCLUS_COMMA std::vector<double> > > );
344 std::map<std::string
CYCLUS_COMMA std::map<std::string CYCLUS_COMMA int> >);
348 std::vector<std::pair<
350 std::map<std::string CYCLUS_COMMA double> > > );
354 std::map<std::pair<std::string CYCLUS_COMMA std::string>
CYCLUS_COMMA int > );
358 std::map<std::string
CYCLUS_COMMA std::map<std::string CYCLUS_COMMA double> >);
361 throw ValueError(
"attempted to retrieve unsupported sqlite backend type");
376#define CYCLUS_COMMA ,
377#define CYCLUS_LOADVAL(D, T) \
379 char* data = stmt->GetText(col, NULL); \
380 std::stringstream ss; \
381 ss.imbue(std::locale("")); \
383 boost::archive::xml_iarchive ar(ss); \
385 ar & BOOST_SERIALIZATION_NVP(vect); \
392 v = stmt->GetInt(col);
395 v =
static_cast<bool>(stmt->GetInt(col));
398 v = stmt->GetDouble(col);
401 v =
static_cast<float>(stmt->GetDouble(col));
404 v = std::string(stmt->GetText(col, NULL));
408 char* s = stmt->GetText(col, &n);
409 v = Blob(std::string(s, n));
412 boost::uuids::uuid u;
413 memcpy(&u, stmt->GetText(col, NULL), 16);
430 std::map<std::string CYCLUS_COMMA std::string>);
432 std::map<std::string
CYCLUS_COMMA std::vector<double> >);
435 std::map<std::string
CYCLUS_COMMA std::map<int CYCLUS_COMMA double> >);
438 double CYCLUS_COMMA std::map<int CYCLUS_COMMA double> > >);
441 std::map<std::string CYCLUS_COMMA double> >);
446 std::pair<std::string CYCLUS_COMMA std::string> > > >);
451 std::pair<std::string
CYCLUS_COMMA std::vector<double> > > );
457 std::map<std::string
CYCLUS_COMMA std::map<std::string CYCLUS_COMMA int> >);
461 std::vector<std::pair<
463 std::map<std::string CYCLUS_COMMA double> > > );
467 std::map<std::pair<std::string CYCLUS_COMMA std::string>
CYCLUS_COMMA int > );
471 std::map<std::string
CYCLUS_COMMA std::map<std::string CYCLUS_COMMA double> >);
474 throw ValueError(
"Attempted to retrieve unsupported backend type");
501 bool operator()(
const std::type_info* a,
const std::type_info* b)
const {
502 return a->before(*b);
506static std::map<const std::type_info*, DbTypes, compare>
type_map;
530 type_map[&
typeid(std::map<std::string, std::vector<double> >)] =
532 type_map[&
typeid(std::map<std::string, std::map<int, double> >)] =
534 type_map[&
typeid(std::map<std::string,
535 std::pair<double, std::map<int, double> > >)] =
537 type_map[&
typeid(std::map<int, std::map<std::string, double> >)] =
540 std::map<std::string,
541 std::vector<std::pair<int, std::pair<std::string,
542 std::string> > > >)] =
546 std::map<std::string,
547 std::pair<std::string,
548 std::vector<double> > >)] =
551 type_map[&
typeid(std::map<std::string, std::map<std::string,int> >)] =
557 std::vector<std::pair<std::pair<double, double>,
558 std::map<std::string, double> > > )] =
562 std::map<std::pair<std::string, std::string>,
int > )] =
565 type_map[&
typeid(std::map<std::string, std::map<std::string,double> >)] =
569 const std::type_info* ti = &v.
type();
571 throw ValueError(std::string(
"unsupported backend type ") + ti->name());
boost::core::typeinfo const & type() const
A type to represent variable-length array of bytes for dumping to a cyclus output database.
Represents a condition used to filter rows returned by a query.
std::string op
One of: "<", ">", "<=", ">=", "==", "!=".
std::string field
table column name
Used to specify and send a collection of key-value pairs to the Recorder for recording.
std::vector< Entry > Vals
std::string title()
Returns the datum's title as specified during the datum's creation.
const Vals & vals()
Returns a vector of all field-value pairs that have been added to this datum.
A generic mechanism to manually manage exceptions.
virtual const char * what() const
Returns the error message associated with this Error.
Meta data and results of a query.
std::vector< QueryRow > rows
ordered results of a query
std::vector< DbTypes > types
types of each field returned by a query.
std::vector< std::string > fields
names of each field returned by a query
boost::shared_ptr< SqlStatement > Ptr
virtual std::map< std::string, DbTypes > ColumnTypes(std::string table)
Return a map of column names of the specified table to the associated database type.
virtual void Notify(DatumList data)
Writes Datum objects immediately to the database as a single transaction.
virtual std::set< std::string > Tables()
Return a set of all table names currently in the database.
virtual QueryResult Query(std::string table, std::vector< Cond > *conds)
Return a set of rows from the specificed table that match all given conditions.
std::string Name()
Returns a unique name for this backend.
SqliteDb & db()
Returns the underlying sqlite database.
SqliteBack(std::string path)
Creates a new sqlite backend that will write to the database file specified by path.
void Flush()
Executes all pending commands.
An abstraction over the Sqlite native C interface to simplify database creation and data insertion.
void open()
Opens the sqlite database by either opening/creating a file (default) or creating/overwriting a file ...
void close()
Finishes any incomplete operations and closes the database.
void Execute(std::string cmd)
Execute an SQL command.
SqlStatement::Ptr Prepare(std::string sql)
Creates a sqlite prepared statement for the given sql.
For values that are too big, too small, etc.
Code providing rudimentary logging capability for the Cyclus core.
taken directly from OsiSolverInterface.cpp on 2/17/14 from https://projects.coin-or....
std::vector< std::string > split(const std::string &s, char delim)
std::vector< Datum * > DatumList
@ LEV_ERROR
Use for errors that require agent code or input file modification (use extremely sparingly)
DbTypes
This is the primary list of all supported database types.
@ VECTOR_PAIR_PAIR_DOUBLE_DOUBLE_MAP_STRING_DOUBLE
@ MAP_STRING_MAP_STRING_DOUBLE
@ MAP_INT_MAP_STRING_DOUBLE
@ MAP_STRING_VECTOR_DOUBLE
@ MAP_STRING_VECTOR_PAIR_INT_PAIR_STRING_STRING
@ MAP_STRING_MAP_STRING_INT
@ MAP_PAIR_STRING_STRING_INT
@ MAP_STRING_PAIR_DOUBLE_MAP_INT_DOUBLE
@ MAP_STRING_PAIR_STRING_VECTOR_DOUBLE
@ MAP_STRING_MAP_INT_DOUBLE
std::vector< boost::spirit::hold_any > QueryRow
static std::map< const std::type_info *, DbTypes, compare > type_map
std::string name(int nuc)
#define CYCLUS_BINDVAL(D, T)
#define CYCLUS_LOADVAL(D, T)
Represents column information.
bool operator()(const std::type_info *a, const std::type_info *b) const