-
Notifications
You must be signed in to change notification settings - Fork 1
/
pgsql.c
155 lines (131 loc) · 2.97 KB
/
pgsql.c
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#include "common.h"
#include "conf.h"
#include "pgsql.h"
#include "stringlist.h"
static PGconn *conn = NULL;
int pgsql_init()
{
const char *conn_info = conf_get("pg_conn", DB_STRING);
if(!conn_info || !*conn_info)
{
error("No pgsql connection string set");
return 1;
}
conn = PQconnectdb(conn_info);
if(PQstatus(conn) != CONNECTION_OK)
{
error("Connection to database failed: %s", PQerrorMessage(conn));
PQfinish(conn);
return 1;
}
debug("Connected to pgsql database");
return 0;
}
void pgsql_fini()
{
PQfinish(conn);
conn = NULL;
}
void pgsql_free(PGresult *res)
{
if(res)
PQclear(res);
}
int pgsql_num_rows(PGresult *res)
{
return PQntuples(res);
}
int pgsql_num_affected(PGresult *res)
{
const char *str = PQcmdTuples(res);
assert(*str);
return atoi(str);
}
const char *pgsql_value(PGresult *res, int row, int col)
{
if(PQgetisnull(res, row, col))
return NULL;
return PQgetvalue(res, row, col);
}
const char *pgsql_nvalue(PGresult *res, int row, const char *col)
{
int fnum = PQfnumber(res, col);
if(fnum == -1)
{
error("Field `%s' does not exist", col);
exit(1);
}
if(PQgetisnull(res, row, fnum))
return NULL;
return PQgetvalue(res, row, fnum);
}
PGresult *pgsql_query(const char *query, int want_result, struct stringlist *params)
{
PGresult *res = NULL;
res = PQexecParams(conn, query, params ? params->count : 0, NULL, params ? (const char*const*)params->data : NULL, NULL, NULL, 0);
switch(PQresultStatus(res))
{
case PGRES_COMMAND_OK:
case PGRES_TUPLES_OK:
break;
default:
error("Unexpected PG result status (%s): %s", PQresStatus(PQresultStatus(res)), PQresultErrorMessage(res));
exit(1);
}
if(params)
stringlist_free(params);
if(!want_result)
{
PQclear(res);
return NULL;
}
return res;
}
int pgsql_query_int(const char *query, struct stringlist *params)
{
int val = 0;
const char *tmp;
PGresult *res = pgsql_query(query, 1, params);
if(pgsql_num_rows(res) > 0 && (tmp = pgsql_value(res, 0, 0)))
val = atoi(tmp);
pgsql_free(res);
return val;
}
int pgsql_query_bool(const char *query, struct stringlist *params)
{
return !strcasecmp(pgsql_query_str(query, params), "t");
}
char *pgsql_query_str(const char *query, struct stringlist *params)
{
static char buf[1024];
const char *tmp;
memset(buf, 0, sizeof(buf));
PGresult *res = pgsql_query(query, 1, params);
if(pgsql_num_rows(res) > 0 && (tmp = pgsql_value(res, 0, 0)))
strlcpy(buf, tmp, sizeof(buf));
pgsql_free(res);
return buf;
}
int pgsql_valid_for_type(const char *value, const char *type)
{
const char *tmp;
int valid = 0;
PGresult *res = pgsql_query("SELECT valid_for_type($1, $2)", 1, stringlist_build(value, type, NULL));
assert(pgsql_num_rows(res) == 1);
assert((tmp = pgsql_value(res, 0, 0)));
valid = !strcasecmp(tmp, "t");
pgsql_free(res);
return valid;
}
void pgsql_begin()
{
pgsql_query("BEGIN TRANSACTION", 0, NULL);
}
void pgsql_commit()
{
pgsql_query("COMMIT", 0, NULL);
}
void pgsql_rollback()
{
pgsql_query("ROLLBACK", 0, NULL);
}