forked from osm2pgsql-dev/osm2pgsql
-
Notifications
You must be signed in to change notification settings - Fork 0
/
pgsql.cpp
141 lines (128 loc) · 4.49 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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/* Helper functions for the postgresql connections */
#include "pgsql.hpp"
#include <cstdio>
#include <cstdlib>
#include <cstdarg>
#include <memory>
#include <boost/format.hpp>
void escape(const std::string &src, std::string &dst)
{
for (const char c: src) {
switch(c) {
case '\\': dst.append("\\\\"); break;
//case 8: dst.append("\\\b"); break;
//case 12: dst.append("\\\f"); break;
case '\n': dst.append("\\\n"); break;
case '\r': dst.append("\\\r"); break;
case '\t': dst.append("\\\t"); break;
//case 11: dst.append("\\\v"); break;
default: dst.push_back(c); break;
}
}
}
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;
}