~singpolyma/biboumi

ref: d7427fc9ca4c06fda458e4951559f57163d90b94 biboumi/src/database/postgresql_engine.cpp -rw-r--r-- 2.6 KiB
d7427fc9 — louiz’ Re-connect to postgresql when the connection is lost 5 years ago
                                                                                
414bbca0 louiz’
c3313d0d louiz’
7e64a2e3 louiz’
0168b96b louiz’
b1750843 louiz’
0168b96b louiz’
b1750843 louiz’
0168b96b louiz’
505deda1 louiz’
0168b96b louiz’
b1750843 louiz’
0168b96b louiz’
7e64a2e3 louiz’
0168b96b louiz’
c3313d0d louiz’
0168b96b louiz’
414bbca0 louiz’
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#include <biboumi.h>
#ifdef PQ_FOUND

#include <utils/scopeguard.hpp>

#include <database/query.hpp>

#include <database/postgresql_engine.hpp>

#include <database/postgresql_statement.hpp>

#include <logger/logger.hpp>

#include <cstring>

PostgresqlEngine::PostgresqlEngine(PGconn*const conn):
    conn(conn)
{}

PostgresqlEngine::~PostgresqlEngine()
{
  PQfinish(this->conn);
}

static void logging_notice_processor(void*, const char* original)
{
  if (original && std::strlen(original) > 0)
    {
      std::string message{original, std::strlen(original) - 1};
      log_warning("PostgreSQL: ", message);
    }
}

std::unique_ptr<DatabaseEngine> PostgresqlEngine::open(const std::string& conninfo)
{
  PGconn* con = PQconnectdb(conninfo.data());

  if (!con)
    {
      log_error("Failed to allocate a Postgresql connection");
      throw std::runtime_error("");
    }
  const auto status = PQstatus(con);
  if (status != CONNECTION_OK)
    {
      const char* errmsg = PQerrorMessage(con);
      log_error("Postgresql connection failed: ", errmsg);
      PQfinish(con);
      throw std::runtime_error("failed to open connection.");
    }
  PQsetNoticeProcessor(con, &logging_notice_processor, nullptr);
  return std::make_unique<PostgresqlEngine>(con);
}

std::set<std::string> PostgresqlEngine::get_all_columns_from_table(const std::string& table_name)
{
  const auto query = "SELECT column_name from information_schema.columns where table_name='" + table_name + "'";
  auto statement = this->prepare(query);
  std::set<std::string> columns;

  while (statement->step() == StepResult::Row)
    columns.insert(statement->get_column_text(0));

  return columns;
}

std::tuple<bool, std::string> PostgresqlEngine::raw_exec(const std::string& query)
{
#ifdef DEBUG_SQL_QUERIES
  log_debug("SQL QUERY: ", query);
  const auto timer = make_sql_timer();
#endif
  PGresult* res = PQexec(this->conn, query.data());
  auto sg = utils::make_scope_guard([res](){
      PQclear(res);
  });

  auto res_status = PQresultStatus(res);
  if (res_status != PGRES_COMMAND_OK)
    return std::make_tuple(false, PQresultErrorMessage(res));
  return std::make_tuple(true, std::string{});
}

std::unique_ptr<Statement> PostgresqlEngine::prepare(const std::string& query)
{
  return std::make_unique<PostgresqlStatement>(query, this->conn);
}

void PostgresqlEngine::extract_last_insert_rowid(Statement& statement)
{
  this->last_inserted_rowid = statement.get_column_int64(0);
}

std::string PostgresqlEngine::get_returning_id_sql_string(const std::string& col_name)
{
  return " RETURNING " + col_name;
}

std::string PostgresqlEngine::id_column_type()
{
  return "SERIAL";
}

#endif