Let's make (git) history!

This commit is contained in:
2018-11-03 17:12:20 +01:00
commit 3bfebfe8a8
212 changed files with 11970 additions and 0 deletions

25
database/categorydao.cpp Normal file
View File

@ -0,0 +1,25 @@
/* Copyright (c) 2018 Albert S.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "categorydao.h"
CategoryDao::CategoryDao()
{
}

20
database/categorydao.h Normal file
View File

@ -0,0 +1,20 @@
#ifndef CATEGORYDAO_H
#define CATEGORYDAO_H
#include <string>
#include <vector>
#include <optional>
#include "queryoption.h"
#include "../category.h"
class CategoryDao
{
public:
CategoryDao();
virtual void save(const Category &c) = 0;
virtual std::vector<std::string> fetchList(QueryOption o) = 0;
virtual std::optional<Category> find(std::string name) = 0;
virtual void deleteCategory(std::string name) = 0;
virtual std::vector<std::string> fetchMembers(std::string name, QueryOption o) = 0;
};
#endif // CATEGORYDAO_H

View File

@ -0,0 +1,122 @@
/* Copyright (c) 2018 Albert S.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include <string>
#include <vector>
#include "categorydaosqlite.h"
#include "sqlitequeryoption.h"
CategoryDaoSqlite::CategoryDaoSqlite()
{
}
std::optional<Category> CategoryDaoSqlite::find(std::string name)
{
try
{
Category result;
*db << "SELECT id, name FROM category WHERE name = ?" << name >> std::tie(result.id, result.name);
return result;
}
catch(const sqlite::exceptions::no_rows &e)
{
return {};
}
catch(sqlite::sqlite_exception &e)
{
throwFrom(e);
}
}
void CategoryDaoSqlite::save(const Category &c)
{
try
{
*db << "INSERT OR IGNORE INTO category (id, name) VALUES (SELECT id FROM category WHERE lower(name) = "
"lower(?), lower(?)"
<< c.name << c.name;
}
catch(sqlite::sqlite_exception &e)
{
throwFrom(e);
}
}
void CategoryDaoSqlite::deleteCategory(std::string name)
{
try
{
*db << "BEGIN";
*db << "DELETE FROM categorymember WHERE catid = (SELECT id FROM category WHERE name = ?)" << name;
*db << "DELETE FROM category WHERE name = ?" << name;
*db << "COMMIT;";
}
catch(sqlite::sqlite_exception &e)
{
throwFrom(e);
}
}
std::vector<std::string> CategoryDaoSqlite::fetchList(QueryOption o)
{
std::vector<std::string> result;
try
{
auto queryoption = SqliteQueryOption(o).setPrependWhere(true).setOrderByColumn("name").build();
*db << "SELECT name FROM category " + queryoption >> [&](std::string n) { result.push_back(n); };
}
catch(const sqlite::exceptions::no_rows &e)
{
return result;
}
catch(const sqlite::sqlite_exception &e)
{
throwFrom(e);
}
return result;
}
std::vector<std::string> CategoryDaoSqlite::fetchMembers(std::string name, QueryOption o)
{
std::vector<std::string> result;
SqliteQueryOption queryOption{o};
std::string queryoptions =
queryOption.setOrderByColumn("name").setVisibleColumnName("page.visible").setPrependWhere(false).build();
try
{
auto query = *db << "SELECT page.name AS name FROM categorymember INNER JOIN page ON page.id = "
"categorymember.page WHERE category = (SELECT id FROM category WHERE name = ? ) AND " +
queryoptions
<< name;
query >> [&](std::string p) { result.push_back(p); };
}
catch(const sqlite::exceptions::no_rows &e)
{
return result;
}
catch(sqlite::sqlite_exception &e)
{
throwFrom(e);
}
return result;
}

View File

@ -0,0 +1,18 @@
#ifndef CATEGORYDAOSQLITE_H
#define CATEGORYDAOSQLITE_H
#include "categorydao.h"
#include "sqlitedao.h"
class CategoryDaoSqlite : public CategoryDao, protected SqliteDao
{
public:
CategoryDaoSqlite();
std::vector<std::string> fetchList(QueryOption o) override;
std::vector<std::string> fetchMembers(std::string name, QueryOption o) override;
void save(const Category &c) override;
void deleteCategory(std::string name) override;
std::optional<Category> find(std::string name) override;
using SqliteDao::SqliteDao;
};
#endif // CATEGORYDAOSQLITE_H

40
database/database.h Normal file
View File

@ -0,0 +1,40 @@
#ifndef DATABASE_H
#define DATABASE_H
#include <memory>
#include <string>
#include "../user.h"
#include "../request.h"
#include "../response.h"
#include "pagedao.h"
#include "revisiondao.h"
#include "sessiondao.h"
#include "userdao.h"
#include "categorydao.h"
class Database
{
private:
std::string connnectionstring;
public:
Database()
{
}
Database(std::string connstring)
{
this->connnectionstring = connstring;
}
virtual void beginTransaction() = 0;
virtual void rollbackTransaction() = 0;
virtual void commitTransaction() = 0;
virtual std::unique_ptr<PageDao> createPageDao() const = 0;
virtual std::unique_ptr<RevisionDao> createRevisionDao() const = 0;
virtual std::unique_ptr<SessionDao> createSessionDao() const = 0;
virtual std::unique_ptr<UserDao> createUserDao() const = 0;
virtual std::unique_ptr<CategoryDao> createCategoryDao() const = 0;
virtual ~Database()
{
}
};
#endif

View File

@ -0,0 +1,26 @@
/* Copyright (c) 2018 Albert S.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "databasefactory.h"
#include "sqlite.h"
std::unique_ptr<Database> createDatabase(const Config &o)
{
return std::make_unique<Sqlite>(o.connectionstring);
}

View File

@ -0,0 +1,7 @@
#ifndef DATABASEFACTORY_H
#define DATABASEFACTORY_H
#include "../config.h"
#include "database.h"
std::unique_ptr<Database> createDatabase(const Config &o);
#endif // DATABASEFACTORY_H

15
database/exceptions.h Normal file
View File

@ -0,0 +1,15 @@
#ifndef EXCEPTIONS_H
#define EXCEPTIONS_H
#include <stdexcept>
class DatabaseException : public std::runtime_error
{
using std::runtime_error::runtime_error;
};
class DatabaseQueryException : public DatabaseException
{
using DatabaseException::DatabaseException;
};
#endif // EXCEPTIONS_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,100 @@
#pragma once
#include <string>
#include <stdexcept>
#include <sqlite3.h>
namespace sqlite
{
class sqlite_exception : public std::runtime_error
{
public:
sqlite_exception(const char *msg, std::string sql, int code = -1) : runtime_error(msg), code(code), sql(sql)
{
}
sqlite_exception(int code, std::string sql) : runtime_error(sqlite3_errstr(code)), code(code), sql(sql)
{
}
int get_code() const
{
return code & 0xFF;
}
int get_extended_code() const
{
return code;
}
std::string get_sql() const
{
return sql;
}
private:
int code;
std::string sql;
};
namespace errors
{
// One more or less trivial derived error class for each SQLITE error.
// Note the following are not errors so have no classes:
// SQLITE_OK, SQLITE_NOTICE, SQLITE_WARNING, SQLITE_ROW, SQLITE_DONE
//
// Note these names are exact matches to the names of the SQLITE error codes.
#define SQLITE_MODERN_CPP_ERROR_CODE(NAME, name, derived) \
class name : public sqlite_exception \
{ \
using sqlite_exception::sqlite_exception; \
}; \
derived
#define SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(BASE, SUB, base, sub) \
class base##_##sub : public base \
{ \
using base::base; \
};
#include "lists/error_codes.h"
#undef SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED
#undef SQLITE_MODERN_CPP_ERROR_CODE
// Some additional errors are here for the C++ interface
class more_rows : public sqlite_exception
{
using sqlite_exception::sqlite_exception;
};
class no_rows : public sqlite_exception
{
using sqlite_exception::sqlite_exception;
};
class more_statements : public sqlite_exception
{
using sqlite_exception::sqlite_exception;
}; // Prepared statements can only contain one statement
class invalid_utf16 : public sqlite_exception
{
using sqlite_exception::sqlite_exception;
};
static void throw_sqlite_error(const int &error_code, const std::string &sql = "")
{
switch(error_code & 0xFF)
{
#define SQLITE_MODERN_CPP_ERROR_CODE(NAME, name, derived) \
case SQLITE_##NAME: \
switch(error_code) \
{ \
derived default : throw name(error_code, sql); \
}
#define SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(BASE, SUB, base, sub) \
case SQLITE_##BASE##_##SUB: \
throw base##_##sub(error_code, sql);
#include "lists/error_codes.h"
#undef SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED
#undef SQLITE_MODERN_CPP_ERROR_CODE
default:
throw sqlite_exception(error_code, sql);
}
}
} // namespace errors
namespace exceptions = errors;
} // namespace sqlite

View File

@ -0,0 +1,90 @@
#if SQLITE_VERSION_NUMBER < 3010000
#define SQLITE_IOERR_VNODE (SQLITE_IOERR | (27 << 8))
#define SQLITE_IOERR_AUTH (SQLITE_IOERR | (28 << 8))
#define SQLITE_AUTH_USER (SQLITE_AUTH | (1 << 8))
#endif
SQLITE_MODERN_CPP_ERROR_CODE(ERROR, error, )
SQLITE_MODERN_CPP_ERROR_CODE(INTERNAL, internal, )
SQLITE_MODERN_CPP_ERROR_CODE(PERM, perm, )
SQLITE_MODERN_CPP_ERROR_CODE(ABORT, abort, SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(ABORT, ROLLBACK, abort, rollback))
SQLITE_MODERN_CPP_ERROR_CODE(BUSY, busy,
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(BUSY, RECOVERY, busy, recovery)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(BUSY, SNAPSHOT, busy, snapshot))
SQLITE_MODERN_CPP_ERROR_CODE(LOCKED, locked,
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(LOCKED, SHAREDCACHE, locked, sharedcache))
SQLITE_MODERN_CPP_ERROR_CODE(NOMEM, nomem, )
SQLITE_MODERN_CPP_ERROR_CODE(READONLY, readonly, )
SQLITE_MODERN_CPP_ERROR_CODE(INTERRUPT, interrupt, )
SQLITE_MODERN_CPP_ERROR_CODE(
IOERR, ioerr,
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(IOERR, READ, ioerr, read) SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(
IOERR, SHORT_READ, ioerr,
short_read) SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(IOERR, WRITE, ioerr,
write) SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(IOERR, FSYNC,
ioerr, fsync)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(IOERR, DIR_FSYNC, ioerr, dir_fsync) SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(
IOERR, TRUNCATE, ioerr,
truncate) SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(IOERR, FSTAT, ioerr,
fstat) SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(IOERR, UNLOCK,
ioerr, unlock)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(IOERR, RDLOCK, ioerr, rdlock) SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(
IOERR, DELETE, ioerr, delete) SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(IOERR, BLOCKED, ioerr, blocked)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(IOERR, NOMEM, ioerr, nomem) SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(
IOERR, ACCESS, ioerr, access) SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(IOERR, CHECKRESERVEDLOCK, ioerr,
checkreservedlock)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(IOERR, LOCK, ioerr, lock)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(IOERR, CLOSE, ioerr, close)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(IOERR, DIR_CLOSE, ioerr, dir_close)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(IOERR, SHMOPEN, ioerr, shmopen)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(IOERR, SHMSIZE, ioerr, shmsize)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(IOERR, SHMLOCK, ioerr, shmlock)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(IOERR, SHMMAP, ioerr, shmmap)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(IOERR, SEEK, ioerr, seek)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(IOERR, DELETE_NOENT, ioerr,
delete_noent)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(IOERR, MMAP, ioerr, mmap)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(IOERR, GETTEMPPATH,
ioerr, gettemppath)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(IOERR, CONVPATH,
ioerr, convpath)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(IOERR, VNODE,
ioerr, vnode)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(
IOERR, AUTH, ioerr, auth))
SQLITE_MODERN_CPP_ERROR_CODE(CORRUPT, corrupt, SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(CORRUPT, VTAB, corrupt, vtab))
SQLITE_MODERN_CPP_ERROR_CODE(NOTFOUND, notfound, )
SQLITE_MODERN_CPP_ERROR_CODE(FULL, full, )
SQLITE_MODERN_CPP_ERROR_CODE(CANTOPEN, cantopen,
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(CANTOPEN, NOTEMPDIR, cantopen, notempdir)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(CANTOPEN, ISDIR, cantopen, isdir)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(CANTOPEN, FULLPATH, cantopen, fullpath)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(CANTOPEN, CONVPATH, cantopen, convpath))
SQLITE_MODERN_CPP_ERROR_CODE(PROTOCOL, protocol, )
SQLITE_MODERN_CPP_ERROR_CODE(EMPTY, empty, )
SQLITE_MODERN_CPP_ERROR_CODE(SCHEMA, schema, )
SQLITE_MODERN_CPP_ERROR_CODE(TOOBIG, toobig, )
SQLITE_MODERN_CPP_ERROR_CODE(
CONSTRAINT, constraint,
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(CONSTRAINT, CHECK, constraint, check)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(CONSTRAINT, COMMITHOOK, constraint, commithook)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(CONSTRAINT, FOREIGNKEY, constraint, foreignkey)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(CONSTRAINT, FUNCTION, constraint, function)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(CONSTRAINT, NOTNULL, constraint, notnull)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(CONSTRAINT, PRIMARYKEY, constraint, primarykey)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(CONSTRAINT, TRIGGER, constraint, trigger)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(CONSTRAINT, UNIQUE, constraint, unique)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(CONSTRAINT, VTAB, constraint, vtab)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(CONSTRAINT, ROWID, constraint, rowid))
SQLITE_MODERN_CPP_ERROR_CODE(MISMATCH, mismatch, )
SQLITE_MODERN_CPP_ERROR_CODE(MISUSE, misuse, )
SQLITE_MODERN_CPP_ERROR_CODE(NOLFS, nolfs, )
SQLITE_MODERN_CPP_ERROR_CODE(AUTH, auth, )
SQLITE_MODERN_CPP_ERROR_CODE(FORMAT, format, )
SQLITE_MODERN_CPP_ERROR_CODE(RANGE, range, )
SQLITE_MODERN_CPP_ERROR_CODE(NOTADB, notadb, )
SQLITE_MODERN_CPP_ERROR_CODE(NOTICE, notice,
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(NOTICE, RECOVER_WAL, notice, recover_wal)
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(NOTICE, RECOVER_ROLLBACK, notice,
recover_rollback))
SQLITE_MODERN_CPP_ERROR_CODE(WARNING, warning,
SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(WARNING, AUTOINDEX, warning, autoindex))

View File

@ -0,0 +1,124 @@
#include "errors.h"
#include <sqlite3.h>
#include <utility>
#include <tuple>
#include <type_traits>
namespace sqlite
{
namespace detail
{
template <class> using void_t = void;
template <class T, class = void> struct is_callable : std::false_type
{
};
template <class Functor, class... Arguments>
struct is_callable<Functor(Arguments...), void_t<decltype(std::declval<Functor>()(std::declval<Arguments>()...))>>
: std::true_type
{
};
template <class Functor, class... Functors> class FunctorOverload : public Functor, public FunctorOverload<Functors...>
{
public:
template <class Functor1, class... Remaining>
FunctorOverload(Functor1 &&functor, Remaining &&...remaining)
: Functor(std::forward<Functor1>(functor)), FunctorOverload<Functors...>(std::forward<Remaining>(remaining)...)
{
}
using Functor::operator();
using FunctorOverload<Functors...>::operator();
};
template <class Functor> class FunctorOverload<Functor> : public Functor
{
public:
template <class Functor1> FunctorOverload(Functor1 &&functor) : Functor(std::forward<Functor1>(functor))
{
}
using Functor::operator();
};
template <class Functor> class WrapIntoFunctor : public Functor
{
public:
template <class Functor1> WrapIntoFunctor(Functor1 &&functor) : Functor(std::forward<Functor1>(functor))
{
}
using Functor::operator();
};
template <class ReturnType, class... Arguments> class WrapIntoFunctor<ReturnType (*)(Arguments...)>
{
ReturnType (*ptr)(Arguments...);
public:
WrapIntoFunctor(ReturnType (*ptr)(Arguments...)) : ptr(ptr)
{
}
ReturnType operator()(Arguments... arguments)
{
return (*ptr)(std::forward<Arguments>(arguments)...);
}
};
inline void store_error_log_data_pointer(std::shared_ptr<void> ptr)
{
static std::shared_ptr<void> stored;
stored = std::move(ptr);
}
template <class T> std::shared_ptr<typename std::decay<T>::type> make_shared_inferred(T &&t)
{
return std::make_shared<typename std::decay<T>::type>(std::forward<T>(t));
}
} // namespace detail
template <class Handler>
typename std::enable_if<!detail::is_callable<Handler(const sqlite_exception &)>::value>::type error_log(
Handler &&handler);
template <class Handler>
typename std::enable_if<detail::is_callable<Handler(const sqlite_exception &)>::value>::type error_log(
Handler &&handler);
template <class... Handler> typename std::enable_if<sizeof...(Handler) >= 2>::type error_log(Handler &&...handler)
{
return error_log(detail::FunctorOverload<detail::WrapIntoFunctor<typename std::decay<Handler>::type>...>(
std::forward<Handler>(handler)...));
}
template <class Handler>
typename std::enable_if<!detail::is_callable<Handler(const sqlite_exception &)>::value>::type error_log(
Handler &&handler)
{
return error_log(std::forward<Handler>(handler), [](const sqlite_exception &) {});
}
template <class Handler>
typename std::enable_if<detail::is_callable<Handler(const sqlite_exception &)>::value>::type error_log(
Handler &&handler)
{
auto ptr = detail::make_shared_inferred(
[handler = std::forward<Handler>(handler)](int error_code, const char *errstr) mutable {
switch(error_code & 0xFF)
{
#define SQLITE_MODERN_CPP_ERROR_CODE(NAME, name, derived) \
case SQLITE_##NAME: \
switch(error_code) \
{ \
derived default : handler(errors::name(errstr, "", error_code)); \
}; \
break;
#define SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(BASE, SUB, base, sub) \
case SQLITE_##BASE##_##SUB: \
handler(errors::base##_##sub(errstr, "", error_code)); \
break;
#include "lists/error_codes.h"
#undef SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED
#undef SQLITE_MODERN_CPP_ERROR_CODE
default:
handler(sqlite_exception(errstr, "", error_code));
}
});
sqlite3_config(
SQLITE_CONFIG_LOG,
(void (*)(void *, int, const char *))[](void *functor, int error_code, const char *errstr) {
(*static_cast<decltype(ptr.get())>(functor))(error_code, errstr);
},
ptr.get());
detail::store_error_log_data_pointer(std::move(ptr));
}
} // namespace sqlite

View File

@ -0,0 +1,53 @@
#pragma once
#ifndef SQLITE_HAS_CODEC
#define SQLITE_HAS_CODEC
#endif
#include "../sqlite_modern_cpp.h"
namespace sqlite
{
struct sqlcipher_config : public sqlite_config
{
std::string key;
};
class sqlcipher_database : public database
{
public:
sqlcipher_database(std::string db, const sqlcipher_config &config) : database(db, config)
{
set_key(config.key);
}
sqlcipher_database(std::u16string db, const sqlcipher_config &config) : database(db, config)
{
set_key(config.key);
}
void set_key(const std::string &key)
{
if(auto ret = sqlite3_key(_db.get(), key.data(), key.size()))
errors::throw_sqlite_error(ret);
}
void set_key(const std::string &key, const std::string &db_name)
{
if(auto ret = sqlite3_key_v2(_db.get(), db_name.c_str(), key.data(), key.size()))
errors::throw_sqlite_error(ret);
}
void rekey(const std::string &new_key)
{
if(auto ret = sqlite3_rekey(_db.get(), new_key.data(), new_key.size()))
errors::throw_sqlite_error(ret);
}
void rekey(const std::string &new_key, const std::string &db_name)
{
if(auto ret = sqlite3_rekey_v2(_db.get(), db_name.c_str(), new_key.data(), new_key.size()))
errors::throw_sqlite_error(ret);
}
};
} // namespace sqlite

View File

@ -0,0 +1,40 @@
#pragma once
#include <tuple>
#include <type_traits>
namespace sqlite
{
namespace utility
{
template <typename> struct function_traits;
template <typename Function>
struct function_traits : public function_traits<decltype(&std::remove_reference<Function>::type::operator())>
{
};
template <typename ClassType, typename ReturnType, typename... Arguments>
struct function_traits<ReturnType (ClassType::*)(Arguments...) const> : function_traits<ReturnType (*)(Arguments...)>
{
};
/* support the non-const operator ()
* this will work with user defined functors */
template <typename ClassType, typename ReturnType, typename... Arguments>
struct function_traits<ReturnType (ClassType::*)(Arguments...)> : function_traits<ReturnType (*)(Arguments...)>
{
};
template <typename ReturnType, typename... Arguments> struct function_traits<ReturnType (*)(Arguments...)>
{
typedef ReturnType result_type;
template <std::size_t Index> using argument = typename std::tuple_element<Index, std::tuple<Arguments...>>::type;
static const std::size_t arity = sizeof...(Arguments);
};
} // namespace utility
} // namespace sqlite

