#pragma once #include #include #include #include #include #include #include #include #include template typename std::enable_if, Id>::value, void>::type actual_bind(Statement& statement, std::vector& params, const std::tuple&) { const auto value = params.front(); params.erase(params.begin()); if (sqlite3_bind_text(statement.get(), N + 1, value.data(), static_cast(value.size()), SQLITE_TRANSIENT) != SQLITE_OK) log_error("Failed to bind ", value, " to param ", N); else log_debug("Bound (not id) [", value, "] to ", N); } template typename std::enable_if, Id>::value, void>::type actual_bind(Statement& statement, std::vector&, const std::tuple& columns) { auto&& column = std::get(columns); if (column.value != 0) { if (sqlite3_bind_int64(statement.get(), N + 1, static_cast(column.value)) != SQLITE_OK) log_error("Failed to bind ", column.value, " to id."); } else if (sqlite3_bind_null(statement.get(), N + 1) != SQLITE_OK) log_error("Failed to bind NULL to param ", N); else log_debug("Bound NULL to ", N); } struct InsertQuery: public Query { InsertQuery(const std::string& name): Query("INSERT OR REPLACE INTO ") { this->body += name; } template void execute(const std::tuple& columns, sqlite3* db) { auto statement = this->prepare(db); { this->bind_param<0>(columns, statement); if (sqlite3_step(statement.get()) != SQLITE_DONE) log_error("Failed to execute query: ", sqlite3_errmsg(db)); } } template typename std::enable_if::type bind_param(const std::tuple& columns, Statement& statement) { using ColumnType = typename std::remove_reference(columns))>::type; actual_bind(statement, this->params, columns); this->bind_param(columns, statement); } template typename std::enable_if::type bind_param(const std::tuple&, Statement&) {} template void insert_values(const std::tuple& columns) { this->body += "VALUES ("; this->insert_value<0>(columns); this->body += ")"; } template typename std::enable_if::type insert_value(const std::tuple& columns) { this->body += "?"; if (N != sizeof...(T) - 1) this->body += ","; this->body += " "; add_param(*this, std::get(columns)); this->insert_value(columns); } template typename std::enable_if::type insert_value(const std::tuple&) { } template void insert_col_names(const std::tuple& columns) { this->body += " ("; this->insert_col_name<0>(columns); this->body += ")\n"; } template typename std::enable_if::type insert_col_name(const std::tuple& columns) { using ColumnType = typename std::remove_reference(columns))>::type; this->body += ColumnType::name; if (N < (sizeof...(T) - 1)) this->body += ", "; this->insert_col_name(columns); } template typename std::enable_if::type insert_col_name(const std::tuple&) {} private: };