Skip to content

Commit 1ff604f

Browse files
committed
Log sqlstate.
1 parent af1252a commit 1ff604f

File tree

4 files changed

+37
-17
lines changed

4 files changed

+37
-17
lines changed

dut.hh

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,29 +12,31 @@ namespace dut {
1212

1313
struct failure : public std::exception {
1414
std::string errstr;
15+
std::string sqlstate;
1516
const char* what() const throw()
1617
{
1718
return errstr.c_str();
1819
}
19-
failure(const char *s) throw()
20-
: errstr() {
20+
failure(const char *s, const char *sqlstate_ = "") throw()
21+
: errstr(), sqlstate() {
2122
errstr = s;
23+
sqlstate = sqlstate_;
2224
};
2325
};
2426

2527
struct broken : failure {
26-
broken(const char *s) throw()
27-
: failure(s) { }
28+
broken(const char *s, const char *sqlstate_ = "") throw()
29+
: failure(s, sqlstate_) { }
2830
};
2931

3032
struct timeout : failure {
31-
timeout(const char *s) throw()
32-
: failure(s) { }
33+
timeout(const char *s, const char *sqlstate_ = "") throw()
34+
: failure(s, sqlstate_) { }
3335
};
3436

3537
struct syntax : failure {
36-
syntax(const char *s) throw()
37-
: failure(s) { }
38+
syntax(const char *s, const char *sqlstate_ = "") throw()
39+
: failure(s, sqlstate_) { }
3840
};
3941

4042
}

log.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,8 @@ pqxx_logger::pqxx_logger(std::string target, std::string conninfo, struct schema
146146
id = r[0][0].as<long>(id);
147147

148148
c->prepare("error",
149-
"insert into error (id, msg, query) "
150-
"values (" + to_string(id) + ", $1, $2)");
149+
"insert into error (id, msg, query, sqlstate) "
150+
"values (" + to_string(id) + ", $1, $2, $3)");
151151

152152
w.exec("insert into stat (id) values (" + to_string(id) + ")");
153153
c->prepare("stat",
@@ -164,7 +164,7 @@ void pqxx_logger::error(prod &query, const dut::failure &e)
164164
work w(*c);
165165
ostringstream s;
166166
s << query;
167-
w.prepared("error")(e.what())(s.str()).exec();
167+
w.prepared("error")(e.what())(s.str())(e.sqlstate).exec();
168168
w.commit();
169169
}
170170

log.sql

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ create table error (
2020
msg text, -- error message
2121
query text, -- failed query
2222
target text, -- conninfo of the target
23+
sqlstate text, -- sqlstate of error
2324

2425
-- not referenced by sqlsmith:
2526
t timestamptz default now(),
@@ -63,6 +64,20 @@ create view report as
6364
select count(1), max(t) as last_seen, error
6465
from base_error group by 3 order by count desc;
6566

67+
68+
create or replace view state_report as
69+
SELECT count(1) AS count,
70+
sqlstate,
71+
min(substring(firstline(e.msg),1,80)) AS sample,
72+
array_agg(DISTINCT i.hostname) AS hosts
73+
FROM error e
74+
JOIN instance i ON i.id = e.id
75+
WHERE e.t > (now() - '24:00:00'::interval)
76+
GROUP BY sqlstate
77+
ORDER BY (count(1));
78+
79+
comment on view state_report is 'an sqlstate-grouped report';
80+
6681
comment on view report is 'same report as sqlsmith''s verbose output';
6782

6883
drop view if exists report24h;
@@ -126,6 +141,7 @@ create trigger discard_known before insert on error
126141
-- YMMV.
127142
create index on error(t);
128143

144+
-- Following views are used for debugging sqlsmith
129145
create view impedance as
130146
select id, generated, level, nodes, updated,
131147
prod, ok, bad, js.retries, limited, failed

postgres.cc

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ void dut_libpq::connect(std::string &conninfo)
308308
conn = PQconnectdb(conninfo.c_str());
309309
char *errmsg = PQerrorMessage(conn);
310310
if (strlen(errmsg))
311-
throw dut::broken(errmsg);
311+
throw dut::broken(errmsg, "08000");
312312

313313
test("set statement_timeout to '1s'");
314314
test("set client_min_messages to 'ERROR';");
@@ -330,25 +330,27 @@ void dut_libpq::test(const std::string &stmt)
330330

331331
PGresult *res = PQexec(conn, stmt.c_str());
332332
int status = PQresultStatus(res);
333-
const char *sqlstate;
334333

335334
switch (status) {
336335

337336
case PGRES_FATAL_ERROR:
338337
default:
339338
{
340-
sqlstate = PQresultErrorField(res, PG_DIAG_SQLSTATE);
341-
(void) sqlstate;
339+
char *sqlstate = PQresultErrorField(res, PG_DIAG_SQLSTATE);
342340
char *errmsg = PQresultErrorMessage(res);
343341
std::string error_string(errmsg);
342+
std::string sqlstate_string(sqlstate);
344343
PQclear(res);
345344

346345
ConnStatusType connstatus = PQstatus(conn);
347346
if (CONNECTION_OK != connstatus) {
348347
conn = 0;
349-
throw dut::broken(error_string.c_str());
348+
throw dut::broken(error_string.c_str(), sqlstate_string.c_str());
350349
}
351-
throw dut::failure(error_string.c_str());
350+
if (sqlstate_string == "42601")
351+
throw dut::syntax(error_string.c_str(), sqlstate_string.c_str());
352+
else
353+
throw dut::failure(error_string.c_str(), sqlstate_string.c_str());
352354
}
353355

354356
case PGRES_NONFATAL_ERROR:

0 commit comments

Comments
 (0)