#include "postgres_statement.hpp" #include "postgres_error.hpp" #include "postgres_parameter_binder.h" #include "postgres_result_reader.hpp" namespace matador::backends::postgres { postgres_statement::postgres_statement(PGconn *db, PGresult *res, std::string name, const sql::query_context &query) : statement_impl(query, 0) , db_(db) , res_(res) , name_(std::move(name)) {} postgres_statement::~postgres_statement() { PQclear(res_); } utils::result postgres_statement::execute(const sql::parameter_binder& bindings) { const auto* postgres_bindings = dynamic_cast(&bindings); if (!postgres_bindings) { return utils::failure(utils::error(sql::error_code::EXECUTE_FAILED, "Failed to cast bindings to postgres bindings")); } PGresult *res = PQexecPrepared(db_, name_.c_str(), static_cast(postgres_bindings->params().values.size()), postgres_bindings->params().values.data(), postgres_bindings->params().lengths.data(), postgres_bindings->params().formats.data(), 0); if (is_result_error(res)) { return utils::failure(make_error(sql::error_code::EXECUTE_FAILED, res, db_, "Failed to execute statement", query_.sql)); } size_t value{0}; if (const auto *tuples = PQcmdTuples(res); strlen(tuples) != 0) { value = std::stoul(tuples); } PQclear(res); return utils::ok(value); } utils::result, utils::error> postgres_statement::fetch(const sql::parameter_binder& bindings) { const auto* postgres_bindings = dynamic_cast(&bindings); if (!postgres_bindings) { return utils::failure(utils::error(sql::error_code::EXECUTE_FAILED, "Failed to cast bindings to postgres bindings")); } PGresult *res = PQexecPrepared(db_, name_.c_str(), static_cast(postgres_bindings->params().values.size()), postgres_bindings->params().values.data(), postgres_bindings->params().lengths.data(), postgres_bindings->params().formats.data(), 0); if (is_result_error(res)) { return utils::failure(make_error(sql::error_code::FETCH_FAILED, res, db_, "Failed to fetch statement", query_.sql)); } return utils::ok(std::make_unique(std::make_unique(res), query_.prototype)); } std::unique_ptr postgres_statement::create_binder() const { return std::make_unique(query_.bind_vars.size()); } }