View File

@ -0,0 +1,34 @@
#pragma once
#include <cassert>
#include <exception>
#include <iostream>
namespace sqlite
{
namespace utility
{
#ifdef __cpp_lib_uncaught_exceptions
class UncaughtExceptionDetector
{
public:
operator bool()
{
return count != std::uncaught_exceptions();
}
private:
int count = std::uncaught_exceptions();
};
#else
class UncaughtExceptionDetector
{
public:
operator bool()
{
return std::uncaught_exception();
}
};
#endif
} // namespace utility
} // namespace sqlite

View File

@ -0,0 +1,45 @@
#pragma once
#include <locale>
#include <string>
#include <algorithm>
#include "../errors.h"
namespace sqlite
{
namespace utility
{
inline std::string utf16_to_utf8(const std::u16string &input)
{
struct : std::codecvt<char16_t, char, std::mbstate_t>
{
} codecvt;
std::mbstate_t state{};
std::string result((std::max)(input.size() * 3 / 2, std::size_t(4)), '\0');
const char16_t *remaining_input = input.data();
std::size_t produced_output = 0;
while(true)
{
char *used_output;
switch(codecvt.out(state, remaining_input, &input[input.size()], remaining_input, &result[produced_output],
&result[result.size() - 1] + 1, used_output))
{
case std::codecvt_base::ok:
result.resize(used_output - result.data());
return result;
case std::codecvt_base::noconv:
// This should be unreachable
case std::codecvt_base::error:
throw errors::invalid_utf16("Invalid UTF-16 input", "");
case std::codecvt_base::partial:
if(used_output == result.data() + produced_output)
throw errors::invalid_utf16("Unexpected end of input", "");
produced_output = used_output - result.data();
result.resize(result.size() +
(std::max)((&input[input.size()] - remaining_input) * 3 / 2, std::ptrdiff_t(4)));
}
}
}
} // namespace utility
} // namespace sqlite

