From dc8cfaa08168fdd332faded2f78679a2a1904fbe Mon Sep 17 00:00:00 2001 From: deva Date: Mon, 14 Feb 2011 10:43:17 +0000 Subject: 'Ported' export functionality from macrotool. --- server/src/admin_export.cc | 273 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 273 insertions(+) create mode 100644 server/src/admin_export.cc (limited to 'server/src/admin_export.cc') diff --git a/server/src/admin_export.cc b/server/src/admin_export.cc new file mode 100644 index 0000000..9475bc3 --- /dev/null +++ b/server/src/admin_export.cc @@ -0,0 +1,273 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set et sw=2 ts=2: */ +/*************************************************************************** + * admin_export.cc + * + * Fri Feb 11 11:43:13 CET 2011 + * Copyright 2011 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of Pracro. + * + * Pracro is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Pracro 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Pracro; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "admin_export.h" + +#include +#include +#include "debug.h" + +#ifndef WITHOUT_DB + +#include +#include + +#include "macrotool/fieldnamescanner.h" +#include "configuration.h" + +#define SEP "\t" + +static std::string escape(std::string &str) +{ + std::string out = "\""; + std::string::iterator i = str.begin(); + while(i != str.end()) { + if(*i == '\"') out += "''"; + else out += *i; + i++; + } + out += "\""; + return out; +} + +class File { +public: + File(fieldnames_t &f, pqxx::work &w) + : work(w), fieldnames(f) + { + // name += ".csf"; + // fp = fopen(name.c_str(), "w"); + + pos["id"] = 0; + pos["patientid"] = 1; + pos["time"] = 2; + pos["template"] = 3; + + //printf("%s\n", n.c_str()); + + size_t idx = 4; + fieldnames_t::iterator i = f.begin(); + while(i != f.end()) { + //printf("%s ", i->c_str()); + pos[*i] = idx; + idx++; + i++; + } + // printf("\n"); + + output_header(); + } + + ~File() + { + // if(fp) fclose(fp); + } + + void output_header() + { + beginrow(); + addcell("id", "ID"); + addcell("patientid", "Patient"); + addcell("time", "Time"); + addcell("template", "Template"); + + { + pqxx::result result = + work.exec("SELECT DISTINCT ON(name) name, caption FROM fieldnames" + " WHERE extract='true';"); + pqxx::result::const_iterator ri = result.begin(); + for(unsigned int r = 0; r < result.size(); r++) { + pqxx::result::tuple tuple = result.at(r); + std::string name = tuple.at(0).c_str(); + std::string caption = tuple.at(1).c_str(); + addcell(name, caption); + } + } + + endrow(); + } + + void beginrow() + { + cells.clear(); + cells.insert(cells.begin(), pos.size(), ""); + } + + void addcell(std::string key, std::string value) + { + if(pos.find(key) == pos.end()) return; + cells[pos[key]] = value; + } + + void endrow() + { + std::vector::iterator i = cells.begin(); + while(i != cells.end()) { + result += escape(*i) + SEP; + i++; + } + result += "\n"; + } + + std::string result; + +private: + pqxx::work &work; + std::map pos; + std::vector cells; + std::string name; + fieldnames_t &fieldnames; +}; + + +static std::string do_export(std::string templ, bool *ok) +{ + if(Conf::database_backend != "pgsql") { + *ok = false; + return "ERROR: Export only available for the pgsql database backend.\n"; + } + + std::string host = Conf::database_addr; + std::string port = "";//Conf::database_port; + std::string user = Conf::database_user;; + std::string passwd = Conf::database_passwd; + std::string dbname = "";//Conf::database_database; + + std::string cs; + if(host.size()) cs += " host=" + host; + if(port.size()) cs += " port=" + port; + if(user.size()) cs += " user=" + user; + if(passwd.size()) cs += " password=" + passwd; + cs += " dbname=" + (dbname.size() ? dbname : "pracro"); + + pqxx::connection conn(cs); + pqxx::work work(conn); + + std::set filter; + + { + pqxx::result result = + work.exec("SELECT DISTINCT name FROM fieldnames" + " WHERE extract='true';"); + pqxx::result::const_iterator ri = result.begin(); + for(unsigned int r = 0; r < result.size(); r++) { + pqxx::result::tuple tuple = result.at(r); + std::string name = tuple.at(0).c_str(); + filter.insert(name); + //printf("filter: '%s'\n", name.c_str()); + } + } + + templates_t t = scanfieldnames(filter); + /* + templates_t::iterator ti = t.begin(); + while(ti != t.end()) { + printf("%s\n", ti->first.c_str()); + fieldnames_t::iterator fi = ti->second.begin(); + while(fi != ti->second.end()) { + printf("\t%s\n", (*fi).c_str()); + fi++; + } + ti++; + } + */ + + File file(t[templ], work); + + { + pqxx::result result = + work.exec("SELECT * FROM commits WHERE template='"+templ+"'" + " AND status='committed' ORDER BY patientid, timestamp;"); + pqxx::result::const_iterator ri = result.begin(); + for(unsigned int r = 0; r < result.size(); r++) { + pqxx::result::tuple tuple = result.at(r); + std::string patientid = tuple.at(0).c_str(); + std::string templ = tuple.at(1).c_str(); + std::string version = tuple.at(2).c_str(); + std::string timestamp = tuple.at(3).c_str(); + std::string uid = tuple.at(4).c_str(); + std::string status = tuple.at(5).c_str(); + + file.beginrow(); + file.addcell("id", uid); + file.addcell("patientid", patientid); + file.addcell("template", templ); + time_t t = atol(timestamp.c_str()); + std::string timestr = ctime(&t); + if(timestr[timestr.size() - 1] == '\n') + timestr = timestr.substr(0, timestr.size() - 1); + file.addcell("time", timestr.c_str()); + + DEBUG(export, "%s %s %s\n", + timestamp.c_str(), patientid.c_str(), templ.c_str()); + + { + pqxx::result result = + work.exec("SELECT f.name, f.value" + " FROM transactions t, fields f, fieldnames n" + " WHERE t.cid='"+uid+"' AND f.transaction=t.uid" + " AND f.name=n.name AND n.extract='true'" + " ORDER BY t.timestamp;"); + pqxx::result::const_iterator ri = result.begin(); + for(unsigned int r = 0; r < result.size(); r++) { + pqxx::result::tuple tuple = result.at(r); + std::string name = tuple.at(0).c_str(); + std::string value = tuple.at(1).c_str(); + + file.addcell(name, value); + + } + } + + file.endrow(); + } + } + + *ok = true; + return file.result; +} + +#endif/* WITHOUT_DB */ + +std::string admin_export(Environment &env, std::string templ, bool *ok) +{ + return do_export(templ, ok); +} + +#ifdef TEST_ADMIN_EXPORT +//deps: +//cflags: +//libs: +#include "test.h" + +TEST_BEGIN; + +// TODO: Put some testcode here (see test.h for usable macros). + +TEST_END; + +#endif/*TEST_ADMIN_EXPORT*/ -- cgit v1.2.3