119 lines
2.5 KiB
C++
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
|