sqlite3 mini-orm work
This commit is contained in:
		
							
								
								
									
										99
									
								
								repertory/librepertory/include/database/db_delete.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								repertory/librepertory/include/database/db_delete.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,99 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					  Copyright <2018-2024> <scott.e.graves@protonmail.com>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  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.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					#ifndef INCLUDE_DATABASE_DB_DELETE_HPP_
 | 
				
			||||||
 | 
					#define INCLUDE_DATABASE_DB_DELETE_HPP_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "database/db_common.hpp"
 | 
				
			||||||
 | 
					#include "utils/error_utils.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace repertory::db {
 | 
				
			||||||
 | 
					class db_delete final {
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  struct context final {
 | 
				
			||||||
 | 
					    context(sqlite3 &db3_, std::string table_name_)
 | 
				
			||||||
 | 
					        : db3(db3_), table_name(std::move(table_name_)) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    sqlite3 &db3;
 | 
				
			||||||
 | 
					    std::string table_name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::vector<comp_data_t> ands{};
 | 
				
			||||||
 | 
					    db3_stmt_t stmt{nullptr};
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  using row = db_row<context>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  db_delete(sqlite3 &db3, std::string table_name)
 | 
				
			||||||
 | 
					      : context_(std::make_shared<context>(db3, table_name)) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  db_delete(std::shared_ptr<context> ctx) : context_(std::move(ctx)) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  struct db_where final {
 | 
				
			||||||
 | 
					    db_where(std::shared_ptr<context> ctx, std::string column_name)
 | 
				
			||||||
 | 
					        : context_(std::move(ctx)), column_name_(std::move(column_name)) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public:
 | 
				
			||||||
 | 
					    struct db_where_next final {
 | 
				
			||||||
 | 
					      db_where_next(std::shared_ptr<context> ctx) : context_(std::move(ctx)) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private:
 | 
				
			||||||
 | 
					      std::shared_ptr<context> context_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public:
 | 
				
			||||||
 | 
					      [[nodiscard]] auto and_where(std::string column_name) const -> db_where {
 | 
				
			||||||
 | 
					        return db_where{context_, column_name};
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      [[nodiscard]] auto dump() const -> std::string {
 | 
				
			||||||
 | 
					        return db_delete{context_}.dump();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      [[nodiscard]] auto go() const -> db_result<context> {
 | 
				
			||||||
 | 
					        return db_delete{context_}.go();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private:
 | 
				
			||||||
 | 
					    std::shared_ptr<context> context_;
 | 
				
			||||||
 | 
					    std::string column_name_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public:
 | 
				
			||||||
 | 
					    [[nodiscard]] auto equals(db_types_t value) const -> db_where_next {
 | 
				
			||||||
 | 
					      context_->ands.emplace_back(comp_data_t{column_name_, "=", value});
 | 
				
			||||||
 | 
					      return db_where_next{context_};
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					  std::shared_ptr<context> context_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  [[nodiscard]] auto dump() const -> std::string;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [[nodiscard]] auto go() const -> db_result<context>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [[nodiscard]] auto where(std::string column_name) const -> db_where;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					} // namespace repertory::db
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif // INCLUDE_DATABASE_DB_DELETE_HPP_
 | 
				
			||||||
@@ -38,7 +38,6 @@ public:
 | 
				
			|||||||
    std::vector<comp_data_t> ands{};
 | 
					    std::vector<comp_data_t> ands{};
 | 
				
			||||||
    std::vector<std::string> columns{};
 | 
					    std::vector<std::string> columns{};
 | 
				
			||||||
    std::map<std::string, std::string> count_columns{};
 | 
					    std::map<std::string, std::string> count_columns{};
 | 
				
			||||||
    bool delete_query{false};
 | 
					 | 
				
			||||||
    std::optional<std::int32_t> limit;
 | 
					    std::optional<std::int32_t> limit;
 | 
				
			||||||
    std::optional<std::pair<std::string, bool>> order_by;
 | 
					    std::optional<std::pair<std::string, bool>> order_by;
 | 
				
			||||||
    db3_stmt_t stmt{nullptr};
 | 
					    db3_stmt_t stmt{nullptr};
 | 
				
			||||||
@@ -81,8 +80,8 @@ public:
 | 
				
			|||||||
        return db_select{context_}.limit(value);
 | 
					        return db_select{context_}.limit(value);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      [[nodiscard]] auto order_by(std::string column_name, bool ascending) const
 | 
					      [[nodiscard]] auto order_by(std::string column_name,
 | 
				
			||||||
          -> db_select {
 | 
					                                  bool ascending) const -> db_select {
 | 
				
			||||||
        return db_select{context_}.order_by(column_name, ascending);
 | 
					        return db_select{context_}.order_by(column_name, ascending);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
@@ -104,10 +103,8 @@ private:
 | 
				
			|||||||
public:
 | 
					public:
 | 
				
			||||||
  [[nodiscard]] auto column(std::string column_name) -> db_select &;
 | 
					  [[nodiscard]] auto column(std::string column_name) -> db_select &;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  [[nodiscard]] auto count(std::string column_name, std::string as_column_name)
 | 
					  [[nodiscard]] auto count(std::string column_name,
 | 
				
			||||||
      -> db_select &;
 | 
					                           std::string as_column_name) -> db_select &;
 | 
				
			||||||
 | 
					 | 
				
			||||||
  [[nodiscard]] auto delete_query() -> db_select &;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  [[nodiscard]] auto dump() const -> std::string;
 | 
					  [[nodiscard]] auto dump() const -> std::string;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -115,8 +112,8 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  [[nodiscard]] auto limit(std::int32_t value) -> db_select &;
 | 
					  [[nodiscard]] auto limit(std::int32_t value) -> db_select &;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  [[nodiscard]] auto order_by(std::string column_name, bool ascending)
 | 
					  [[nodiscard]] auto order_by(std::string column_name,
 | 
				
			||||||
      -> db_select &;
 | 
					                              bool ascending) -> db_select &;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  [[nodiscard]] auto where(std::string column_name) const -> db_where;
 | 
					  [[nodiscard]] auto where(std::string column_name) const -> db_where;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -36,6 +36,8 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    std::vector<comp_data_t> ands{};
 | 
					    std::vector<comp_data_t> ands{};
 | 
				
			||||||
    std::map<std::string, db_types_t> values{};
 | 
					    std::map<std::string, db_types_t> values{};
 | 
				
			||||||
 | 
					    std::optional<std::int32_t> limit;
 | 
				
			||||||
 | 
					    std::optional<std::pair<std::string, bool>> order_by;
 | 
				
			||||||
    db3_stmt_t stmt{nullptr};
 | 
					    db3_stmt_t stmt{nullptr};
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -65,6 +67,15 @@ public:
 | 
				
			|||||||
      [[nodiscard]] auto go() const -> db_result<context> {
 | 
					      [[nodiscard]] auto go() const -> db_result<context> {
 | 
				
			||||||
        return db_update{context_}.go();
 | 
					        return db_update{context_}.go();
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      [[nodiscard]] auto limit(std::int32_t value) const -> db_update {
 | 
				
			||||||
 | 
					        return db_update{context_}.limit(value);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      [[nodiscard]] auto order_by(std::string column_name,
 | 
				
			||||||
 | 
					                                  bool ascending) const -> db_update {
 | 
				
			||||||
 | 
					        return db_update{context_}.order_by(column_name, ascending);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private:
 | 
					  private:
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										94
									
								
								repertory/librepertory/src/database/db_delete.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								repertory/librepertory/src/database/db_delete.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,94 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					  Copyright <2018-2024> <scott.e.graves@protonmail.com>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  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 "database/db_delete.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace repertory::db {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					auto db_delete::dump() const -> std::string {
 | 
				
			||||||
 | 
					  std::stringstream query;
 | 
				
			||||||
 | 
					  query << "DELETE FROM \"" << context_->table_name << "\"";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (not context_->ands.empty()) {
 | 
				
			||||||
 | 
					    query << " WHERE (";
 | 
				
			||||||
 | 
					    for (std::int32_t idx = 0;
 | 
				
			||||||
 | 
					         idx < static_cast<std::int32_t>(context_->ands.size()); idx++) {
 | 
				
			||||||
 | 
					      if (idx > 0) {
 | 
				
			||||||
 | 
					        query << " AND ";
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      auto &item = context_->ands.at(static_cast<std::size_t>(idx));
 | 
				
			||||||
 | 
					      query << '"' << item.column_name << '"' << item.op_type << "?"
 | 
				
			||||||
 | 
					            << (idx + 1);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    query << ")";
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  query << ';';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return query.str();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					auto db_delete::go() const -> db_result<context> {
 | 
				
			||||||
 | 
					  static constexpr const std::string_view function_name{
 | 
				
			||||||
 | 
					      static_cast<const char *>(__FUNCTION__),
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  sqlite3_stmt *stmt_ptr{nullptr};
 | 
				
			||||||
 | 
					  auto query_str = dump();
 | 
				
			||||||
 | 
					  auto res = sqlite3_prepare_v2(&context_->db3, query_str.c_str(), -1,
 | 
				
			||||||
 | 
					                                &stmt_ptr, nullptr);
 | 
				
			||||||
 | 
					  if (res != SQLITE_OK) {
 | 
				
			||||||
 | 
					    utils::error::raise_error(function_name,
 | 
				
			||||||
 | 
					                              "failed to prepare|" + std::to_string(res) + '|' +
 | 
				
			||||||
 | 
					                                  sqlite3_errstr(res) + '|' + query_str);
 | 
				
			||||||
 | 
					    return {context_, res};
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  context_->stmt.reset(stmt_ptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (std::int32_t idx = 0;
 | 
				
			||||||
 | 
					       idx < static_cast<std::int32_t>(context_->ands.size()); idx++) {
 | 
				
			||||||
 | 
					    res = std::visit(
 | 
				
			||||||
 | 
					        overloaded{
 | 
				
			||||||
 | 
					            [this, &idx](std::int64_t data) -> std::int32_t {
 | 
				
			||||||
 | 
					              return sqlite3_bind_int64(context_->stmt.get(), idx + 1, data);
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            [this, &idx](const std::string &data) -> std::int32_t {
 | 
				
			||||||
 | 
					              return sqlite3_bind_text(context_->stmt.get(), idx + 1,
 | 
				
			||||||
 | 
					                                       data.c_str(), -1, nullptr);
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        context_->ands.at(static_cast<std::size_t>(idx)).value);
 | 
				
			||||||
 | 
					    if (res != SQLITE_OK) {
 | 
				
			||||||
 | 
					      utils::error::raise_error(function_name,
 | 
				
			||||||
 | 
					                                "failed to bind|" + std::to_string(res) + '|' +
 | 
				
			||||||
 | 
					                                    sqlite3_errstr(res) + '|' + query_str);
 | 
				
			||||||
 | 
					      return {context_, res};
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return {context_, res};
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					auto db_delete::where(std::string column_name) const -> db_where {
 | 
				
			||||||
 | 
					  return db_where{context_, column_name};
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					} // namespace repertory::db
 | 
				
			||||||
@@ -24,10 +24,6 @@
 | 
				
			|||||||
namespace repertory::db {
 | 
					namespace repertory::db {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
auto db_select::column(std::string column_name) -> db_select & {
 | 
					auto db_select::column(std::string column_name) -> db_select & {
 | 
				
			||||||
  if (context_->delete_query) {
 | 
					 | 
				
			||||||
    throw std::runtime_error("columns may not be specified for delete");
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  context_->columns.push_back(column_name);
 | 
					  context_->columns.push_back(column_name);
 | 
				
			||||||
  return *this;
 | 
					  return *this;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -38,46 +34,34 @@ auto db_select::count(std::string column_name,
 | 
				
			|||||||
  return *this;
 | 
					  return *this;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
auto db_select::delete_query() -> db_select & {
 | 
					 | 
				
			||||||
  if (not context_->columns.empty()) {
 | 
					 | 
				
			||||||
    throw std::runtime_error("columns must be empty for delete");
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  context_->delete_query = true;
 | 
					 | 
				
			||||||
  return *this;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
auto db_select::dump() const -> std::string {
 | 
					auto db_select::dump() const -> std::string {
 | 
				
			||||||
  std::stringstream query;
 | 
					  std::stringstream query;
 | 
				
			||||||
  query << (context_->delete_query ? "DELETE " : "SELECT ");
 | 
					  query << "SELECT ";
 | 
				
			||||||
  if (not context_->delete_query) {
 | 
					  bool has_column{false};
 | 
				
			||||||
    bool has_column{false};
 | 
					  if (context_->columns.empty()) {
 | 
				
			||||||
    if (context_->columns.empty()) {
 | 
					    if (context_->count_columns.empty()) {
 | 
				
			||||||
      if (context_->count_columns.empty()) {
 | 
					      query << "*";
 | 
				
			||||||
        query << "*";
 | 
					      has_column = true;
 | 
				
			||||||
        has_column = true;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
      has_column = not context_->columns.empty();
 | 
					 | 
				
			||||||
      for (std::size_t idx = 0U; idx < context_->columns.size(); idx++) {
 | 
					 | 
				
			||||||
        if (idx > 0U) {
 | 
					 | 
				
			||||||
          query << ", ";
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        query << context_->columns.at(idx);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
    for (std::int32_t idx = 0U;
 | 
					    has_column = not context_->columns.empty();
 | 
				
			||||||
         idx < static_cast<std::int32_t>(context_->count_columns.size());
 | 
					    for (std::size_t idx = 0U; idx < context_->columns.size(); idx++) {
 | 
				
			||||||
         idx++) {
 | 
					      if (idx > 0U) {
 | 
				
			||||||
      if (has_column || idx > 0) {
 | 
					 | 
				
			||||||
        query << ", ";
 | 
					        query << ", ";
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      query << "COUNT(\"";
 | 
					      query << context_->columns.at(idx);
 | 
				
			||||||
      auto &count_column = *std::next(context_->count_columns.begin(), idx);
 | 
					 | 
				
			||||||
      query << count_column.first << "\") AS \"" << count_column.second << '"';
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (std::int32_t idx = 0U;
 | 
				
			||||||
 | 
					       idx < static_cast<std::int32_t>(context_->count_columns.size()); idx++) {
 | 
				
			||||||
 | 
					    if (has_column || idx > 0) {
 | 
				
			||||||
 | 
					      query << ", ";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    query << "COUNT(\"";
 | 
				
			||||||
 | 
					    auto &count_column = *std::next(context_->count_columns.begin(), idx);
 | 
				
			||||||
 | 
					    query << count_column.first << "\") AS \"" << count_column.second << '"';
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
  query << " FROM \"" << context_->table_name << "\"";
 | 
					  query << " FROM \"" << context_->table_name << "\"";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (not context_->ands.empty()) {
 | 
					  if (not context_->ands.empty()) {
 | 
				
			||||||
@@ -95,15 +79,13 @@ auto db_select::dump() const -> std::string {
 | 
				
			|||||||
    query << ")";
 | 
					    query << ")";
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (not context_->delete_query) {
 | 
					  if (context_->order_by.has_value()) {
 | 
				
			||||||
    if (context_->order_by.has_value()) {
 | 
					    query << " ORDER BY \"" << context_->order_by.value().first << "\" ";
 | 
				
			||||||
      query << " ORDER BY \"" << context_->order_by.value().first << "\" ";
 | 
					    query << (context_->order_by.value().second ? "ASC" : "DESC");
 | 
				
			||||||
      query << (context_->order_by.value().second ? "ASC" : "DESC");
 | 
					  }
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (context_->limit.has_value()) {
 | 
					  if (context_->limit.has_value()) {
 | 
				
			||||||
      query << " LIMIT " << context_->limit.value();
 | 
					    query << " LIMIT " << context_->limit.value();
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  query << ';';
 | 
					  query << ';';
 | 
				
			||||||
@@ -153,20 +135,12 @@ auto db_select::go() const -> db_result<context> {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
auto db_select::limit(std::int32_t value) -> db_select & {
 | 
					auto db_select::limit(std::int32_t value) -> db_select & {
 | 
				
			||||||
  if (context_->delete_query) {
 | 
					 | 
				
			||||||
    throw std::runtime_error("limit may not be specified for delete");
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  context_->limit = value;
 | 
					  context_->limit = value;
 | 
				
			||||||
  return *this;
 | 
					  return *this;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
auto db_select::order_by(std::string column_name,
 | 
					auto db_select::order_by(std::string column_name,
 | 
				
			||||||
                         bool ascending) -> db_select & {
 | 
					                         bool ascending) -> db_select & {
 | 
				
			||||||
  if (context_->delete_query) {
 | 
					 | 
				
			||||||
    throw std::runtime_error("order_by may not be specified for delete");
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  context_->order_by = {column_name, ascending};
 | 
					  context_->order_by = {column_name, ascending};
 | 
				
			||||||
  return *this;
 | 
					  return *this;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -39,7 +39,7 @@ auto db_update::dump() const -> std::string {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    auto column = std::next(context_->values.begin(), idx);
 | 
					    auto column = std::next(context_->values.begin(), idx);
 | 
				
			||||||
    query << column->first << " = ?";
 | 
					    query << column->first << "=?" + std::to_string(idx + 1U);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (not context_->ands.empty()) {
 | 
					  if (not context_->ands.empty()) {
 | 
				
			||||||
@@ -52,11 +52,20 @@ auto db_update::dump() const -> std::string {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
      auto &item = context_->ands.at(static_cast<std::size_t>(idx));
 | 
					      auto &item = context_->ands.at(static_cast<std::size_t>(idx));
 | 
				
			||||||
      query << '"' << item.column_name << '"' << item.op_type << "?"
 | 
					      query << '"' << item.column_name << '"' << item.op_type << "?"
 | 
				
			||||||
            << (idx + 1);
 | 
					            << (idx + context_->values.size() + 1U);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    query << ")";
 | 
					    query << ")";
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (context_->order_by.has_value()) {
 | 
				
			||||||
 | 
					    query << " ORDER BY \"" << context_->order_by.value().first << "\" ";
 | 
				
			||||||
 | 
					    query << (context_->order_by.value().second ? "ASC" : "DESC");
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (context_->limit.has_value()) {
 | 
				
			||||||
 | 
					    query << " LIMIT " << context_->limit.value();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  query << ';';
 | 
					  query << ';';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return query.str();
 | 
					  return query.str();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,6 +23,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "app_config.hpp"
 | 
					#include "app_config.hpp"
 | 
				
			||||||
#include "database/db_common.hpp"
 | 
					#include "database/db_common.hpp"
 | 
				
			||||||
 | 
					#include "database/db_delete.hpp"
 | 
				
			||||||
#include "database/db_insert.hpp"
 | 
					#include "database/db_insert.hpp"
 | 
				
			||||||
#include "database/db_select.hpp"
 | 
					#include "database/db_select.hpp"
 | 
				
			||||||
#include "database/db_update.hpp"
 | 
					#include "database/db_update.hpp"
 | 
				
			||||||
@@ -565,8 +566,7 @@ auto file_manager::remove_file(const std::string &api_path) -> api_error {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  remove_upload(api_path);
 | 
					  remove_upload(api_path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  auto result = db::db_select{*db_.get(), resume_table}
 | 
					  auto result = db::db_delete{*db_.get(), resume_table}
 | 
				
			||||||
                    .delete_query()
 | 
					 | 
				
			||||||
                    .where("api_path")
 | 
					                    .where("api_path")
 | 
				
			||||||
                    .equals(api_path)
 | 
					                    .equals(api_path)
 | 
				
			||||||
                    .go();
 | 
					                    .go();
 | 
				
			||||||
@@ -587,8 +587,7 @@ auto file_manager::remove_file(const std::string &api_path) -> api_error {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void file_manager::remove_resume(const std::string &api_path,
 | 
					void file_manager::remove_resume(const std::string &api_path,
 | 
				
			||||||
                                 const std::string &source_path) {
 | 
					                                 const std::string &source_path) {
 | 
				
			||||||
  auto result = db::db_select{*db_.get(), resume_table}
 | 
					  auto result = db::db_delete{*db_.get(), resume_table}
 | 
				
			||||||
                    .delete_query()
 | 
					 | 
				
			||||||
                    .where("api_path")
 | 
					                    .where("api_path")
 | 
				
			||||||
                    .equals(api_path)
 | 
					                    .equals(api_path)
 | 
				
			||||||
                    .go();
 | 
					                    .go();
 | 
				
			||||||
@@ -612,14 +611,12 @@ void file_manager::remove_upload(const std::string &api_path, bool no_lock) {
 | 
				
			|||||||
    lock = std::make_unique<mutex_lock>(upload_mtx_);
 | 
					    lock = std::make_unique<mutex_lock>(upload_mtx_);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  auto result = db::db_select{*db_.get(), upload_table}
 | 
					  auto result = db::db_delete{*db_.get(), upload_table}
 | 
				
			||||||
                    .delete_query()
 | 
					 | 
				
			||||||
                    .where("api_path")
 | 
					                    .where("api_path")
 | 
				
			||||||
                    .equals(api_path)
 | 
					                    .equals(api_path)
 | 
				
			||||||
                    .go();
 | 
					                    .go();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  result = db::db_select{*db_.get(), upload_active_table}
 | 
					  result = db::db_delete{*db_.get(), upload_active_table}
 | 
				
			||||||
               .delete_query()
 | 
					 | 
				
			||||||
               .where("api_path")
 | 
					               .where("api_path")
 | 
				
			||||||
               .equals(api_path)
 | 
					               .equals(api_path)
 | 
				
			||||||
               .go();
 | 
					               .go();
 | 
				
			||||||
@@ -996,8 +993,7 @@ void file_manager::upload_completed(const file_upload_completed &evt) {
 | 
				
			|||||||
  if (not utils::string::to_bool(evt.get_cancelled().get<std::string>())) {
 | 
					  if (not utils::string::to_bool(evt.get_cancelled().get<std::string>())) {
 | 
				
			||||||
    auto err = api_error_from_string(evt.get_result().get<std::string>());
 | 
					    auto err = api_error_from_string(evt.get_result().get<std::string>());
 | 
				
			||||||
    if (err == api_error::success) {
 | 
					    if (err == api_error::success) {
 | 
				
			||||||
      auto result = db::db_select{*db_.get(), upload_active_table}
 | 
					      auto result = db::db_delete{*db_.get(), upload_active_table}
 | 
				
			||||||
                        .delete_query()
 | 
					 | 
				
			||||||
                        .where("api_path")
 | 
					                        .where("api_path")
 | 
				
			||||||
                        .equals(evt.get_api_path().get<std::string>())
 | 
					                        .equals(evt.get_api_path().get<std::string>())
 | 
				
			||||||
                        .go();
 | 
					                        .go();
 | 
				
			||||||
@@ -1071,8 +1067,7 @@ void file_manager::upload_handler() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            upload_lookup_[fsi.api_path] =
 | 
					            upload_lookup_[fsi.api_path] =
 | 
				
			||||||
                std::make_unique<upload>(fsi, provider_);
 | 
					                std::make_unique<upload>(fsi, provider_);
 | 
				
			||||||
            auto del_res = db::db_select{*db_.get(), upload_table}
 | 
					            auto del_res = db::db_delete{*db_.get(), upload_table}
 | 
				
			||||||
                               .delete_query()
 | 
					 | 
				
			||||||
                               .where("api_path")
 | 
					                               .where("api_path")
 | 
				
			||||||
                               .equals(api_path)
 | 
					                               .equals(api_path)
 | 
				
			||||||
                               .go();
 | 
					                               .go();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,6 +22,7 @@
 | 
				
			|||||||
#include "providers/encrypt/encrypt_provider.hpp"
 | 
					#include "providers/encrypt/encrypt_provider.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "database/db_common.hpp"
 | 
					#include "database/db_common.hpp"
 | 
				
			||||||
 | 
					#include "database/db_delete.hpp"
 | 
				
			||||||
#include "database/db_insert.hpp"
 | 
					#include "database/db_insert.hpp"
 | 
				
			||||||
#include "database/db_select.hpp"
 | 
					#include "database/db_select.hpp"
 | 
				
			||||||
#include "events/event_system.hpp"
 | 
					#include "events/event_system.hpp"
 | 
				
			||||||
@@ -999,14 +1000,12 @@ void encrypt_provider::remove_deleted_files() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  for (auto &&item : removed_list) {
 | 
					  for (auto &&item : removed_list) {
 | 
				
			||||||
    if (not item.directory) {
 | 
					    if (not item.directory) {
 | 
				
			||||||
      auto del_res = db::db_select{*db_, source_table}
 | 
					      auto del_res = db::db_delete{*db_, source_table}
 | 
				
			||||||
                         .delete_query()
 | 
					 | 
				
			||||||
                         .where("api_path")
 | 
					                         .where("api_path")
 | 
				
			||||||
                         .equals(item.api_path)
 | 
					                         .equals(item.api_path)
 | 
				
			||||||
                         .go();
 | 
					                         .go();
 | 
				
			||||||
      // TODO handle error
 | 
					      // TODO handle error
 | 
				
			||||||
      del_res = db::db_select{*db_, file_table}
 | 
					      del_res = db::db_delete{*db_, file_table}
 | 
				
			||||||
                    .delete_query()
 | 
					 | 
				
			||||||
                    .where("source_path")
 | 
					                    .where("source_path")
 | 
				
			||||||
                    .equals(item.source_path)
 | 
					                    .equals(item.source_path)
 | 
				
			||||||
                    .go();
 | 
					                    .go();
 | 
				
			||||||
@@ -1018,14 +1017,12 @@ void encrypt_provider::remove_deleted_files() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  for (auto &&item : removed_list) {
 | 
					  for (auto &&item : removed_list) {
 | 
				
			||||||
    if (item.directory) {
 | 
					    if (item.directory) {
 | 
				
			||||||
      auto del_res = db::db_select{*db_, source_table}
 | 
					      auto del_res = db::db_delete{*db_, source_table}
 | 
				
			||||||
                         .delete_query()
 | 
					 | 
				
			||||||
                         .where("api_path")
 | 
					                         .where("api_path")
 | 
				
			||||||
                         .equals(item.api_path)
 | 
					                         .equals(item.api_path)
 | 
				
			||||||
                         .go();
 | 
					                         .go();
 | 
				
			||||||
      // TODO handle error
 | 
					      // TODO handle error
 | 
				
			||||||
      del_res = db::db_select{*db_, directory_table}
 | 
					      del_res = db::db_delete{*db_, directory_table}
 | 
				
			||||||
                    .delete_query()
 | 
					 | 
				
			||||||
                    .where("source_path")
 | 
					                    .where("source_path")
 | 
				
			||||||
                    .equals(item.source_path)
 | 
					                    .equals(item.source_path)
 | 
				
			||||||
                    .go();
 | 
					                    .go();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,6 +23,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "app_config.hpp"
 | 
					#include "app_config.hpp"
 | 
				
			||||||
#include "database/db_common.hpp"
 | 
					#include "database/db_common.hpp"
 | 
				
			||||||
 | 
					#include "database/db_delete.hpp"
 | 
				
			||||||
#include "database/db_insert.hpp"
 | 
					#include "database/db_insert.hpp"
 | 
				
			||||||
#include "database/db_select.hpp"
 | 
					#include "database/db_select.hpp"
 | 
				
			||||||
#include "utils/error_utils.hpp"
 | 
					#include "utils/error_utils.hpp"
 | 
				
			||||||
@@ -241,11 +242,8 @@ void meta_db::remove_api_path(const std::string &api_path) {
 | 
				
			|||||||
      static_cast<const char *>(__FUNCTION__),
 | 
					      static_cast<const char *>(__FUNCTION__),
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  auto result = db::db_select{*db_, table_name}
 | 
					  auto result =
 | 
				
			||||||
                    .delete_query()
 | 
					      db::db_delete{*db_, table_name}.where("api_path").equals(api_path).go();
 | 
				
			||||||
                    .where("api_path")
 | 
					 | 
				
			||||||
                    .equals(api_path)
 | 
					 | 
				
			||||||
                    .go();
 | 
					 | 
				
			||||||
  if (not result.ok()) {
 | 
					  if (not result.ok()) {
 | 
				
			||||||
    utils::error::raise_api_path_error(
 | 
					    utils::error::raise_api_path_error(
 | 
				
			||||||
        function_name, api_path, result.get_error(), "failed to remove meta");
 | 
					        function_name, api_path, result.get_error(), "failed to remove meta");
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,12 +22,45 @@
 | 
				
			|||||||
#include "test_common.hpp"
 | 
					#include "test_common.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "database/db_common.hpp"
 | 
					#include "database/db_common.hpp"
 | 
				
			||||||
 | 
					#include "database/db_delete.hpp"
 | 
				
			||||||
#include "database/db_insert.hpp"
 | 
					#include "database/db_insert.hpp"
 | 
				
			||||||
#include "database/db_select.hpp"
 | 
					#include "database/db_select.hpp"
 | 
				
			||||||
#include "utils/path.hpp"
 | 
					#include "utils/path.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace repertory {
 | 
					namespace repertory {
 | 
				
			||||||
TEST(database, db_insert) {
 | 
					TEST(database, db_delete_query) {
 | 
				
			||||||
 | 
					  console_consumer consumer1;
 | 
				
			||||||
 | 
					  event_system::instance().start();
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    db::db3_t db3;
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      sqlite3 *db3_ptr{nullptr};
 | 
				
			||||||
 | 
					      auto res = sqlite3_open_v2(
 | 
				
			||||||
 | 
					          utils::path::combine(test::get_test_input_dir(), {"test.db3"})
 | 
				
			||||||
 | 
					              .c_str(),
 | 
				
			||||||
 | 
					          &db3_ptr, SQLITE_OPEN_READWRITE, nullptr);
 | 
				
			||||||
 | 
					      ASSERT_EQ(SQLITE_OK, res);
 | 
				
			||||||
 | 
					      ASSERT_TRUE(db3_ptr != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      db3.reset(db3_ptr);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto query = db::db_delete{*db3.get(), "table"}
 | 
				
			||||||
 | 
					                     .where("column1")
 | 
				
			||||||
 | 
					                     .equals("test1")
 | 
				
			||||||
 | 
					                     .and_where("column2")
 | 
				
			||||||
 | 
					                     .equals("test2");
 | 
				
			||||||
 | 
					    auto query_str = query.dump();
 | 
				
			||||||
 | 
					    std::cout << query_str << std::endl;
 | 
				
			||||||
 | 
					    EXPECT_STREQ(
 | 
				
			||||||
 | 
					        R"(DELETE FROM "table" WHERE ("column1"=?1 AND "column2"=?2);)",
 | 
				
			||||||
 | 
					        query_str.c_str());
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  event_system::instance().stop();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST(database, db_insert_query) {
 | 
				
			||||||
  console_consumer consumer1;
 | 
					  console_consumer consumer1;
 | 
				
			||||||
  event_system::instance().start();
 | 
					  event_system::instance().start();
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
@@ -52,26 +85,43 @@ TEST(database, db_insert) {
 | 
				
			|||||||
    EXPECT_STREQ(
 | 
					    EXPECT_STREQ(
 | 
				
			||||||
        R"(INSERT INTO "table" ("column1", "column2") VALUES (?1, ?2);)",
 | 
					        R"(INSERT INTO "table" ("column1", "column2") VALUES (?1, ?2);)",
 | 
				
			||||||
        query_str.c_str());
 | 
					        query_str.c_str());
 | 
				
			||||||
 | 
					 | 
				
			||||||
    query = db::db_insert{*db3.get(), "table"}
 | 
					 | 
				
			||||||
                .or_replace()
 | 
					 | 
				
			||||||
                .column_value("column1", "test1")
 | 
					 | 
				
			||||||
                .column_value("column2", "test2");
 | 
					 | 
				
			||||||
    query_str = query.dump();
 | 
					 | 
				
			||||||
    std::cout << query_str << std::endl;
 | 
					 | 
				
			||||||
    EXPECT_STREQ(
 | 
					 | 
				
			||||||
        R"(INSERT OR REPLACE INTO "table" ("column1", "column2") VALUES (?1, ?2);)",
 | 
					 | 
				
			||||||
        query_str.c_str());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    auto res = query.go();
 | 
					 | 
				
			||||||
    EXPECT_TRUE(res.ok());
 | 
					 | 
				
			||||||
    EXPECT_FALSE(res.has_row());
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  event_system::instance().stop();
 | 
					  event_system::instance().stop();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TEST(database, db_select) {
 | 
					TEST(database, db_insert_or_replace_query) {
 | 
				
			||||||
 | 
					  console_consumer consumer1;
 | 
				
			||||||
 | 
					  event_system::instance().start();
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    db::db3_t db3;
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      sqlite3 *db3_ptr{nullptr};
 | 
				
			||||||
 | 
					      auto res = sqlite3_open_v2(
 | 
				
			||||||
 | 
					          utils::path::combine(test::get_test_input_dir(), {"test.db3"})
 | 
				
			||||||
 | 
					              .c_str(),
 | 
				
			||||||
 | 
					          &db3_ptr, SQLITE_OPEN_READWRITE, nullptr);
 | 
				
			||||||
 | 
					      ASSERT_EQ(SQLITE_OK, res);
 | 
				
			||||||
 | 
					      ASSERT_TRUE(db3_ptr != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      db3.reset(db3_ptr);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto query = db::db_insert{*db3.get(), "table"}
 | 
				
			||||||
 | 
					                     .or_replace()
 | 
				
			||||||
 | 
					                     .column_value("column1", "test1")
 | 
				
			||||||
 | 
					                     .column_value("column2", "test2");
 | 
				
			||||||
 | 
					    query_str = query.dump();
 | 
				
			||||||
 | 
					    std::cout << query_str << std::endl;
 | 
				
			||||||
 | 
					    EXPECT_STREQ(
 | 
				
			||||||
 | 
					        R"(INSERT OR REPLACE INTO "table" ("column1", "column2") VALUES (?1, ?2);)",
 | 
				
			||||||
 | 
					        query_str.c_str());
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  event_system::instance().stop();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST(database, db_select_query) {
 | 
				
			||||||
  console_consumer consumer1;
 | 
					  console_consumer consumer1;
 | 
				
			||||||
  event_system::instance().start();
 | 
					  event_system::instance().start();
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
@@ -98,25 +148,75 @@ TEST(database, db_select) {
 | 
				
			|||||||
    EXPECT_STREQ(
 | 
					    EXPECT_STREQ(
 | 
				
			||||||
        R"(SELECT * FROM "table" WHERE ("column1"=?1 AND "column2"=?2);)",
 | 
					        R"(SELECT * FROM "table" WHERE ("column1"=?1 AND "column2"=?2);)",
 | 
				
			||||||
        query_str.c_str());
 | 
					        query_str.c_str());
 | 
				
			||||||
    auto res = query.go();
 | 
					    // auto res = query.go();
 | 
				
			||||||
 | 
					    //
 | 
				
			||||||
 | 
					    // EXPECT_TRUE(res.ok());
 | 
				
			||||||
 | 
					    // EXPECT_TRUE(res.has_row());
 | 
				
			||||||
 | 
					    // std::size_t row_count{};
 | 
				
			||||||
 | 
					    // while (res.has_row()) {
 | 
				
			||||||
 | 
					    //   std::optional<db::db_select::row> row;
 | 
				
			||||||
 | 
					    //   EXPECT_TRUE(res.get_row(row));
 | 
				
			||||||
 | 
					    //   EXPECT_TRUE(row.has_value());
 | 
				
			||||||
 | 
					    //   if (row.has_value()) {
 | 
				
			||||||
 | 
					    //     for (const auto &column : row.value().get_columns()) {
 | 
				
			||||||
 | 
					    //       std::cout << column.get_index() << ':';
 | 
				
			||||||
 | 
					    //       std::cout << column.get_name() << ':';
 | 
				
			||||||
 | 
					    //       std::cout << column.get_value<std::string>() << std::endl;
 | 
				
			||||||
 | 
					    //     }
 | 
				
			||||||
 | 
					    //   }
 | 
				
			||||||
 | 
					    //   ++row_count;
 | 
				
			||||||
 | 
					    // }
 | 
				
			||||||
 | 
					    // EXPECT_EQ(std::size_t(1U), row_count);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    EXPECT_TRUE(res.ok());
 | 
					  event_system::instance().stop();
 | 
				
			||||||
    EXPECT_TRUE(res.has_row());
 | 
					}
 | 
				
			||||||
    std::size_t row_count{};
 | 
					
 | 
				
			||||||
    while (res.has_row()) {
 | 
					TEST(database, db_update_query) {
 | 
				
			||||||
      std::optional<db::db_select::row> row;
 | 
					  console_consumer consumer1;
 | 
				
			||||||
      EXPECT_TRUE(res.get_row(row));
 | 
					  event_system::instance().start();
 | 
				
			||||||
      EXPECT_TRUE(row.has_value());
 | 
					  {
 | 
				
			||||||
      if (row.has_value()) {
 | 
					    db::db3_t db3;
 | 
				
			||||||
        for (const auto &column : row.value().get_columns()) {
 | 
					    {
 | 
				
			||||||
          std::cout << column.get_index() << ':';
 | 
					      sqlite3 *db3_ptr{nullptr};
 | 
				
			||||||
          std::cout << column.get_name() << ':';
 | 
					      auto res = sqlite3_open_v2(
 | 
				
			||||||
          std::cout << column.get_value<std::string>() << std::endl;
 | 
					          utils::path::combine(test::get_test_input_dir(), {"test.db3"})
 | 
				
			||||||
        }
 | 
					              .c_str(),
 | 
				
			||||||
      }
 | 
					          &db3_ptr, SQLITE_OPEN_READWRITE, nullptr);
 | 
				
			||||||
      ++row_count;
 | 
					      ASSERT_EQ(SQLITE_OK, res);
 | 
				
			||||||
 | 
					      ASSERT_TRUE(db3_ptr != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      db3.reset(db3_ptr);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    EXPECT_EQ(std::size_t(1U), row_count);
 | 
					
 | 
				
			||||||
 | 
					    auto query = db::db_update{*db3.get(), "table"}
 | 
				
			||||||
 | 
					                     .column()
 | 
				
			||||||
 | 
					                     .where("column1")
 | 
				
			||||||
 | 
					                     .equals("test1")
 | 
				
			||||||
 | 
					                     .and_where("column2")
 | 
				
			||||||
 | 
					                     .equals("test2");
 | 
				
			||||||
 | 
					    auto query_str = query.dump();
 | 
				
			||||||
 | 
					    std::cout << query_str << std::endl;
 | 
				
			||||||
 | 
					    EXPECT_STREQ(R"(UPDATE "table" SET ;)", query_str.c_str());
 | 
				
			||||||
 | 
					    // auto res = query.go();
 | 
				
			||||||
 | 
					    //
 | 
				
			||||||
 | 
					    // EXPECT_TRUE(res.ok());
 | 
				
			||||||
 | 
					    // EXPECT_TRUE(res.has_row());
 | 
				
			||||||
 | 
					    // std::size_t row_count{};
 | 
				
			||||||
 | 
					    // while (res.has_row()) {
 | 
				
			||||||
 | 
					    //   std::optional<db::db_select::row> row;
 | 
				
			||||||
 | 
					    //   EXPECT_TRUE(res.get_row(row));
 | 
				
			||||||
 | 
					    //   EXPECT_TRUE(row.has_value());
 | 
				
			||||||
 | 
					    //   if (row.has_value()) {
 | 
				
			||||||
 | 
					    //     for (const auto &column : row.value().get_columns()) {
 | 
				
			||||||
 | 
					    //       std::cout << column.get_index() << ':';
 | 
				
			||||||
 | 
					    //       std::cout << column.get_name() << ':';
 | 
				
			||||||
 | 
					    //       std::cout << column.get_value<std::string>() << std::endl;
 | 
				
			||||||
 | 
					    //     }
 | 
				
			||||||
 | 
					    //   }
 | 
				
			||||||
 | 
					    //   ++row_count;
 | 
				
			||||||
 | 
					    // }
 | 
				
			||||||
 | 
					    // EXPECT_EQ(std::size_t(1U), row_count);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  event_system::instance().stop();
 | 
					  event_system::instance().stop();
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										
											BIN
										
									
								
								repertory/repertory_test/test_config/test.db3
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								repertory/repertory_test/test_config/test.db3
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
		Reference in New Issue
	
	Block a user