View File

@ -0,0 +1,230 @@
#pragma once
#include "../errors.h"
#include <sqlite3.h>
#include <optional>
#include <variant>
namespace sqlite::utility
{
template <typename... Options> struct VariantFirstNullable
{
using type = void;
};
template <typename T, typename... Options> struct VariantFirstNullable<T, Options...>
{
using type = typename VariantFirstNullable<Options...>::type;
};
#ifdef MODERN_SQLITE_STD_OPTIONAL_SUPPORT
template <typename T, typename... Options> struct VariantFirstNullable<std::optional<T>, Options...>
{
using type = std::optional<T>;
};
#endif
template <typename T, typename... Options> struct VariantFirstNullable<std::unique_ptr<T>, Options...>
{
using type = std::unique_ptr<T>;
};
template <typename... Options> struct VariantFirstNullable<std::nullptr_t, Options...>
{
using type = std::nullptr_t;
};
template <typename Callback, typename... Options> inline void variant_select_null(Callback &&callback)
{
if constexpr(std::is_same_v<typename VariantFirstNullable<Options...>::type, void>)
{
throw errors::mismatch("NULL is unsupported by this variant.", "", SQLITE_MISMATCH);
}
else
{
std::forward<Callback>(callback)(typename VariantFirstNullable<Options...>::type());
}
}
template <typename... Options> struct VariantFirstIntegerable
{
using type = void;
};
template <typename T, typename... Options> struct VariantFirstIntegerable<T, Options...>
{
using type = typename VariantFirstIntegerable<Options...>::type;
};
#ifdef MODERN_SQLITE_STD_OPTIONAL_SUPPORT
template <typename T, typename... Options> struct VariantFirstIntegerable<std::optional<T>, Options...>
{
using type = std::conditional_t<std::is_same_v<typename VariantFirstIntegerable<T, Options...>::type, T>,
std::optional<T>, typename VariantFirstIntegerable<Options...>::type>;
};
#endif
template <typename T, typename... Options>
struct VariantFirstIntegerable<
std::enable_if_t<std::is_same_v<typename VariantFirstIntegerable<T, Options...>::type, T>>, std::unique_ptr<T>,
Options...>
{
using type = std::conditional_t<std::is_same_v<typename VariantFirstIntegerable<T, Options...>::type, T>,
std::unique_ptr<T>, typename VariantFirstIntegerable<Options...>::type>;
};
template <typename... Options> struct VariantFirstIntegerable<int, Options...>
{
using type = int;
};
template <typename... Options> struct VariantFirstIntegerable<sqlite_int64, Options...>
{
using type = sqlite_int64;
};
template <typename Callback, typename... Options> inline auto variant_select_integer(Callback &&callback)
{
if constexpr(std::is_same_v<typename VariantFirstIntegerable<Options...>::type, void>)
{
throw errors::mismatch("Integer is unsupported by this variant.", "", SQLITE_MISMATCH);
}
else
{
std::forward<Callback>(callback)(typename VariantFirstIntegerable<Options...>::type());
}
}
template <typename... Options> struct VariantFirstFloatable
{
using type = void;
};
template <typename T, typename... Options> struct VariantFirstFloatable<T, Options...>
{
using type = typename VariantFirstFloatable<Options...>::type;
};
#ifdef MODERN_SQLITE_STD_OPTIONAL_SUPPORT
template <typename T, typename... Options> struct VariantFirstFloatable<std::optional<T>, Options...>
{
using type = std::conditional_t<std::is_same_v<typename VariantFirstFloatable<T, Options...>::type, T>,
std::optional<T>, typename VariantFirstFloatable<Options...>::type>;
};
#endif
template <typename T, typename... Options> struct VariantFirstFloatable<std::unique_ptr<T>, Options...>
{
using type = std::conditional_t<std::is_same_v<typename VariantFirstFloatable<T, Options...>::type, T>,
std::unique_ptr<T>, typename VariantFirstFloatable<Options...>::type>;
};
template <typename... Options> struct VariantFirstFloatable<float, Options...>
{
using type = float;
};
template <typename... Options> struct VariantFirstFloatable<double, Options...>
{
using type = double;
};
template <typename Callback, typename... Options> inline auto variant_select_float(Callback &&callback)
{
if constexpr(std::is_same_v<typename VariantFirstFloatable<Options...>::type, void>)
{
throw errors::mismatch("Real is unsupported by this variant.", "", SQLITE_MISMATCH);
}
else
{
std::forward<Callback>(callback)(typename VariantFirstFloatable<Options...>::type());
}
}
template <typename... Options> struct VariantFirstTextable
{
using type = void;
};
template <typename T, typename... Options> struct VariantFirstTextable<T, Options...>
{
using type = typename VariantFirstTextable<void, Options...>::type;
};
#ifdef MODERN_SQLITE_STD_OPTIONAL_SUPPORT
template <typename T, typename... Options> struct VariantFirstTextable<std::optional<T>, Options...>
{
using type = std::conditional_t<std::is_same_v<typename VariantFirstTextable<T, Options...>::type, T>,
std::optional<T>, typename VariantFirstTextable<Options...>::type>;
};
#endif
template <typename T, typename... Options> struct VariantFirstTextable<std::unique_ptr<T>, Options...>
{
using type = std::conditional_t<std::is_same_v<typename VariantFirstTextable<T, Options...>::type, T>,
std::unique_ptr<T>, typename VariantFirstTextable<Options...>::type>;
};
template <typename... Options> struct VariantFirstTextable<std::string, Options...>
{
using type = std::string;
};
template <typename... Options> struct VariantFirstTextable<std::u16string, Options...>
{
using type = std::u16string;
};
template <typename Callback, typename... Options> inline void variant_select_text(Callback &&callback)
{
if constexpr(std::is_same_v<typename VariantFirstTextable<Options...>::type, void>)
{
throw errors::mismatch("Text is unsupported by this variant.", "", SQLITE_MISMATCH);
}
else
{
std::forward<Callback>(callback)(typename VariantFirstTextable<Options...>::type());
}
}
template <typename... Options> struct VariantFirstBlobable
{
using type = void;
};
template <typename T, typename... Options> struct VariantFirstBlobable<T, Options...>
{
using type = typename VariantFirstBlobable<Options...>::type;
};
#ifdef MODERN_SQLITE_STD_OPTIONAL_SUPPORT
template <typename T, typename... Options> struct VariantFirstBlobable<std::optional<T>, Options...>
{
using type = std::conditional_t<std::is_same_v<typename VariantFirstBlobable<T, Options...>::type, T>,
std::optional<T>, typename VariantFirstBlobable<Options...>::type>;
};
#endif
template <typename T, typename... Options> struct VariantFirstBlobable<std::unique_ptr<T>, Options...>
{
using type = std::conditional_t<std::is_same_v<typename VariantFirstBlobable<T, Options...>::type, T>,
std::unique_ptr<T>, typename VariantFirstBlobable<Options...>::type>;
};
template <typename T, typename A, typename... Options>
struct VariantFirstBlobable<std::enable_if_t<std::is_pod_v<T>>, std::vector<T, A>, Options...>
{
using type = std::vector<T, A>;
};
template <typename Callback, typename... Options> inline auto variant_select_blob(Callback &&callback)
{
if constexpr(std::is_same_v<typename VariantFirstBlobable<Options...>::type, void>)
{
throw errors::mismatch("Blob is unsupported by this variant.", "", SQLITE_MISMATCH);
}
else
{
std::forward<Callback>(callback)(typename VariantFirstBlobable<Options...>::type());
}
}
template <typename... Options> inline auto variant_select(int type)
{
return [type](auto &&callback) {
using Callback = decltype(callback);
switch(type)
{
case SQLITE_NULL:
variant_select_null<Callback, Options...>(std::forward<Callback>(callback));
break;
case SQLITE_INTEGER:
variant_select_integer<Callback, Options...>(std::forward<Callback>(callback));
break;
case SQLITE_FLOAT:
variant_select_float<Callback, Options...>(std::forward<Callback>(callback));
break;
case SQLITE_TEXT:
variant_select_text<Callback, Options...>(std::forward<Callback>(callback));
break;
case SQLITE_BLOB:
variant_select_blob<Callback, Options...>(std::forward<Callback>(callback));
break;
default:;
/* assert(false); */
}
};
}
} // namespace sqlite::utility

25
database/pagedao.cpp Normal file
View File

@ -0,0 +1,25 @@
/* Copyright (c) 2018 Albert S.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "pagedao.h"
PageDao::PageDao()
{
}

30
database/pagedao.h Normal file
View File

@ -0,0 +1,30 @@
#ifndef PAGEDAO_H
#define PAGEDAO_H
#include <string>
#include <optional>
#include <vector>
#include "queryoption.h"
#include "../page.h"
#include "../searchresult.h"
class PageDao
{
public:
PageDao();
virtual bool exists(std::string page) const = 0;
virtual bool exists(int id) const = 0;
virtual std::optional<Page> find(std::string name) = 0;
virtual std::optional<Page> find(int id) = 0;
virtual std::vector<std::string> getPageList(QueryOption option) = 0;
virtual std::vector<std::string> fetchCategories(std::string pagename, QueryOption option) = 0;
virtual void deletePage(std::string page) = 0;
virtual void save(const Page &page) = 0;
// TODO: this may not be the correct place for this.
virtual void setCategories(std::string pagename, const std::vector<std::string> &catnames) = 0;
virtual std::vector<SearchResult> search(std::string query, QueryOption option) = 0;
virtual ~PageDao()
{
}
};
#endif // PAGEDAO_H

207
database/pagedaosqlite.cpp Normal file
View File

@ -0,0 +1,207 @@
/* Copyright (c) 2018 Albert S.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include <sqlite_modern_cpp/errors.h>
#include "pagedaosqlite.h"
#include "exceptions.h"
#include "sqlitequeryoption.h"
#include "../logger.h"
/* TODO: copied from C version mostly, review whether access to table other than page is ok */
bool PageDaoSqlite::exists(int id) const
{
auto binder = *db << "SELECT 1 from page WHERE id = ?" << id;
return execBool(binder);
}
bool PageDaoSqlite::exists(std::string name) const
{
auto binder = *db << "SELECT 1 FROM page WHERE name = ?" << name;
return execBool(binder);
}
std::optional<Page> PageDaoSqlite::find(std::string name)
{
int pageid = fetchPageId(name);
return find(pageid);
}
std::optional<Page> PageDaoSqlite::find(int id)
{
Page result;
try
{
auto ps = *db << "SELECT name, lastrevision, visible FROM page WHERE id = ?";
ps << id >> std::tie(result.name, result.current_revision, result.listed);
}
catch(const sqlite::errors::no_rows &e)
{
return {};
}
catch(sqlite::sqlite_exception &e)
{
throwFrom(e);
}
return result;
}
void PageDaoSqlite::deletePage(std::string page)
{
int pageId = this->fetchPageId(page);
// TODO on delete cascade is better most certainly
try
{
*db << "BEGIN;";
*db << "DELETE FROM revision WHERE page = ?;" << pageId;
*db << "DELETE FROM categorymember WHERE page = ?;" << pageId;
*db << "DELETE FROM permissions WHERE page = ?;" << pageId;
*db << "DELETE FROM page WHERE id =?;" << pageId;
*db << "COMMIT;";
}
catch(sqlite::sqlite_exception &e)
{
throwFrom(e);
}
}
void PageDaoSqlite::save(const Page &page)
{
try
{
*db << "INSERT INTO page (name, lastrevision, visible) VALUES(?, ?, ?)" << page.name << page.current_revision
<< page.listed;
}
catch(sqlite::sqlite_exception &e)
{
throwFrom(e);
}
}
std::vector<std::string> PageDaoSqlite::getPageList(QueryOption option)
{
std::vector<std::string> result;
try
{
std::string queryOption = SqliteQueryOption(option)
.setOrderByColumn("lower(name)")
.setVisibleColumnName("visible")
.setPrependWhere(true)
.build();
std::string query = "SELECT name FROM page " + queryOption;
*db << query >> [&](std::string name) { result.push_back(name); };
}
catch(const sqlite::errors::no_rows &e)
{
return result;
}
catch(sqlite::sqlite_exception &e)
{
throwFrom(e);
}
return result;
}
std::vector<std::string> PageDaoSqlite::fetchCategories(std::string pagename, QueryOption option)
{
std::vector<std::string> result;
try
{
auto query = *db << "SELECT name FROM categorymember INNNER JOIN category ON category = category.id WHERE page "
"= (SELECT id FROM page WHERE name = ?)"
<< pagename;
query << " AND " << SqliteQueryOption(option).setPrependWhere(false).setOrderByColumn("name").build();
query >> [&](std::string pagename) { result.push_back(pagename); };
}
catch(const sqlite::exceptions::no_rows &e)
{
return result;
}
catch(sqlite::sqlite_exception &e)
{
throwFrom(e);
}
return result;
}
std::vector<SearchResult> PageDaoSqlite::search(std::string name, QueryOption option)
{
std::vector<SearchResult> result;
try
{
std::string qo = SqliteQueryOption(option).setPrependWhere(false).setOrderByColumn("rank").build();
// TODO: what is passed here, simple gets thrown to the MATCH operator without escaping or anything and this is
// suboptimal
auto query =
*db << "SELECT page.name FROM search INNER JOIN page ON search.page = page.id WHERE search MATCH ? "
<< name;
query >> [&](std::string pagename) {
SearchResult sresult;
sresult.pagename = pagename;
sresult.query = name;
result.push_back(sresult);
};
}
catch(const sqlite::exceptions::no_rows &e)
{
return result;
}
catch(sqlite::sqlite_exception &e)
{
throwFrom(e);
}
return result;
}
void PageDaoSqlite::setCategories(std::string pagename, const std::vector<std::string> &catnames)
{
try
{
int pageid = fetchPageId(pagename);
*db << "savepoint setcategories;";
*db << "DELETE FROM categorymember WHERE page = ?" << pageid;
for(const std::string &cat : catnames)
{
*db << "INSERT OR IGNORE INTO category (id, name) VALUES( (SELECT id FROM category WHERE lower(name) = "
"lower(?)), lower(?))"
<< cat << cat;
*db << "INSERT INTO categorymember (category, page) VALUES ( (SELECT ID FROM category WHERE lower(name) = "
"lower(?)), ?)"
<< cat << pageid;
}
*db << "release setcategories;";
}
catch(sqlite::sqlite_exception &e)
{
throwFrom(e);
}
}
int PageDaoSqlite::fetchPageId(std::string pagename)
{
auto binder = *db << "SELECT id FROM page WHERE name = ?" << pagename;
return execInt(binder);
}

29
database/pagedaosqlite.h Normal file
View File

@ -0,0 +1,29 @@
#ifndef PAGEDAOSQLITE_H
#define PAGEDAOSQLITE_H
#include <string>
#include <optional>
#include <sqlite3.h>
#include "../page.h"
#include "pagedao.h"
#include "sqlitedao.h"
class PageDaoSqlite : public PageDao, protected SqliteDao
{
public:
PageDaoSqlite()
{
}
void deletePage(std::string page) override;
bool exists(int id) const override;
bool exists(std::string name) const override;
void save(const Page &page) override;
std::optional<Page> find(std::string name) override;
std::optional<Page> find(int id) override;
std::vector<std::string> getPageList(QueryOption option) override;
std::vector<std::string> fetchCategories(std::string pagename, QueryOption option) override;
using SqliteDao::SqliteDao;
int fetchPageId(std::string pagename);
std::vector<SearchResult> search(std::string query, QueryOption option) override;
void setCategories(std::string pagename, const std::vector<std::string> &catnames) override;
};
#endif // PAGEDAOSQLITE_H

View File

@ -0,0 +1,25 @@
/* Copyright (c) 2018 Albert S.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "permissionsdao.h"
PermissionsDao::PermissionsDao()
{
}

12
database/permissionsdao.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef PERMISSIONSDAO_H
#define PERMISSIONSDAO_H
#include "../permissions.h"
#include "../user.h"
class PermissionsDao
{
public:
PermissionsDao();
virtual Permissions find(std::string pagename, std::string username) = 0;
};
#endif // PERMISSIONSDAO_H

View File

@ -0,0 +1,31 @@
/* Copyright (c) 2018 Albert S.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "permissionsdaosqlite.h"
PermissionsDaoSqlite::PermissionsDaoSqlite()
{
}
Permissions PermissionsDaoSqlite::find(std::string pagename, std::string username)
{
/* auto query = *db << "SELECT COALESCE( (SELECT permissions FROM permissions WHERE page = ? AND userid = ?),
(SELECT permissions FROM user WHERE ID = ?))"; exec*/
}

View File

@ -0,0 +1,15 @@
#ifndef PERMISSIONSDAOSQLITE_H
#define PERMISSIONSDAOSQLITE_H
#include "permissionsdao.h"
#include "sqlitedao.h"
class PermissionsDaoSqlite : public PermissionsDao, protected SqliteDao
{
public:
PermissionsDaoSqlite();
Permissions find(std::string pagename, std::string username) override;
using SqliteDao::SqliteDao;
};
#endif // PERMISSIONSDAOSQLITE_H

21
database/queryoption.cpp Normal file
View File

@ -0,0 +1,21 @@
/* Copyright (c) 2018 Albert S.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "queryoption.h"

19
database/queryoption.h Normal file
View File

@ -0,0 +1,19 @@
#ifndef QUERYOPTION_H
#define QUERYOPTION_H
enum SORT_ORDER
{
ASCENDING = 0,
DESCENDING
};
class QueryOption
{
public:
unsigned int offset = 0;
unsigned int limit = 0;
SORT_ORDER order = ASCENDING;
bool includeInvisible = true;
};
#endif // QUERYOPTION_H

21
database/revisiondao.cpp Normal file
View File

@ -0,0 +1,21 @@
/* Copyright (c) 2018 Albert S.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "revisiondao.h"

23
database/revisiondao.h Normal file
View File

@ -0,0 +1,23 @@
#ifndef REVISIONDAO_H
#define REVISIONDAO_H
#include <vector>
#include <optional>
#include "../revision.h"
#include "queryoption.h"
class RevisionDao
{
public:
virtual void save(const Revision &revision) = 0;
virtual std::vector<Revision> getAllRevisions(QueryOption &options) = 0;
virtual std::vector<Revision> getAllRevisionsForPage(std::string pagename, QueryOption &option) = 0;
virtual std::optional<Revision> getCurrentForPage(std::string pagename) = 0;
virtual std::optional<Revision> getRevisionForPage(std::string pagnename, unsigned int revision) = 0;
virtual unsigned int countTotalRevisions() = 0;
virtual unsigned int countTotalRevisions(std::string pagename) = 0;
virtual ~RevisionDao()
{
}
};
#endif // REVISIONDAO_H

View File

@ -0,0 +1,174 @@
/* Copyright (c) 2018 Albert S.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "revisiondaosqlite.h"
#include "exceptions.h"
#include "sqlitequeryoption.h"
#include "../utils.h"
RevisionDaoSqlite::RevisionDaoSqlite()
{
}
void RevisionDaoSqlite::save(const Revision &revision)
{
try
{
*db << "savepoint revisionsubmit;";
*db << "INSERT INTO revision(author, comment, content, creationtime, page, revisionid) VALUES((SELECT id FROM "
"user WHERE username = ?), ?, ?, DATETIME(), (SELECT id FROM page WHERE name = ?), (SELECT "
"lastrevision+1 FROM page WHERE id = (SELECT id FROM page WHERE name = ?)));"
<< revision.author << revision.comment << revision.content << revision.page << revision.page;
*db << "UPDATE page SET lastrevision=lastrevision+1 WHERE name = ?; " << revision.page;
*db << "release revisionsubmit;";
}
catch(sqlite::sqlite_exception &e)
{
throwFrom(e);
}
}
std::vector<Revision> RevisionDaoSqlite::getAllRevisions(QueryOption &options)
{
std::vector<Revision> result;
try
{
SqliteQueryOption queryOption{options};
std::string queryOptionSql = queryOption.setPrependWhere(true).setOrderByColumn("id").build();
auto query = *db << "SELECT author, comment, content, strftime('%s',creationtime), (SELECT name FROM page "
"WHERE page.id = page ), revisionid FROM revision " +
queryOptionSql;
query >> [&](std::string author, std::string comment, std::string content, time_t creationtime,
std::string page, unsigned int revisionid) {
Revision r;
r.author = author;
r.comment = comment;
r.content = content;
r.timestamp = creationtime;
r.page = page;
r.revision = revisionid;
result.push_back(r);
};
}
catch(const sqlite::errors::no_rows &e)
{
return result;
}
catch(sqlite::sqlite_exception &e)
{
throwFrom(e);
}
return result;
}
std::vector<Revision> RevisionDaoSqlite::getAllRevisionsForPage(std::string pagename, QueryOption &option)
{
std::vector<Revision> result;
try
{
SqliteQueryOption queryOption{option};
std::string queryOptionSql = queryOption.setPrependWhere(false).setOrderByColumn("id").build();
auto query = *db << "SELECT (SELECT username FROM user WHERE id = author), comment, content, "
"strftime('%s',creationtime), (SELECT name FROM page WHERE page.id = page ), revisionid "
"FROM revision WHERE page = (SELECT id FROM page WHERE name = ?) " +
queryOptionSql
<< pagename;
query >> [&](std::string author, std::string comment, std::string content, time_t creationtime,
std::string page, unsigned int revisionid) {
Revision r;
r.author = author;
r.comment = comment;
r.content = content;
r.timestamp = creationtime;
r.page = page;
r.revision = revisionid;
result.push_back(r);
};
}
catch(const sqlite::errors::no_rows &e)
{
return result;
}
catch(sqlite::sqlite_exception &e)
{
throwFrom(e);
}
return result;
}
std::optional<Revision> RevisionDaoSqlite::getCurrentForPage(std::string pagename)
{
Revision result;
try
{
auto query = *db << "SELECT (SELECT username FROM user WHERE id = author), comment, content, "
"strftime('%s',creationtime), page, revisionid FROM revision WHERE page = (SELECT id FROM "
"page WHERE name = ? ) AND revisionid = (SELECT lastrevision FROM page WHERE name = ?)";
query << pagename << pagename;
query >>
std::tie(result.author, result.comment, result.content, result.timestamp, result.page, result.revision);
}
catch(const sqlite::errors::no_rows &e)
{
return {};
}
catch(sqlite::sqlite_exception &e)
{
throwFrom(e);
}
return result;
}
std::optional<Revision> RevisionDaoSqlite::getRevisionForPage(std::string pagename, unsigned int revision)
{
Revision result;
try
{
auto query =
*db
<< "SELECT (SELECT username FROM user WHERE id = author), comment, content, strftime('%s',creationtime), "
"page, revisionid FROM revision WHERE page = (SELECT id FROM page WHERE name = ? ) AND revisionid = ?";
query << pagename << revision;
query >>
std::tie(result.author, result.comment, result.content, result.timestamp, result.page, result.revision);
}
catch(const sqlite::exceptions::no_rows &e)
{
return {};
}
return result;
}
unsigned int RevisionDaoSqlite::countTotalRevisions()
{
auto query = *db << "SELECT COUNT(ROWID) FROM revision";
return static_cast<unsigned int>(execInt(query));
}
unsigned int RevisionDaoSqlite::countTotalRevisions(std::string page)
{
auto query = *db << "SELECT COUNT(ROWID) FROM revision WHERE page = (SELECT id FROM page WHERE name = ?)" << page;
return static_cast<unsigned int>(execInt(query));
}

View File

@ -0,0 +1,21 @@
#ifndef REVISIONDAOSQLITE_H
#define REVISIONDAOSQLITE_H
#include <sqlite3.h>
#include "revisiondao.h"
#include "sqlitedao.h"
class RevisionDaoSqlite : public RevisionDao, protected SqliteDao
{
public:
RevisionDaoSqlite();
void save(const Revision &revision) override;
std::vector<Revision> getAllRevisions(QueryOption &options) override;
std::vector<Revision> getAllRevisionsForPage(std::string pagename, QueryOption &option) override;
std::optional<Revision> getCurrentForPage(std::string pagename) override;
std::optional<Revision> getRevisionForPage(std::string pagnename, unsigned int revision) override;
unsigned int countTotalRevisions() override;
unsigned int countTotalRevisions(std::string pagename) override;
using SqliteDao::SqliteDao;
};
#endif // REVISIONDAOSQLITE_H

25
database/sessiondao.cpp Normal file
View File

@ -0,0 +1,25 @@
/* Copyright (c) 2018 Albert S.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "sessiondao.h"
SessionDao::SessionDao()
{
}

18
database/sessiondao.h Normal file
View File

@ -0,0 +1,18 @@
#ifndef SESSIONDAO_H
#define SESSIONDAO_H
#include <string>
#include <optional>
#include "../session.h"
class SessionDao
{
public:
SessionDao();
virtual void save(const Session &session) = 0;
virtual std::optional<Session> find(std::string token) = 0;
virtual void deleteSession(std::string token) = 0;
virtual ~SessionDao()
{
}
};
#endif // SESSIONDAO_H

View File

@ -0,0 +1,94 @@
/* Copyright (c) 2018 Albert S.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "sessiondaosqlite.h"
#include "userdaosqlite.h"
void SessionDaoSqlite::save(const Session &session)
{
try
{
// TODO: we do not store creationtime
auto q = *db << "INSERT OR REPLACE INTO session(id, token, csrf_token, creationtime, userid) VALUES((SELECT id "
"FROM session WHERE token = ?), ?, ?, DATETIME(), (SELECT id FROM user WHERE username = ?))";
q << session.token << session.token << session.csrf_token << session.user.login;
q.execute();
}
catch(sqlite::sqlite_exception &e)
{
throwFrom(e);
}
}
void SessionDaoSqlite::deleteSession(std::string token)
{
try
{
auto stmt = *db << "DELETE FROM session WHERE token = ?" << token;
stmt.execute();
}
catch(sqlite::sqlite_exception &e)
{
throwFrom(e);
}
}
std::optional<Session> SessionDaoSqlite::find(std::string token)
{
Session result;
try
{
std::string username;
auto q = *db << "SELECT userid, token, csrf_token, strftime('%s', creationtime) FROM session WHERE token = ?"
<< token;
int userid;
q >> std::tie(userid, result.token, result.csrf_token, result.creation_time);
if(userid > -1)
{
UserDaoSqlite userDao{this->db};
auto u = userDao.find(userid);
if(u)
{
result.user = *u;
}
else
{
Logger::error() << "Session for non existent user";
throw DatabaseQueryException("Session for non existent user");
}
}
else
{
result.user = User::Anonymous();
}
result.loggedIn = userid != -1;
}
catch(const sqlite::exceptions::no_rows &e)
{
return {};
}
catch(sqlite::sqlite_exception &e)
{
throwFrom(e);
}
return result;
}

View File

@ -0,0 +1,17 @@
#ifndef SESSIONDAOSQLITE_H
#define SESSIONDAOSQLITE_H
#include "sessiondao.h"
#include "../session.h"
#include "sqlitedao.h"
class SessionDaoSqlite : public SessionDao, protected SqliteDao
{
public:
SessionDaoSqlite();
void save(const Session &session) override;
std::optional<Session> find(std::string token) override;
void deleteSession(std::string token) override;
using SqliteDao::SqliteDao;
};
#endif // SESSIONDAOSQLITE_H

86
database/sqlite.cpp Normal file
View File

@ -0,0 +1,86 @@
/* Copyright (c) 2018 Albert S.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "sqlite.h"
#include "../logger.h"
#include "pagedaosqlite.h"
#include "revisiondaosqlite.h"
#include "sessiondaosqlite.h"
#include "userdaosqlite.h"
#include "categorydaosqlite.h"
#include "exceptions.h"
Sqlite::Sqlite(std::string path) : Database(path)
{
this->db = std::make_shared<sqlite::database>(path);
*db << "PRAGMA journal_mode=WAL;";
}
std::unique_ptr<RevisionDao> Sqlite::createRevisionDao() const
{
return create<RevisionDaoSqlite>();
}
std::unique_ptr<PageDao> Sqlite::createPageDao() const
{
return create<PageDaoSqlite>();
}
std::unique_ptr<UserDao> Sqlite::createUserDao() const
{
return create<UserDaoSqlite>();
}
std::unique_ptr<SessionDao> Sqlite::createSessionDao() const
{
return create<SessionDaoSqlite>();
}
std::unique_ptr<CategoryDao> Sqlite::createCategoryDao() const
{
return create<CategoryDaoSqlite>();
}
void Sqlite::beginTransaction()
{
if(!inTransaction)
{
*db << "begin;";
inTransaction = true;
}
}
void Sqlite::rollbackTransaction()
{
if(inTransaction)
{
*db << "rollback;";
inTransaction = false;
}
}
void Sqlite::commitTransaction()
{
if(inTransaction)
{
*db << "commit;";
inTransaction = false;
}
}

31
database/sqlite.h Normal file
View File

@ -0,0 +1,31 @@
#ifndef SQLITE_H
#define SQLITE_H
#include <string>
#include <sqlite3.h>
#include <sqlite_modern_cpp.h>
#include "database.h"
class Sqlite : public Database
{
private:
bool inTransaction = false;
std::shared_ptr<sqlite::database> db;
template <class T> std::unique_ptr<T> create() const
{
return std::make_unique<T>(db);
}
public:
Sqlite(std::string path);
std::unique_ptr<PageDao> createPageDao() const;
std::unique_ptr<RevisionDao> createRevisionDao() const;
std::unique_ptr<UserDao> createUserDao() const;
std::unique_ptr<SessionDao> createSessionDao() const;
std::unique_ptr<CategoryDao> createCategoryDao() const;
void beginTransaction();
void commitTransaction();
void rollbackTransaction();
};
#endif // SQLITE_H

51
database/sqlitedao.cpp Normal file
View File

@ -0,0 +1,51 @@
/* Copyright (c) 2018 Albert S.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "sqlitedao.h"
bool SqliteDao::execBool(sqlite::database_binder &binder) const
{
bool result;
try
{
bool result;
binder >> result;
return result;
}
catch(sqlite::sqlite_exception &e)
{
// TODO: well, we may want to check whether rows have found or not and thus log this here
return false;
}
}
int SqliteDao::execInt(sqlite::database_binder &binder) const
{
try
{
int result;
binder >> result;
return result;
}
catch(sqlite::sqlite_exception &e)
{
throwFrom(e);
}
}

42
database/sqlitedao.h Normal file
View File

@ -0,0 +1,42 @@
#ifndef SQLITEDAO_H
#define SQLITEDAO_H
#include <string_view>
#include <sqlite3.h>
#include <stdarg.h>
#include <sqlite_modern_cpp.h>
#include <sqlite_modern_cpp/errors.h>
#include "queryoption.h"
#include "exceptions.h"
#include "../logger.h"
class SqliteDao
{
protected:
std::shared_ptr<sqlite::database> db;
public:
SqliteDao()
{
}
SqliteDao(std::shared_ptr<sqlite::database> db)
{
this->db = db;
}
void setDb(std::shared_ptr<sqlite::database> db)
{
this->db = db;
}
inline void throwFrom(const sqlite::sqlite_exception &e) const
{
std::string msg = "Sqlite Error: " + std::to_string(e.get_code()) + " SQL: " + e.get_sql();
Logger::error() << msg << " Extended code: " << e.get_extended_code();
throw DatabaseQueryException(msg);
}
bool execBool(sqlite::database_binder &binder) const;
int execInt(sqlite::database_binder &binder) const;
};
#endif // SQLITEDAO_H

View File

@ -0,0 +1,72 @@
/* Copyright (c) 2018 Albert S.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "sqlitequeryoption.h"
SqliteQueryOption::SqliteQueryOption(const QueryOption &o)
{
this->o = o;
}
SqliteQueryOption &SqliteQueryOption::setOrderByColumn(std::string name)
{
this->orderByColumnName = name;
return *this;
}
SqliteQueryOption &SqliteQueryOption::setVisibleColumnName(std::string name)
{
this->visibleColumnName = name;
return *this;
}
SqliteQueryOption &SqliteQueryOption::setPrependWhere(bool b)
{
this->prependWhere = b;
return *this;
}
std::string SqliteQueryOption::build()
{
std::string result;
if(!o.includeInvisible && !this->visibleColumnName.empty())
{
if(this->prependWhere)
{
result += "WHERE ";
}
result += this->visibleColumnName + " = 1";
}
result += " ORDER BY " + orderByColumnName;
if(o.order == ASCENDING)
{
result += " ASC";
}
else
{
result += " DESC";
}
// TODO: limits for offset?
if(o.limit > 0)
result += " LIMIT " + std::to_string(o.limit) + " OFFSET " + std::to_string(o.offset);
return result;
}

View File

@ -0,0 +1,27 @@
#ifndef SQLITEQUERYOPTION_H
#define SQLITEQUERYOPTION_H
#include <string>
#include "queryoption.h"
class SqliteQueryOption
{
private:
QueryOption o;
std::string visibleColumnName;
std::string orderByColumnName;
bool prependWhere;
public:
SqliteQueryOption(const QueryOption &o);
SqliteQueryOption &setOrderByColumn(std::string name);
SqliteQueryOption &setVisibleColumnName(std::string name);
SqliteQueryOption &setPrependWhere(bool b);
std::string build();
};
#endif // SQLITEQUERYOPTION_H

25
database/userdao.cpp Normal file
View File

@ -0,0 +1,25 @@
/* Copyright (c) 2018 Albert S.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "userdao.h"
UserDao::UserDao()
{
}

18
database/userdao.h Normal file
View File

@ -0,0 +1,18 @@
#ifndef USERDAO_H
#define USERDAO_H
#include <string>
#include <optional>
#include "../user.h"
class UserDao
{
public:
UserDao();
virtual bool exists(std::string username) = 0;
virtual std::optional<User> find(std::string username) = 0;
virtual std::optional<User> find(int id) = 0;
virtual void deleteUser(std::string username) = 0;
virtual void save(const User &u) = 0;
virtual ~UserDao(){};
};
#endif // USERDAO_H

View File

@ -0,0 +1,91 @@
/* Copyright (c) 2018 Albert S.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include <sqlite3.h>
#include <string>
#include <memory>
#include <cstring>
#include "userdaosqlite.h"
UserDaoSqlite::UserDaoSqlite()
{
}
bool UserDaoSqlite::exists(std::string username)
{
auto prep = *db << "SELECT 1 FROM user WHERE username = ?" << username;
return execBool(prep);
}
std::optional<User> UserDaoSqlite::find(std::string username)
{
try
{
User user;
auto stmt = *db << "SELECT username, password, salt, permissions FROM user WHERE username = ?" << username;
int perms = 0;
stmt >> std::tie(user.login, user.password, user.salt, perms);
user.permissions = Permissions{perms};
return std::move(user);
}
catch(const sqlite::errors::no_rows &e)
{
return {};
}
catch(sqlite::sqlite_exception &e)
{
throwFrom(e);
}
}
std::optional<User> UserDaoSqlite::find(int id)
{
try
{
User user;
auto stmt = *db << "SELECT username, password, salt, permissions FROM user WHERE id = ?" << id;
int perms = 0;
stmt >> std::tie(user.login, user.password, user.salt, perms);
user.permissions = Permissions{perms};
return std::move(user);
}
catch(const sqlite::errors::no_rows &e)
{
return {};
}
catch(sqlite::sqlite_exception &e)
{
throwFrom(e);
}
}
void UserDaoSqlite::deleteUser(std::string username)
{
// What to do with the contributions of the user?
}
void UserDaoSqlite::save(const User &u)
{
}

22
database/userdaosqlite.h Normal file
View File

@ -0,0 +1,22 @@
#ifndef USERDAOSQLITE_H
#define USERDAOSQLITE_H
#include <string>
#include <optional>
#include <vector>
#include "userdao.h"
#include "sqlitedao.h"
class UserDaoSqlite : public UserDao, protected SqliteDao
{
public:
bool exists(std::string username);
std::optional<User> find(std::string username);
std::optional<User> find(int id);
void deleteUser(std::string username);
void save(const User &u);
using SqliteDao::SqliteDao;
UserDaoSqlite();
};
#endif // USERDAOSQLITE_H