Something went wrong on our end
-
marco authored
specifically, remove LOGN_* macros and introduce new logging levels. We now have ERROR, WARNING, INFO, VERBOSE, DEBUG and TRACE. DEBUG and TRACE are turned off under NDEBUG and expand to an empty macro. new default verbosity level displays ERROR/WARNING/INFO git-svn-id: https://dng.biozentrum.unibas.ch/svn/openstructure/trunk@2709 5a81b35b-ba03-0410-adc8-b2c5c5119f08
marco authoredspecifically, remove LOGN_* macros and introduce new logging levels. We now have ERROR, WARNING, INFO, VERBOSE, DEBUG and TRACE. DEBUG and TRACE are turned off under NDEBUG and expand to an empty macro. new default verbosity level displays ERROR/WARNING/INFO git-svn-id: https://dng.biozentrum.unibas.ch/svn/openstructure/trunk@2709 5a81b35b-ba03-0410-adc8-b2c5c5119f08
compound_lib.cc 13.32 KiB
//------------------------------------------------------------------------------
// This file is part of the OpenStructure project <www.openstructure.org>
//
// Copyright (C) 2008-2010 by the OpenStructure authors
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License as published by the Free
// Software Foundation; either version 3.0 of the License, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this library; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//------------------------------------------------------------------------------
/*
Author: Marco Biasini
*/
#include <iostream>
#include <sstream>
#include <boost/format.hpp>
#include <ost/log.hh>
#include "compound_lib.hh"
using boost::format;
namespace ost { namespace conop {
namespace {
const char* CREATE_CMD[]={
"CREATE TABLE IF NOT EXISTS chem_compounds ( "
" id INTEGER PRIMARY KEY AUTOINCREMENT, "
" tlc VARCHAR(3) UNIQUE NOT NULL, "
" olc VARCHAR(1) NOT NULL, "
" chem_class VARCHAR(1), "
" formula VARCHAR(64) NOT NULL, "
" pdb_initial TIMESTAMP, "
" pdb_modified TIMESTAMP "
");",
"CREATE TABLE IF NOT EXISTS atoms ( "
" id INTEGER PRIMARY KEY AUTOINCREMENT, "
" compound_id INTEGER REFERENCES chem_compounds (id) ON DELETE CASCADE, "
" name VARCHAR(4) NOT NULL, "
" alt_name VARCHAR(4) NOT NULL, "
" element VARCHAR(2) NOT NULL, "
" is_aromatic VARCHAR(1) NOT NULL, "
" stereo_conf VARCHAR(1) NOT NULL, "
" is_leaving VARCHAR(1) NOT NULL, "
" ordinal INT "
");",
" CREATE INDEX IF NOT EXISTS atom_name_index ON atoms "
" (compound_id, name, alt_name)",
" CREATE TABLE IF NOT EXISTS bonds ( "
" id INTEGER PRIMARY KEY AUTOINCREMENT, "
" compound_id INTEGER REFERENCES chem_compounds (id) ON DELETE CASCADE, "
" atom_one INTEGER REFERENCES atoms (id) ON DELETE CASCADE, "
" atom_two INTEGER REFERENCES atoms (id) ON DELETE CASCADE, "
" bond_order INT, "
" stereo_conf VARCHAR(1) NOT NULL "
" );",
" CREATE INDEX IF NOT EXISTS bond_index ON bonds (compound_id)",
" CREATE TRIGGER delete_related_objects "
" BEFORE DELETE ON chem_compounds "
" FOR EACH ROW BEGIN "
" DELETE FROM bonds WHERE compound_id=OLD.id; "
" DELETE FROM atoms WHERE compound_id=OLD.id; "
" END",
" DROP TRIGGER IF EXISTS delete_related_objects", NULL};
const char* INSERT_COMPOUND_STATEMENT="INSERT INTO chem_compounds "
" (tlc, olc, chem_class, formula, pdb_initial, pdb_modified) "
" VALUES (?, ?, ?, ?, DATE(?), DATE(?))";
const char* INSERT_ATOM_STATEMENT="INSERT INTO atoms "
" (compound_id, name, alt_name, element, is_aromatic, stereo_conf, "
" is_leaving, ordinal) "
" VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
const char* INSERT_BOND_STATEMENT="insert into bonds "
" (compound_id, atom_one, atom_two, bond_order, stereo_conf) "
" VALUES (?, ?, ?, ?, ?)";
}
void CompoundLib::AddCompound(const CompoundPtr& compound)
{
sqlite3_stmt* stmt=NULL;
int retval=sqlite3_prepare_v2(conn_, INSERT_COMPOUND_STATEMENT,
strlen(INSERT_COMPOUND_STATEMENT), &stmt, NULL);
if (SQLITE_OK==retval) {
sqlite3_bind_text(stmt, 1, compound->GetID().c_str(),
compound->GetID().length(), NULL);
char olc=compound->GetOneLetterCode();
sqlite3_bind_text(stmt, 2, &olc, 1, NULL);
char chem_type=compound->GetChemClass();
sqlite3_bind_text(stmt, 3, &chem_type, 1, NULL);
sqlite3_bind_text(stmt, 4, compound->GetFormula().c_str(),
compound->GetFormula().length(), NULL);
std::stringstream ss;
ss << compound->GetCreationDate().year << "-"
<< compound->GetCreationDate().month << "-"
<< compound->GetCreationDate().day;
String date=ss.str();
ss.str("");
ss << compound->GetModificationDate().year << "-"
<< compound->GetModificationDate().month << "-"
<< compound->GetModificationDate().day;
sqlite3_bind_text(stmt, 5, date.c_str(), date.length(), NULL);
date=ss.str();
sqlite3_bind_text(stmt, 6, date.c_str(), date.length(), NULL);
} else {
LOG_ERROR(sqlite3_errmsg(conn_));
sqlite3_finalize(stmt);
return;
}
retval=sqlite3_step(stmt);
if (SQLITE_DONE!=retval) {
if (sqlite3_errcode(conn_)==SQLITE_CONSTRAINT) {
LOG_ERROR("Compound '" << compound->GetID() << "' already exists.");
} else {
LOG_ERROR(sqlite3_errmsg(conn_));
}
}
sqlite3_finalize(stmt);
sqlite3_int64 compound_id=sqlite3_last_insert_rowid(conn_);
// insert atoms
const AtomSpecList& al=compound->GetAtomSpecs();
std::vector<sqlite3_int64> atom_ids(al.size(), 0);
for (AtomSpecList::const_iterator i=al.begin(), e=al.end(); i!=e; ++i) {
const AtomSpec& a=*i;
retval=sqlite3_prepare_v2(conn_, INSERT_ATOM_STATEMENT,
strlen(INSERT_ATOM_STATEMENT), &stmt, NULL);
if (SQLITE_OK==retval) {
sqlite3_bind_int64(stmt, 1, compound_id);
sqlite3_bind_text(stmt, 2, a.name.c_str(), a.name.length(), NULL);
sqlite3_bind_text(stmt, 3, a.alt_name.c_str(),
a.alt_name.length(), NULL);
sqlite3_bind_text(stmt, 4, a.element.c_str(), a.element.length(), NULL);
sqlite3_bind_int(stmt, 5, a.is_aromatic);
sqlite3_bind_int(stmt, 6, 0);
sqlite3_bind_int(stmt, 7, a.is_leaving);
sqlite3_bind_int(stmt, 8, i-al.begin());
retval=sqlite3_step(stmt);
assert(retval==SQLITE_DONE);
atom_ids[i-al.begin()]=sqlite3_last_insert_rowid(conn_);
} else {
std::cout << sqlite3_errmsg(conn_) << std::endl;
}
sqlite3_finalize(stmt);
}
const BondSpecList& bl=compound->GetBondSpecs();
for (BondSpecList::const_iterator i=bl.begin(), e=bl.end(); i!=e; ++i) {
const BondSpec& b=*i;
retval=sqlite3_prepare_v2(conn_, INSERT_BOND_STATEMENT,
strlen(INSERT_BOND_STATEMENT), &stmt, NULL);
if (SQLITE_OK==retval) {
sqlite3_bind_int64(stmt, 1, compound_id);
sqlite3_bind_int64(stmt, 2, atom_ids[b.atom_one]);
sqlite3_bind_int64(stmt, 3, atom_ids[b.atom_two]);
sqlite3_bind_int(stmt, 4, b.order);
sqlite3_bind_int(stmt, 5, 0);
retval=sqlite3_step(stmt);
assert(retval==SQLITE_DONE);
} else {
std::cout << sqlite3_errmsg(conn_) << std::endl;
}
sqlite3_finalize(stmt);
}
}
CompoundLibPtr CompoundLib::Copy(const String& filename) const
{
CompoundLibPtr clone=CompoundLibPtr(new CompoundLib);
int retval=sqlite3_open(filename.c_str(), &clone->conn_);
if (SQLITE_OK==retval) {
sqlite3_backup* backup;
backup=sqlite3_backup_init(clone->conn_, "main", conn_, "main");
if (backup){
sqlite3_backup_step(backup, -1);
sqlite3_backup_finish(backup);
}
int rc=sqlite3_errcode(clone->conn_);
if (rc!=SQLITE_OK) {
std::cout << sqlite3_errmsg(clone->conn_) << std::endl;
return CompoundLibPtr();
}
return clone;
}
std::cout << sqlite3_errmsg(clone->conn_) << std::endl;
return CompoundLibPtr();
}
CompoundLibPtr CompoundLib::Create(const String& database)
{
CompoundLibPtr lib(new CompoundLib);
int retval=sqlite3_open(database.c_str(), &lib->conn_);
if (SQLITE_OK==retval) {
const char** cmd=CREATE_CMD;
while (*cmd) {
sqlite3_stmt* stmt;
retval=sqlite3_prepare_v2(lib->conn_, *cmd, strlen(*cmd), &stmt, NULL);
if (SQLITE_OK==retval) {
retval=sqlite3_step(stmt);
sqlite3_finalize(stmt);
assert(SQLITE_DONE==retval);
} else {
std::cout << sqlite3_errmsg(lib->conn_) << std::endl;
sqlite3_finalize(stmt);
return CompoundLibPtr();
}
++cmd;
}
return lib;
}
std::cout << sqlite3_errmsg(lib->conn_) << std::endl;
return CompoundLibPtr();
}
CompoundLibPtr CompoundLib::Load(const String& database)
{
CompoundLibPtr lib(new CompoundLib);
int retval=sqlite3_open(database.c_str(), &lib->conn_);
if (SQLITE_OK==retval) {
return lib;
}
std::cout << sqlite3_errmsg(lib->conn_) << std::endl;
return CompoundLibPtr();
}
void CompoundLib::LoadAtomsFromDB(CompoundPtr comp, int pk) {
String aq=str(format("SELECT name, alt_name, element, ordinal, is_leaving FROM atoms WHERE compound_id=%d ORDER BY ordinal ASC") % pk);
sqlite3_stmt* stmt;
int retval=sqlite3_prepare_v2(conn_, aq.c_str(),
static_cast<int>(aq.length()),
&stmt, NULL);
if (SQLITE_OK==retval) {
int ret=0;
while (SQLITE_ROW==(ret=sqlite3_step(stmt))) {
AtomSpec atom_sp;
atom_sp.name=String(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0)));
atom_sp.alt_name=String(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1)));
atom_sp.element=String(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 2)));
atom_sp.ordinal=sqlite3_column_int(stmt, 3);
atom_sp.is_leaving=bool(sqlite3_column_int(stmt, 4)!=0);
comp->AddAtom(atom_sp);
}
}
sqlite3_finalize(stmt);
}
void CompoundLib::ClearCache()
{
compound_cache_.clear();
}
void CompoundLib::LoadBondsFromDB(CompoundPtr comp, int pk) {
sqlite3_stmt* stmt;
String aq=str(format("SELECT a1.ordinal, a2.ordinal, b.bond_order FROM bonds AS b "
"LEFT JOIN atoms AS a1 ON b.atom_one=a1.id "
"LEFT JOIN atoms as a2 ON b.atom_two=a2.id "
"WHERE b.compound_id=%d") % pk);
int retval=sqlite3_prepare_v2(conn_, aq.c_str(),
static_cast<int>(aq.length()),
&stmt, NULL);
if (SQLITE_OK==retval) {
int ret=0;
while (SQLITE_ROW==(ret=sqlite3_step(stmt))) {
BondSpec bond_sp;
bond_sp.atom_one=sqlite3_column_int(stmt, 0);
bond_sp.atom_two=sqlite3_column_int(stmt, 1);
bond_sp.order=sqlite3_column_int(stmt, 2);
comp->AddBond(bond_sp);
}
}
sqlite3_finalize(stmt);
}
CompoundPtr CompoundLib::FindCompound(const String& id) {
CompoundMap::iterator i=compound_cache_.find(id);
if (i!=compound_cache_.end()) {
return i->second;
}
String query="select id, tlc, olc, chem_class from chem_compounds where tlc='"+id+"'";
sqlite3_stmt* stmt;
int retval=sqlite3_prepare_v2(conn_, query.c_str(),
static_cast<int>(query.length()),
&stmt, NULL);
if (SQLITE_OK==retval) {
int ret=sqlite3_step(stmt);
if (SQLITE_DONE==ret) {
sqlite3_finalize(stmt);
return CompoundPtr();
}
if (SQLITE_ROW==ret) {
int pk=sqlite3_column_int(stmt, 0);
const char* id=reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1));
CompoundPtr compound(new Compound(id));
compound->SetOneLetterCode((sqlite3_column_text(stmt, 2))[0]);
compound->SetChemClass(mol::ChemClass(sqlite3_column_text(stmt, 3)[0]));
// Load atoms and bonds
this->LoadAtomsFromDB(compound, pk);
this->LoadBondsFromDB(compound, pk);
compound_cache_.insert(std::make_pair(compound->GetID(), compound));
sqlite3_finalize(stmt);
return compound;
}
assert(SQLITE_DONE==sqlite3_step(stmt));
} else {
std::cout << "ERROR: " << sqlite3_errmsg(conn_) << std::endl;
sqlite3_finalize(stmt);
return CompoundPtr();
}
sqlite3_finalize(stmt);
return CompoundPtr();
}
CompoundLib::CompoundLib()
: conn_(NULL) {
}
CompoundLib::~CompoundLib() {
if (conn_) {
sqlite3_close(conn_);
}
}
}}