#pragma once #include #include #include #include #include #include #include #include using namespace std::string_literals; template typename std::enable_if::value, std::int64_t>::type extract_row_value(Statement& statement, const int i) { return statement.get_column_int64(i); } template typename std::enable_if::value, T>::type extract_row_value(Statement& statement, const int i) { return statement.get_column_text(i); } template typename std::enable_if::value, T>::type extract_row_value(Statement& statement, const int i) { const auto integer = statement.get_column_int(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) { 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&, Statement&) {} template struct SelectQuery: public Query { SelectQuery(std::string table_name): Query("SELECT"), table_name(table_name) { this->insert_col_name(); this->body += " from " + this->table_name; } template typename std::enable_if::type insert_col_name() { using ColumnsType = std::tuple; using ColumnType = typename std::remove_reference(std::declval()))>::type; this->body += " " + std::string{ColumnType::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(DatabaseEngine& db) { std::vector> rows; #ifdef DEBUG_SQL_QUERIES const auto timer = this->log_and_time(); #endif auto statement = db.prepare(this->body); statement->bind(std::move(this->params)); while (statement->step() == StepResult::Row) { Row row(this->table_name); extract_row_values(row, *statement); rows.push_back(row); } return rows; } const std::string table_name; };