libinvdb/source/include/session.hh

119 lines
2.5 KiB
C++

#ifndef INVENTORY_DBSESSION_HH
#define INVENTORY_DBSESSION_HH
#include <string>
#include <vector>
#include <stdexcept>
#include <zdb.h>
namespace inventory {
namespace db {
class DBSession {
public:
DBSession(const char *url);
Connection_T get_connection();
// database accessors for use w/ datamodel types
template<class T>
T get(int id);
template<class T>
T get(const char *name);
template<class T>
std::vector<T> get_all(int offset = 0, int limit = -1);
template<class T>
T get_parent(const T &);
private:
void create_connpool();
const std::string m_url;
ConnectionPool_T m_pool;
};
template<class T>
T DBSession::get(int id) {
// We want to use underlying database's prepared
// statement system to sanititze inputs, but it's
// not possible to specify tables this way.
const std::string prepared_stmt =
std::string("SELECT * FROM ") +
T::sc_table +
std::string(" WHERE id=?");
Connection_T conn = get_connection();
PreparedStatement_T s = Connection_prepareStatement(conn,
prepared_stmt.c_str());
PreparedStatement_setInt(s, 1, id);
ResultSet_T r = PreparedStatement_executeQuery(s);
ResultSet_next(r); // with unique key, only one item is expected
if (r == NULL)
throw std::runtime_error("No such item");
T &&ret = T::from_query(r);
Connection_close(conn);
return ret;
}
template<class T>
T DBSession::get(const char *name) {
const std::string prepared_stmt =
std::string("SELECT * FROM ") +
T::sc_table +
std::string(" WHERE name=?");
Connection_T conn = get_connection();
PreparedStatement_T s = Connection_prepareStatement(conn,
prepared_stmt.c_str());
PreparedStatement_setString(s, 1, name);
ResultSet_T r = PreparedStatement_executeQuery(s);
ResultSet_next(r);
if (r == NULL)
throw std::runtime_error("No such item");
T &&ret = T::from_query(r);
Connection_close(conn);
return ret;
}
template<class T>
std::vector<T> DBSession::get_all(int offset, int limit) {
const std::string prepared_stmt =
std::string("SELECT * FROM ") +
T::sc_table +
std::string(" ORDER BY name ASC LIMIT ? OFFSET ?");
Connection_T conn = get_connection();
PreparedStatement_T s = Connection_prepareStatement(conn,
prepared_stmt.c_str());
PreparedStatement_setInt(s, 1, limit);
PreparedStatement_setInt(s, 2, offset);
ResultSet_T r = PreparedStatement_executeQuery(s);
std::vector<T> ret;
while (ResultSet_next(r)) {
T &&it = T::from_query(r);
ret.push_back(it);
}
return ret;
}
template<class T>
T DBSession::get_parent(const T &t) {
return (T&&)(get(t.id));
}
}
}
#endif