master
Mateusz Zalega 2015-11-07 19:42:28 +01:00
commit 880f447196
8 changed files with 377 additions and 0 deletions

55
Makefile Normal file
View File

@ -0,0 +1,55 @@
INC = -Isource/include -I/usr/include/zdb
LIBS = -lcairo -lqrencode -lzdb -lpthread
CXXSOURCE = $(wildcard source/*.cc)
CSOURCE = $(wildcard source/*.c)
HEADERS = $(wildcard source/include/*.h source/include/*.hh)
SOURCE = $(CSOURCE) $(CXXSOURCE)
COBJ = $(CSOURCE:source/%.c=build/%.o)
CXXOBJ = $(CXXSOURCE:source/%.cc=build/%.o)
OBJ = $(COBJ) $(CXXOBJ)
CDEPEND = $(CSOURCE:source/%.c=build/%.c.d)
CXXDEPEND = $(CXXSOURCE:source/%.cc=build/%.cc.d)
DEPEND = $(CDEPEND) $(CXXDEPEND)
.PRECIOUS: $(DEPEND) $(OBJ)
.SECONDARY: $(DEPEND) $(OBJ)
TARGETS = build/libinvdb.so
CC = gcc
CXX = g++
LD = $(CXX)
CXXFLAGS = -std=c++14 -g -fPIC
SOFLAGS = -shared
.PHONY: all depend clean mrproper
all: depend $(TARGETS)
depend: $(DEPEND)
clean:
rm -f build/*.o
rm -f $(TARGETS)
mrproper: clean
rm -f build/*.d
build/%.cc.d: source/%.cc
$(CXX) -M $< -o $@ $(INC) $(CXXFLAGS)
build/%.c.d: source/%.c
$(CXX) -M $< -o $@ $(INC) $(CXXFLAGS)
build/%.o: source/%.cc build/%.cc.d
$(CXX) -c $< -o $@ $(INC) $(CXXFLAGS)
build/%.o: source/%.c build/%.c.d
$(CC) -c $< -o $@ $(INC) $(CFLAGS)
build/%.so: $(OBJ)
$(LD) $(SOFLAGS) $(OBJ) -o $@
include $(wildcard build/*.d)

48
source/category.cc Normal file
View File

@ -0,0 +1,48 @@
#include "category.hh"
#include "session.hh"
#include <stdexcept>
#include <vector>
#include <algorithm>
#include <zdb.h>
// refer to libzdb docs
#include <Exception.h>
namespace inventory {
namespace datamodel {
const char *Category::sc_table = "categories";
Category Category::from_query(ResultSet_T r) {
Category ret;
TRY {
ret.id = ResultSet_getIntByName(r, "id");
ret.parent = ResultSet_getIntByName(r, "parent");
const char *pname = ResultSet_getStringByName(r, "name");
if (pname != NULL)
ret.name = pname;
const char *pdescription = ResultSet_getStringByName(r, "description");
if (pdescription != NULL)
ret.description = pdescription;
int symbol_size;
// returns void* by default, and std::copy needs type size info
const char *psymbol =
(const char *)(ResultSet_getBlobByName(r, "symbol", &symbol_size));
if (psymbol != NULL) {
ret.symbol.resize(symbol_size);
std::copy(psymbol, psymbol + symbol_size, std::back_inserter(ret.symbol));
}
} CATCH(SQLException) {
}
END_TRY;
return ret;
}
}
}

29
source/dbsession.cc Normal file
View File

@ -0,0 +1,29 @@
#include "session.hh"
#include <zdb.h>
#include <stdexcept>
namespace inventory {
namespace db {
DBSession::DBSession(const char *url)
: m_url(url), m_pool(NULL) {
}
void DBSession::create_connpool() {
if (m_pool == NULL) {
URL_T url = URL_new(m_url.c_str());
m_pool = ConnectionPool_new(url);
ConnectionPool_start(m_pool);
}
}
Connection_T DBSession::get_connection() {
create_connpool();
Connection_T conn = ConnectionPool_getConnection(m_pool);
if (conn == NULL)
throw std::runtime_error("Couldn't get db connection");
return conn;
}
}
}

View File

@ -0,0 +1,25 @@
#ifndef INVENTORY_CATEGORY_HH_
#define INVENTORY_CATEGORY_HH_
#include <string>
#include <vector>
#include <zdb.h>
namespace inventory {
namespace datamodel {
class Category {
public:
int id;
int parent;
std::string name;
std::string description;
std::vector<char> symbol;
static const char *sc_table;
static Category from_query(ResultSet_T);
};
}
}
#endif

24
source/include/group.hh Normal file
View File

@ -0,0 +1,24 @@
#ifndef INVENTORY_GROUP_HH_
#define INVENTORY_GROUP_HH_
#include <string>
#include <vector>
namespace inventory {
namespace datamodel {
class Group {
public:
int id;
int parent;
std::string name;
std::string description;
int style_id;
static const char *sc_table;
static Category from_query(ResultSet_T);
};
}
}
#endif

31
source/include/item.hh Normal file
View File

@ -0,0 +1,31 @@
#ifndef INVENTORY_ITEM_HH_
#define INVENTORY_ITEM_HH_
#include "session.hh"
#include <zdb.h>
#include <string>
#include <vector>
namespace inventory {
namespace datamodel {
class Item {
public:
// raw data in table order
// no need for deeper abstraction here
int id;
int parent;
std::string name;
std::string description;
unsigned int time_added;
unsigned int time_spoiled;
std::string cash_worth;
int currency_id;
static const char *sc_table;
// these may throw, can't do it in copy constructor
static Item from_query(ResultSet_T);
};
}
}
#endif

118
source/include/session.hh Normal file
View File

@ -0,0 +1,118 @@
#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

47
source/item.cc Normal file
View File

@ -0,0 +1,47 @@
#include "item.hh"
#include "session.hh"
#include <stdexcept>
#include <zdb.h>
// refer to libzdb docs
#include <Exception.h>
namespace inventory {
namespace datamodel {
const char *Item::sc_table = "items";
Item Item::from_query(ResultSet_T r) {
Item ret;
TRY {
ret.id = ResultSet_getIntByName(r, "id");
ret.parent = ResultSet_getIntByName(r, "parent");
// SQL NULL case
const char *pname = ResultSet_getStringByName(r, "name");
if (pname != NULL)
ret.name = pname;
const char *pdescription = ResultSet_getStringByName(r, "description");
if (pdescription != NULL)
ret.description = pdescription;
ret.time_added = ResultSet_getIntByName(r, "time_added");
ret.time_spoiled = ResultSet_getIntByName(r, "time_spoiled");
const char *pcashworth = ResultSet_getStringByName(r, "cash_worth");
if (pcashworth != NULL)
ret.cash_worth = pcashworth;
ret.currency_id = ResultSet_getIntByName(r, "currency_id");
} CATCH(SQLException) {
}
END_TRY;
return ret;
}
}
}