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>
28std::vector<std::string>
split(
const std::string& s,
char delim) {
29 std::vector<std::string> elems;
30 std::stringstream ss(s);
32 while (std::getline(ss, item, delim)) {
33 elems.push_back(item);
51 db_.Execute(
"PRAGMA synchronous=OFF;");
52 db_.Execute(
"PRAGMA journal_mode=MEMORY;");
53 db_.Execute(
"PRAGMA temp_store=MEMORY;");
57 stmt = db_.Prepare(
"SELECT name FROM sqlite_master WHERE type='table';");
59 for (
int i = 0; stmt->Step(); ++i) {
60 tbl_names_.insert(stmt->GetText(0, NULL));
63 if (tbl_names_.count(
"FieldTypes") == 0) {
64 std::string cmd =
"CREATE TABLE IF NOT EXISTS FieldTypes";
65 cmd +=
"(TableName TEXT,Field TEXT,Type INTEGER);";
71 db_.Execute(
"BEGIN TRANSACTION;");
73 for (DatumList::iterator it = data.begin(); it != data.end(); ++it) {
74 std::string tbl = (*it)->title();
75 if (tbl_names_.count(tbl) == 0) {
78 if (stmts_.count(tbl) == 0) {
84 db_.Execute(
"END TRANSACTION;");
87 db_.Execute(
"END TRANSACTION;");
93std::list<ColumnInfo> SqliteBack::Schema(std::string table) {
94 std::list<ColumnInfo> schema;
96 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;
151 std::string sql =
"SELECT name FROM sqlite_master WHERE type='table';";
153 stmt = db_.Prepare(sql);
154 while (stmt->Step()) {
155 rtn.insert(stmt->GetText(0, NULL));
157 rtn.erase(
"FieldTypes");
165QueryResult SqliteBack::GetTableInfo(std::string table) {
167 "SELECT Field,Type FROM FieldTypes WHERE TableName = '" + table +
"';";
173 for (i = 0; stmt->Step(); ++i) {
174 info.
fields.push_back(stmt->GetText(0, NULL));
178 throw ValueError(
"Invalid table name " + table);
187void SqliteBack::BuildStmt(
Datum* d) {
188 std::string name = d->
title();
190 std::vector<DbTypes> schema;
192 schema.push_back(Type(vals[0].second));
193 std::string insert =
"INSERT INTO " + name +
" VALUES (?";
194 for (
int i = 1; i < vals.size(); ++i) {
195 schema.push_back(Type(vals[i].second));
200 schemas_[name] = schema;
201 stmts_[name] = db_.
Prepare(insert);
204void SqliteBack::CreateTable(
Datum* d) {
205 std::string
name = d->title();
206 tbl_names_.insert(name);
209 Datum::Vals::iterator it = vals.begin();
211 std::stringstream types;
212 types <<
"INSERT INTO FieldTypes VALUES ('" <<
name <<
"','" << it->first
213 <<
"','" << Type(it->second) <<
"');";
214 db_.Execute(types.str());
216 std::string cmd =
"CREATE TABLE " +
name +
" (";
217 cmd += std::string(it->first) +
" " + SqlType(it->second);
220 while (it != vals.end()) {
221 cmd +=
", " + std::string(it->first) +
" " + SqlType(it->second);
222 std::stringstream types;
223 types <<
"INSERT INTO FieldTypes VALUES ('" <<
name <<
"','" << it->first
224 <<
"','" << Type(it->second) <<
"');";
225 db_.Execute(types.str());
233void SqliteBack::WriteDatum(
Datum* d) {
236 std::vector<DbTypes> schema = schemas_[d->title()];
238 for (
int i = 0; i < vals.size(); ++i) {
240 Bind(v, schema[i], stmt, i + 1);
254#define CYCLUS_COMMA ,
255#define CYCLUS_BINDVAL(D, T) \
257 T vect = v.cast<T>(); \
258 std::stringstream ss; \
259 ss.imbue(std::locale("")); \
261 boost::archive::xml_oarchive ar(ss); \
262 ar& BOOST_SERIALIZATION_NVP(vect); \
265 std::string s = ss.str(); \
266 stmt->BindBlob(index, s.c_str(), s.size()); \
272 stmt->BindInt(index, v.
cast<
int>());
276 stmt->BindInt(index, v.
cast<
bool>());
280 stmt->BindDouble(index, v.
cast<
double>());
284 stmt->BindDouble(index, v.
cast<
float>());
288 std::string s = v.
cast<Blob>().str();
289 stmt->BindBlob(index, s.c_str(), s.size());
293 stmt->BindText(index, v.
cast<std::string>().c_str());
297 boost::uuids::uuid ui = v.
cast<boost::uuids::uuid>();
298 stmt->BindBlob(index, ui.data, 16);
313 std::map<std::string CYCLUS_COMMA double>);
315 std::map<std::string CYCLUS_COMMA std::string>);
317 std::map<std::string
CYCLUS_COMMA std::vector<double>>);
320 std::map<std::string
CYCLUS_COMMA std::map<int CYCLUS_COMMA double>>);
324 double CYCLUS_COMMA std::map<int CYCLUS_COMMA double>>>);
327 std::map<
int CYCLUS_COMMA std::map<std::string CYCLUS_COMMA double>>);
339 std::list<std::pair<int CYCLUS_COMMA int>>);
343 std::map<std::string CYCLUS_COMMA int>>);
348 std::pair<std::pair<double CYCLUS_COMMA double>
CYCLUS_COMMA
349 std::map<std::string CYCLUS_COMMA double>>>);
352 std::map<std::pair<std::string CYCLUS_COMMA std::string>
357 std::map<std::string CYCLUS_COMMA double>>);
360 throw ValueError(
"attempted to retrieve unsupported sqlite backend type");
374#define CYCLUS_COMMA ,
375#define CYCLUS_LOADVAL(D, T) \
377 char* data = stmt->GetText(col, NULL); \
378 std::stringstream ss; \
379 ss.imbue(std::locale("")); \
381 boost::archive::xml_iarchive ar(ss); \
383 ar& BOOST_SERIALIZATION_NVP(vect); \
390 v = stmt->GetInt(col);
394 v =
static_cast<bool>(stmt->GetInt(col));
398 v = stmt->GetDouble(col);
402 v =
static_cast<float>(stmt->GetDouble(col));
406 v = std::string(stmt->GetText(col, NULL));
411 char* s = stmt->GetText(col, &n);
412 v = Blob(std::string(s, n));
416 boost::uuids::uuid u;
417 memcpy(&u, stmt->GetText(col, NULL), 16);
432 std::map<std::string CYCLUS_COMMA double>);
435 std::map<std::string CYCLUS_COMMA std::string>);
437 std::map<std::string
CYCLUS_COMMA std::vector<double>>);
440 std::map<std::string
CYCLUS_COMMA std::map<int CYCLUS_COMMA double>>);
444 double CYCLUS_COMMA std::map<int CYCLUS_COMMA double>>>);
447 std::map<
int CYCLUS_COMMA std::map<std::string CYCLUS_COMMA double>>);
459 std::list<std::pair<int CYCLUS_COMMA int>>);
463 std::map<std::string CYCLUS_COMMA int>>);
468 std::pair<std::pair<double CYCLUS_COMMA double>
CYCLUS_COMMA
469 std::map<std::string CYCLUS_COMMA double>>>);
472 std::map<std::pair<std::string CYCLUS_COMMA std::string>
477 std::map<std::string CYCLUS_COMMA double>>);
480 throw ValueError(
"Attempted to retrieve unsupported backend type");
508 bool operator()(
const std::type_info* a,
const std::type_info* b)
const {
509 return a->before(*b);
513static std::map<const std::type_info*, DbTypes, compare>
type_map;
537 type_map[&
typeid(std::map<std::string, std::vector<double>>)] =
539 type_map[&
typeid(std::map<std::string, std::map<int, double>>)] =
542 std::map<std::string, std::pair<double, std::map<int, double>>>)] =
544 type_map[&
typeid(std::map<int, std::map<std::string, double>>)] =
547 std::map<std::string,
549 std::pair<int, std::pair<std::string, std::string>>>>)] =
553 std::map<std::string, std::pair<std::string, std::vector<double>>>)] =
556 type_map[&
typeid(std::map<std::string, std::map<std::string, int>>)] =
561 type_map[&
typeid(std::vector<std::pair<std::pair<double, double>,
562 std::map<std::string, double>>>)] =
565 type_map[&
typeid(std::map<std::pair<std::string, std::string>,
int>)] =
568 type_map[&
typeid(std::map<std::string, std::map<std::string, double>>)] =
572 const std::type_info* ti = &v.
type();
574 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.
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.
basic_hold_any< char > hold_any
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