From 50cadf3dac0d56ef8181d1800cc30f8dcb749141 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Tue, 13 Jun 2017 10:38:39 +0200 Subject: Implement our own database ORM, and update the whole code to use it Entirely replace LiteSQL fix #3271 --- src/database/select_query.hpp | 153 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 src/database/select_query.hpp (limited to 'src/database/select_query.hpp') diff --git a/src/database/select_query.hpp b/src/database/select_query.hpp new file mode 100644 index 0000000..b41632e --- /dev/null +++ b/src/database/select_query.hpp @@ -0,0 +1,153 @@ +#pragma once + +#include +#include +#include + +#include +#include + +#include + +using namespace std::string_literals; + +template +typename std::enable_if::value, sqlite3_int64>::type +extract_row_value(sqlite3_stmt* statement, const int i) +{ + return sqlite3_column_int64(statement, i); +} + +template +typename std::enable_if::value, std::string>::type +extract_row_value(sqlite3_stmt* statement, const int i) +{ + const auto size = sqlite3_column_bytes(statement, i); + const unsigned char* str = sqlite3_column_text(statement, i); + std::string result(reinterpret_cast(str), size); + return result; +} + +template +typename std::enable_if::type +extract_row_values(Row& row, sqlite3_stmt* statement) +{ + using ColumnType = typename std::remove_reference(row.columns))>::type; + + auto&& column = std::get(row.columns); + column.value = static_cast(extract_row_value(statement, N)); + + extract_row_values(row, statement); +} + +template +typename std::enable_if::type +extract_row_values(Row&, sqlite3_stmt*) +{} + +template +struct SelectQuery: public Query +{ + SelectQuery(std::string table_name): + Query("SELECT"), + table_name(table_name) + { + this->insert_col_name<0>(); + this->body += " from " + this->table_name; + } + + template + typename std::enable_if::type + insert_col_name() + { + using ColumnsType = std::tuple; + ColumnsType tuple{}; + auto value = std::get(tuple); + + this->body += " "s + value.name; + + if (N < (sizeof...(T) - 1)) + this->body += ", "; + + this->insert_col_name(); + } + template + typename std::enable_if::type + insert_col_name() + {} + + SelectQuery& where() + { + this->body += " WHERE "; + return *this; + }; + + SelectQuery& order_by() + { + this->body += " ORDER BY "; + return *this; + } + + SelectQuery& limit() + { + this->body += " LIMIT "; + return *this; + } + + auto execute(sqlite3* db) + { + auto statement = this->prepare(db); + int i = 1; + for (const std::string& param: this->params) + { + if (sqlite3_bind_text(statement, i, param.data(), static_cast(param.size()), SQLITE_TRANSIENT) != SQLITE_OK) + log_debug("Failed to bind ", param, " to param ", i); + else + log_debug("Bound ", param, " to ", i); + + i++; + } + std::vector> rows; + while (sqlite3_step(statement) == SQLITE_ROW) + { + Row row(this->table_name); + extract_row_values(row, statement); + rows.push_back(row); + } + return rows; + } + + const std::string table_name; +}; + +template +typename std::enable_if::value, SelectQuery&>::type +operator<<(SelectQuery& query, const T&) +{ + query.body += T::name; + return query; +} + +template +SelectQuery& operator<<(SelectQuery& query, const char* str) +{ + query.body += str; + return query; +} + +template +SelectQuery& operator<<(SelectQuery& query, const std::string& str) +{ + query.body += "?"; + actual_add_param(query, str); + return query; +} + +template +typename std::enable_if::value, SelectQuery&>::type +operator<<(SelectQuery& query, const Integer& i) +{ + query.body += "?"; + actual_add_param(query, i); + return query; +} -- cgit v1.2.3 From 9defd0ccb75b1905c308ed0437e5ccd479e3a7b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Wed, 14 Jun 2017 00:04:00 +0200 Subject: Add a Statement class to manage the sqlite3_stmt objects and avoid leaks --- src/database/select_query.hpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'src/database/select_query.hpp') diff --git a/src/database/select_query.hpp b/src/database/select_query.hpp index b41632e..80d1424 100644 --- a/src/database/select_query.hpp +++ b/src/database/select_query.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -13,24 +14,24 @@ using namespace std::string_literals; template typename std::enable_if::value, sqlite3_int64>::type -extract_row_value(sqlite3_stmt* statement, const int i) +extract_row_value(Statement& statement, const int i) { - return sqlite3_column_int64(statement, i); + return sqlite3_column_int64(statement.get(), i); } template typename std::enable_if::value, std::string>::type -extract_row_value(sqlite3_stmt* statement, const int i) +extract_row_value(Statement& statement, const int i) { - const auto size = sqlite3_column_bytes(statement, i); - const unsigned char* str = sqlite3_column_text(statement, i); + const auto size = sqlite3_column_bytes(statement.get(), i); + const unsigned char* str = sqlite3_column_text(statement.get(), i); std::string result(reinterpret_cast(str), size); return result; } template typename std::enable_if::type -extract_row_values(Row& row, sqlite3_stmt* statement) +extract_row_values(Row& row, Statement& statement) { using ColumnType = typename std::remove_reference(row.columns))>::type; @@ -42,7 +43,7 @@ extract_row_values(Row& row, sqlite3_stmt* statement) template typename std::enable_if::type -extract_row_values(Row&, sqlite3_stmt*) +extract_row_values(Row&, Statement&) {} template @@ -100,7 +101,7 @@ struct SelectQuery: public Query int i = 1; for (const std::string& param: this->params) { - if (sqlite3_bind_text(statement, i, param.data(), static_cast(param.size()), SQLITE_TRANSIENT) != SQLITE_OK) + if (sqlite3_bind_text(statement.get(), i, param.data(), static_cast(param.size()), SQLITE_TRANSIENT) != SQLITE_OK) log_debug("Failed to bind ", param, " to param ", i); else log_debug("Bound ", param, " to ", i); @@ -108,7 +109,7 @@ struct SelectQuery: public Query i++; } std::vector> rows; - while (sqlite3_step(statement) == SQLITE_ROW) + while (sqlite3_step(statement.get()) == SQLITE_ROW) { Row row(this->table_name); extract_row_values(row, statement); -- cgit v1.2.3 From 2677ac42e8d2e1cf162fec773a9acb453bef8b9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Wed, 14 Jun 2017 10:31:45 +0200 Subject: Fix compilation (many warnings, and a linkage error) with clang++ --- src/database/select_query.hpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'src/database/select_query.hpp') diff --git a/src/database/select_query.hpp b/src/database/select_query.hpp index 80d1424..d0c1d59 100644 --- a/src/database/select_query.hpp +++ b/src/database/select_query.hpp @@ -25,7 +25,7 @@ extract_row_value(Statement& statement, const int i) { const auto size = sqlite3_column_bytes(statement.get(), i); const unsigned char* str = sqlite3_column_text(statement.get(), i); - std::string result(reinterpret_cast(str), size); + std::string result(reinterpret_cast(str), static_cast(size)); return result; } @@ -62,10 +62,9 @@ struct SelectQuery: public Query insert_col_name() { using ColumnsType = std::tuple; - ColumnsType tuple{}; - auto value = std::get(tuple); + using ColumnType = typename std::remove_reference(std::declval()))>::type; - this->body += " "s + value.name; + this->body += " "s + ColumnType::name; if (N < (sizeof...(T) - 1)) this->body += ", "; -- cgit v1.2.3 From 5834dd53f32ff89f5818681a93e416b0a48b6254 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Wed, 14 Jun 2017 16:21:23 +0200 Subject: Add a 0 default value for template argument N --- src/database/select_query.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/database/select_query.hpp') diff --git a/src/database/select_query.hpp b/src/database/select_query.hpp index d0c1d59..93d69ed 100644 --- a/src/database/select_query.hpp +++ b/src/database/select_query.hpp @@ -53,11 +53,11 @@ struct SelectQuery: public Query Query("SELECT"), table_name(table_name) { - this->insert_col_name<0>(); + this->insert_col_name(); this->body += " from " + this->table_name; } - template + template typename std::enable_if::type insert_col_name() { @@ -71,7 +71,7 @@ struct SelectQuery: public Query this->insert_col_name(); } - template + template typename std::enable_if::type insert_col_name() {} -- cgit v1.2.3 From 40db183e3753486deaa43e950fff38579c5ced6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Fri, 16 Jun 2017 09:52:40 +0200 Subject: Using OptionalBool, add RecordHistoryOptional col into IrcChannelOptions table ref #3269 --- src/database/select_query.hpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'src/database/select_query.hpp') diff --git a/src/database/select_query.hpp b/src/database/select_query.hpp index 93d69ed..837b064 100644 --- a/src/database/select_query.hpp +++ b/src/database/select_query.hpp @@ -5,6 +5,8 @@ #include #include +#include + #include #include @@ -20,7 +22,7 @@ extract_row_value(Statement& statement, const int i) } template -typename std::enable_if::value, std::string>::type +typename std::enable_if::value, T>::type extract_row_value(Statement& statement, const int i) { const auto size = sqlite3_column_bytes(statement.get(), i); @@ -29,6 +31,19 @@ extract_row_value(Statement& statement, const int i) return result; } +template +typename std::enable_if::value, T>::type +extract_row_value(Statement& statement, const int i) +{ + const auto integer = sqlite3_column_int(statement.get(), i); + OptionalBool result; + if (integer > 0) + result.set_value(true); + else if (integer < 0) + result.set_value(false); + return result; +} + template typename std::enable_if::type extract_row_values(Row& row, Statement& statement) -- cgit v1.2.3 From b71ca15a0f9114db38eec23b49d1489a2ff1d0ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Fri, 23 Jun 2017 00:11:07 +0200 Subject: Move a few functions from select_query to query --- src/database/select_query.hpp | 41 ----------------------------------------- 1 file changed, 41 deletions(-) (limited to 'src/database/select_query.hpp') diff --git a/src/database/select_query.hpp b/src/database/select_query.hpp index 837b064..f4d71af 100644 --- a/src/database/select_query.hpp +++ b/src/database/select_query.hpp @@ -112,16 +112,6 @@ struct SelectQuery: public Query auto execute(sqlite3* db) { auto statement = this->prepare(db); - int i = 1; - for (const std::string& param: this->params) - { - if (sqlite3_bind_text(statement.get(), i, param.data(), static_cast(param.size()), SQLITE_TRANSIENT) != SQLITE_OK) - log_debug("Failed to bind ", param, " to param ", i); - else - log_debug("Bound ", param, " to ", i); - - i++; - } std::vector> rows; while (sqlite3_step(statement.get()) == SQLITE_ROW) { @@ -135,34 +125,3 @@ struct SelectQuery: public Query const std::string table_name; }; -template -typename std::enable_if::value, SelectQuery&>::type -operator<<(SelectQuery& query, const T&) -{ - query.body += T::name; - return query; -} - -template -SelectQuery& operator<<(SelectQuery& query, const char* str) -{ - query.body += str; - return query; -} - -template -SelectQuery& operator<<(SelectQuery& query, const std::string& str) -{ - query.body += "?"; - actual_add_param(query, str); - return query; -} - -template -typename std::enable_if::value, SelectQuery&>::type -operator<<(SelectQuery& query, const Integer& i) -{ - query.body += "?"; - actual_add_param(query, i); - return query; -} -- cgit v1.2.3