/** * A SQLite3 interface */ #ifndef DB_H #define DB_H 1 #include "Common/InsOrderedMap.h" #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #if _SQL # include #endif typedef std::vector > dbVec; // for output typedef InsOrderedMap dbMap; // for input typedef std::vector dbVars; class DB { private: dbMap statMap; dbVars initVars, peVars; #if _SQL sqlite3* db; sqlite3_stmt* stmt; #else void* db; void* stmt; #endif std::string prog, cmd; int exp; // Verbosity inherited from the equivalent abyss-pe option. int verbose_val; std::string getSqliteName() { std::string name("dummy"); // for a program running outside of abyss-pe std::fstream fl("name.txt"); if (fl) fl >> name; return name; } void openDB( const char* c, const int& v) { #if _SQL verbose_val = v; if (sqlite3_open(c, &db)) { std::cerr << "[" << prog << "] Can't open DB.\n"; exit(EXIT_FAILURE); } else { if (verbose_val >= 2 && exp != READ) std::cerr << "[" << prog << "] DB opened.\n"; } #else (void)v; (void)c; #endif } static int callback( void* info, int argc, char** argv, char** colName) { int i; std::cerr << (const char*)info << std::endl; for (i=0; i= 2 && exp != READ) std::cerr << "[" << prog << "] DB closed.\n"; } #else return; #endif } void createTables(); void insertToMetaTables(const dbVars&); std::string initializeRun(); std::string getPath(const std::string&); bool definePeVars(const std::string&); void assemblyStatsToDb(); public: enum { NO_INIT, INIT, READ }; DB() { // suppress unused variable warnings under clang++ (void)db; (void)stmt; initVars.resize(3); peVars.resize(3); exp = NO_INIT; } ~DB() { if (exp == INIT) assemblyStatsToDb(); if (exp != NO_INIT) closeDB(); } friend void init( DB& d, const std::string& path) { #if _SQL d.exp = READ; d.openDB(path.c_str(), 0); #else (void)d; (void)path; std::cerr << "error: `db` parameter has been used, but ABySS has not been configured to support SQLite.\n"; exit(EXIT_FAILURE); #endif } friend void init( DB& d, const std::string& path, const int& v, const std::string& program, const std::string& command, const dbVars& vars) { #if _SQL d.prog = program; d.cmd = command; d.initVars = vars; d.exp = INIT; std::string name(d.getSqliteName()); d.openDB(path.empty() ? name.c_str() : path.c_str(), v); #else (void)d; (void)path; (void)v; (void)program; (void)command; (void)vars; std::cerr << "error: `db` parameter has been used, but ABySS has not been configured to support SQLite.\n"; exit(EXIT_FAILURE); #endif } std::string activateForeignKey(const std::string& s) { std::string s_pragma("pragma foreign_keys=on; "); return s_pragma += s; } bool query(const std::string& s) { #if _SQL int rc; unsigned long int n; char* errMsg = 0; std::string new_s(activateForeignKey(s)); const char* statement = new_s.c_str(); n = 1; do { rc = sqlite3_exec(db, statement, callback, 0, &errMsg); if (rc == SQLITE_OK) return true; n++; usleep(getRand()); } while (rc == SQLITE_BUSY && n < 30000000); // adhoc timeout if (rc != SQLITE_OK) { std::cerr << "[" << prog << "] SQL error: " << errMsg << std::endl; sqlite3_free(errMsg); exit(EXIT_FAILURE); } #else (void)s; #endif return true; } friend void addToDb( DB& d, const std::string& key, const int& value) { d.statMap.push_back(key, value); } friend void addToDb( DB& d, dbMap m) { d.statMap.insert(m.getAC()); m.clear(); } dbVec readSqlToVec(const std::string&); std::string getProperTableName(const std::string&); }; #endif