Initial
commit
880f447196
|
@ -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)
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue