diff options
author | Florent Le Coz <louiz@louiz.org> | 2015-09-18 21:49:54 +0200 |
---|---|---|
committer | Florent Le Coz <louiz@louiz.org> | 2015-09-18 22:09:26 +0200 |
commit | 88ae2599f6dbf655e8806c9b4619ec089425683b (patch) | |
tree | 850cb2048401efff1650a2ce29b41df8464c7092 | |
parent | 33fa1dcd5a87035de1d9b8df65e5c7551b4bbd1b (diff) | |
download | biboumi-88ae2599f6dbf655e8806c9b4619ec089425683b.tar.gz biboumi-88ae2599f6dbf655e8806c9b4619ec089425683b.tar.bz2 biboumi-88ae2599f6dbf655e8806c9b4619ec089425683b.tar.xz biboumi-88ae2599f6dbf655e8806c9b4619ec089425683b.zip |
Introduce an optional Database module
Uses litesql
-rw-r--r-- | CMakeLists.txt | 31 | ||||
-rw-r--r-- | INSTALL | 6 | ||||
-rw-r--r-- | biboumi.h.cmake | 1 | ||||
-rw-r--r-- | cmake/Modules/FindLITESQL.cmake | 75 | ||||
-rw-r--r-- | database/database.xml | 18 | ||||
-rw-r--r-- | src/database/database.cpp | 54 | ||||
-rw-r--r-- | src/database/database.hpp | 47 | ||||
-rw-r--r-- | src/test.cpp | 37 |
8 files changed, 268 insertions, 1 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 93e91ba..1bad544 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,8 +44,11 @@ set(SOFTWARE_VERSION ${${PROJECT_NAME}_VERSION_MAJOR}.${${PROJECT_NAME}_VERSION_MINOR}${${PROJECT_NAME}_VERSION_SUFFIX}) # To be able to include the config.h file generated by cmake + +# To be able to include the config.h and other files generated by cmake include_directories("${CMAKE_CURRENT_BINARY_DIR}/src/") include_directories("${CMAKE_CURRENT_SOURCE_DIR}/src/") +include_directories("${CMAKE_CURRENT_BINARY_DIR}/") # ## Documentation @@ -63,6 +66,24 @@ if(RONN_EXECUTABLE) add_custom_target(doc DEPENDS ${MAN_PAGE}) endif() +# Look for litesql and enable the database if found +if(WITH_LITESQL) + find_package(LITESQL REQUIRED) +elseif(NOT WITHOUT_LITESQL) + find_package(LITESQL) +endif() + +if(LITESQL_FOUND) + LITESQL_GENERATE_CPP("database/database.xml" + "biboudb" + LITESQL_GENERATED_SOURCES) + + add_library(database STATIC src/database/database.cpp + ${LITESQL_GENERATED_SOURCES}) + target_link_libraries(database ${LITESQL_LIBRARIES} ${BOTAN_LIBRARIES}) + set(USE_DATABASE TRUE) +endif() + add_subdirectory("louloulibs") include_directories("louloulibs") @@ -97,6 +118,9 @@ file(GLOB source_xmpp add_library(xmpp STATIC ${source_xmpp}) target_link_libraries(xmpp xmpplib bridge network utils logger) +if(USE_DATABASE) + target_link_libraries(xmpp database) +endif() # ## bridge # @@ -134,6 +158,11 @@ target_link_libraries(test_suite config logger) +if(USE_DATABASE) + target_link_libraries(test_suite + database) +endif() + # ## Install target # @@ -151,3 +180,5 @@ add_custom_target(dist COMMAND git archive --prefix=${ARCHIVE_NAME}/ --format=tar HEAD | xz > ${CMAKE_CURRENT_BINARY_DIR}/${ARCHIVE_NAME}.tar.xz WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/biboumi.h.cmake ${CMAKE_BINARY_DIR}/src/biboumi.h)
\ No newline at end of file @@ -49,6 +49,12 @@ Libraries: Other branches than the 1.11 are not supported. http://botan.randombit.net/ +- litesql (optional) + Provides a way to store various options in a (sqlite3) database. Each user + of the gateway can store their own values (for example their prefered port, + or their IRC password). + http://git.louiz.org/litesql + - systemd (optional) Provides the support for a systemd service of Type=notify. This is useful only if you are packaging biboumi in a distribution with Systemd. diff --git a/biboumi.h.cmake b/biboumi.h.cmake new file mode 100644 index 0000000..beb67d0 --- /dev/null +++ b/biboumi.h.cmake @@ -0,0 +1 @@ +#cmakedefine USE_DATABASE diff --git a/cmake/Modules/FindLITESQL.cmake b/cmake/Modules/FindLITESQL.cmake new file mode 100644 index 0000000..2ce8fd6 --- /dev/null +++ b/cmake/Modules/FindLITESQL.cmake @@ -0,0 +1,75 @@ +# - Find LiteSQL +# +# Find the LiteSQL library, and defines a function to generate C++ files +# from the database xml file using litesql-gen fro +# +# This module defines the following variables: +# LITESQL_FOUND - True if library and include directory are found +# If set to TRUE, the following are also defined: +# LITESQL_INCLUDE_DIRS - The directory where to find the header file +# LITESQL_LIBRARIES - Where to find the library file +# LITESQL_GENERATE_CPP - A function, to be used like this: +# LITESQL_GENERATE_CPP("db/database.xml" # The file defining the db schemas +# "database" # The name of the C++ “module” +# # that will be generated +# LITESQL_GENERATED_SOURCES # Variable containing the +# resulting C++ files to compile +# +# For conveniance, these variables are also set. They have the same values +# than the variables above. The user can thus choose his/her prefered way +# to write them. +# LITESQL_INCLUDE_DIR +# LITESQL_LIBRARY +# +# This file is in the public domain + +find_path(LITESQL_INCLUDE_DIRS NAMES litesql.hpp + DOC "The LiteSQL include directory") + +find_library(LITESQL_LIBRARIES NAMES litesql + DOC "The LiteSQL library") + +foreach(DB_TYPE sqlite postgresql mysql ocilib) + string(TOUPPER ${DB_TYPE} DB_TYPE_UPPER) + find_library(LITESQL_${DB_TYPE_UPPER}_LIB_PATH NAMES litesql_${DB_TYPE} + DOC "The ${DB_TYPE} backend for LiteSQL") + if(LITESQL_${DB_TYPE_UPPER}_LIB_PATH) + list(APPEND LITESQL_LIBRARIES ${LITESQL_${DB_TYPE_UPPER}_LIB_PATH}) + endif() +endforeach() + +find_program(LITESQLGEN_EXECUTABLE NAMES litesql-gen + DOC "The utility that creates .h and .cpp files from a xml database description") + +# Use some standard module to handle the QUIETLY and REQUIRED arguments, and +# set LITESQL_FOUND to TRUE if these two variables are set. +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(LITESQL REQUIRED_VARS LITESQL_LIBRARIES LITESQL_INCLUDE_DIRS + LITESQLGEN_EXECUTABLE) + +# Compatibility for all the ways of writing these variables +if(LITESQL_FOUND) + set(LITESQL_INCLUDE_DIR ${LITESQL_INCLUDE_DIRS}) + set(LITESQL_LIBRARY ${LITESQL_LIBRARIES}) +endif() + +mark_as_advanced(LITESQL_INCLUDE_DIRS LITESQL_LIBRARIES) + + +# LITESQL_GENERATE_CPP function + +function(LITESQL_GENERATE_CPP + SOURCE_FILE OUTPUT_NAME OUTPUT_SOURCES) + set(${OUTPUT_SOURCES}) + add_custom_command( + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT_NAME}.cpp" + "${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT_NAME}.hpp" + COMMAND ${LITESQLGEN_EXECUTABLE} + ARGS -t c++ --output-dir=${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/${SOURCE_FILE} + DEPENDS ${SOURCE_FILE} + COMMENT "Running litesql-gen on ${SOURCE_FILE}" + VERBATIM) + list(APPEND ${OUTPUT_SOURCES} "${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT_NAME}.cpp") + set_source_files_properties(${${OUTPUT_SOURCES}} PROPERTIES GENERATED TRUE) + set(${OUTPUT_SOURCES} ${${OUTPUT_SOURCES}} PARENT_SCOPE) +endfunction() diff --git a/database/database.xml b/database/database.xml new file mode 100644 index 0000000..f3a005c --- /dev/null +++ b/database/database.xml @@ -0,0 +1,18 @@ +<?xml version="1.0"?> +<!DOCTYPE database SYSTEM "litesql.dtd"> + +<database name="BibouDB" namespace="db"> + <object name="IrcServerOptions"> + <field name="owner" type="string" length="3071"/> + <field name="server" type="string" length="3071"/> + + <field name="requireTls" type="boolean" default="true"/> + <field name="pass" type="string" length="1024"/> + + <index unique="true"> + <indexfield name="owner"/> + <indexfield name="server"/> + </index> + + </object> +</database> diff --git a/src/database/database.cpp b/src/database/database.cpp new file mode 100644 index 0000000..e16465c --- /dev/null +++ b/src/database/database.cpp @@ -0,0 +1,54 @@ +#include <database/database.hpp> +#include <config/config.hpp> +#include <utils/xdg.hpp> +#include <logger/logger.hpp> +#include <string> + +using namespace std::string_literals; + +std::unique_ptr<db::BibouDB> Database::db; + +db::BibouDB& Database::get_db() +{ + if (!Database::db) + { + const std::string db_filename = Config::get("db_name", + xdg_data_path("biboumi.sqlite")); + // log_info("Opening database: " << db_filename); + std::cout << "Opening database: " << db_filename << std::endl; + Database::db = std::make_unique<db::BibouDB>("sqlite3", + "database="s + db_filename); + } + + if (Database::db->needsUpgrade()) + Database::db->upgrade(); + + return *Database::db.get(); +} + +void Database::set_verbose(const bool val) +{ + Database::get_db().verbose = val; +} + +db::IrcServerOptions Database::get_irc_server_options(const std::string& owner, + const std::string& server) +{ + try { + auto options = litesql::select<db::IrcServerOptions>(Database::get_db(), + db::IrcServerOptions::Owner == owner && + db::IrcServerOptions::Server == server).one(); + return options; + } catch (const litesql::NotFound& e) { + db::IrcServerOptions options(Database::get_db()); + options.owner = owner; + options.server = server; + // options.update(); + return options; + } +} + +void Database::close() +{ + Database::db.reset(nullptr); +} diff --git a/src/database/database.hpp b/src/database/database.hpp new file mode 100644 index 0000000..d8dc735 --- /dev/null +++ b/src/database/database.hpp @@ -0,0 +1,47 @@ +#ifndef DATABASE_HPP_INCLUDED +#define DATABASE_HPP_INCLUDED + +#include <biboumi.h> +#ifdef USE_DATABASE + +#include "biboudb.hpp" + +#include <memory> + +#include <litesql.hpp> + +class Database +{ +public: + Database() = default; + ~Database() = default; + + static void set_verbose(const bool val); + + template<typename PersistentType> + static size_t count() + { + return litesql::select<PersistentType>(Database::get_db()).count(); + } + /** + * Return the object from the db. Create it beforehand (with all default + * values) if it is not already present. + */ + static db::IrcServerOptions get_irc_server_options(const std::string& owner, + const std::string& server); + + static void close(); + +private: + static std::unique_ptr<db::BibouDB> db; + + static db::BibouDB& get_db(); + + Database(const Database&) = delete; + Database(Database&&) = delete; + Database& operator=(const Database&) = delete; + Database& operator=(Database&&) = delete; +}; +#endif /* USE_DATABASE */ + +#endif /* DATABASE_HPP_INCLUDED */ diff --git a/src/test.cpp b/src/test.cpp index 3ac0332..bc85cb0 100644 --- a/src/test.cpp +++ b/src/test.cpp @@ -4,6 +4,7 @@ #include <xmpp/xmpp_component.hpp> #include <utils/timed_events.hpp> +#include <database/database.hpp> #include <xmpp/xmpp_parser.hpp> #include <utils/encoding.hpp> #include <logger/logger.hpp> @@ -16,12 +17,15 @@ #include <utils/xdg.hpp> #include <xmpp/jid.hpp> #include <irc/iid.hpp> +#include <unistd.h> #include <string.h> #include <iostream> #include <thread> #include <vector> +#include "biboumi.h" + #undef NDEBUG #include <assert.h> @@ -403,8 +407,39 @@ int main() assert(iid6.is_channel); assert(!iid6.is_user); } +#ifdef USE_DATABASE { - + std::cout << color << "Testing the Database…" << reset << std::endl; + // Remove any potential existing db + unlink("./test.db"); + Config::set("db_name", "test.db"); + Database::set_verbose(true); + auto o = Database::get_irc_server_options("zouzou@example.com", "irc.example.com"); + o.requireTls = false; + o.update(); + auto a = Database::get_irc_server_options("zouzou@example.com", "irc.example.com"); + assert(a.requireTls == false); + auto b = Database::get_irc_server_options("moumou@example.com", "irc.example.com"); + assert(b.requireTls == true); + + // b does not yet exist in the db, the object is created but not yet + // inserted + assert(1 == Database::count<db::IrcServerOptions>()); + + b.update(); + assert(2 == Database::count<db::IrcServerOptions>()); + + assert(b.pass == ""); + assert(b.pass.value() == ""); + + std::vector<litesql::FieldType> ftypes; + db::IrcServerOptions::getFieldTypes(ftypes); + for (const auto& type: ftypes) + { + std::cout << type.type() << std::endl; + } + } +#endif { std::cout << color << "Testing the xdg_path function…" << reset << std::endl; std::string res; |