forked from osm2pgsql-dev/osm2pgsql
-
Notifications
You must be signed in to change notification settings - Fork 0
/
pgsql.cpp
125 lines (113 loc) · 3.97 KB
/
pgsql.cpp
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
/* Helper functions for the postgresql connections */
#include "pgsql.hpp"
#include <cstdio>
#include <cstdlib>
#include <cstdarg>
#include <memory>
#include <boost/format.hpp>
pg_result_t pgsql_exec_simple(PGconn *sql_conn, const ExecStatusType expect,
const std::string &sql)
{
return pgsql_exec_simple(sql_conn, expect, sql.c_str());
}
pg_result_t pgsql_exec_simple(PGconn *sql_conn, const ExecStatusType expect,
const char *sql)
{
#ifdef DEBUG_PGSQL
fprintf( stderr, "Executing: %s\n", sql );
#endif
pg_result_t res(PQexec(sql_conn, sql));
if (PQresultStatus(res.get()) != expect) {
throw std::runtime_error((boost::format("%1% failed: %2%\n") % sql % PQerrorMessage(sql_conn)).str());
}
return res;
}
int pgsql_exec(PGconn *sql_conn, const ExecStatusType expect, const char *fmt, ...)
{
va_list ap;
char *sql, *nsql;
int n, size = 100;
/* Based on vprintf manual page */
/* Guess we need no more than 100 bytes. */
if ((sql = static_cast<char *>(malloc(size))) == nullptr)
throw std::runtime_error("Memory allocation failed in pgsql_exec");
while (1) {
/* Try to print in the allocated space. */
va_start(ap, fmt);
n = vsnprintf(sql, size, fmt, ap);
va_end(ap);
/* If that worked, return the string. */
if (n > -1 && n < size)
break;
/* Else try again with more space. */
if (n > -1) /* glibc 2.1 */
size = n+1; /* precisely what is needed */
else /* glibc 2.0 */
size *= 2; /* twice the old size */
if ((nsql = static_cast<char *>(realloc (sql, size))) == nullptr) {
free(sql);
throw std::runtime_error("Memory re-allocation failed in pgsql_exec");
} else {
sql = nsql;
}
}
#ifdef DEBUG_PGSQL
fprintf( stderr, "Executing: %s\n", sql );
#endif
pg_result_t res(PQexec(sql_conn, sql));
if (PQresultStatus(res.get()) != expect) {
std::string err_msg = (boost::format("%1% failed: %2%") % sql % PQerrorMessage(sql_conn)).str();
free(sql);
throw std::runtime_error(err_msg);
}
free(sql);
return 0;
}
void pgsql_CopyData(const char *context, PGconn *sql_conn, std::string const &sql)
{
#ifdef DEBUG_PGSQL
fprintf(stderr, "%s>>> %s\n", context, sql.c_str());
#endif
int r = PQputCopyData(sql_conn, sql.c_str(), sql.size());
switch(r)
{
//need to wait for write ready
case 0:
throw std::runtime_error((boost::format("%1% - bad result during COPY, data %2%") % context % sql % PQerrorMessage(sql_conn)).str());
break;
//error occurred
case -1:
throw std::runtime_error((boost::format("%1%: %2% - bad result during COPY, data %3%") % PQerrorMessage(sql_conn) % context % sql).str());
break;
//other possibility is 1 which means success
}
}
pg_result_t pgsql_execPrepared(PGconn *sql_conn, const char *stmtName,
const int nParams,
const char *const *paramValues,
const ExecStatusType expect)
{
#ifdef DEBUG_PGSQL
fprintf( stderr, "ExecPrepared: %s\n", stmtName );
#endif
//run the prepared statement
pg_result_t res(PQexecPrepared(sql_conn, stmtName, nParams, paramValues,
nullptr, nullptr, 0));
if (PQresultStatus(res.get()) != expect) {
std::string message =
(boost::format("%1% failed: %2%(%3%)\n") % stmtName %
PQerrorMessage(sql_conn) % PQresultStatus(res.get()))
.str();
if(nParams)
{
message += "Arguments were: ";
for(int i = 0; i < nParams; i++)
{
message += paramValues[i]?paramValues[i]:"<NULL>";
message += ", ";
}
}
throw std::runtime_error(message);
}
return res;
}