Repository navigation
Expand file tree
/
Copy pathsqlite_from_sql_error_probe.cpp
More file actions
101 lines (97 loc) · 4.45 KB
/
Copy pathsqlite_from_sql_error_probe.cpp
File metadata and controls
101 lines (97 loc) · 4.45 KB
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
#include <teaql/provider_sqlite/from_sql_error.hpp>
#include <teaql/provider_sqlite/driver_error.hpp>
#include <teaql/runtime/context.hpp>
#include "debug_modes.hpp"
#include "fixture_value.hpp"
#include <iostream>
static SqliteFromSqlError make_error(Memory owner, const Json& input) {
auto kind = text(field(input, "kind"));
if (kind == "invalid") {
return SqliteFromSqlError::invalid_type(owner);
}
if (kind == "range") {
return SqliteFromSqlError::out_of_range(owner, number<std::int64_t>(field(input, "value")));
}
if (kind == "blob") {
return SqliteFromSqlError::invalid_blob_size(owner,
number<std::size_t>(field(input, "expected")),
number<std::size_t>(field(input, "actual")));
}
Vector<std::uint8_t> bytes(owner);
for (const auto& value : std::get<Json::Array>(field(input, "bytes").data)) {
bytes.push_back(static_cast<std::uint8_t>(std::get<std::uint64_t>(value.data)));
}
auto utf8 = SqliteUtf8Error::validate(
std::string_view(reinterpret_cast<const char*>(bytes.data()), bytes.size()));
if (!utf8) {
throw std::invalid_argument("UTF-8 conversion fixture is valid");
}
if (kind == "utf8") {
return SqliteFromSqlError::utf8_error(owner, *utf8);
}
if (kind == "other") {
return SqliteFromSqlError::other(owner,
SqliteBoxedError::make<SqliteUtf8Error>(owner, *utf8));
}
throw std::invalid_argument("Unknown column-conversion fixture");
}
static Json chain(Memory owner, SqliteErrorCauseView source) {
Json::Array values(owner);
while (source) {
Json::Object value(owner);
value.emplace("debug", formatted_debug(owner, source));
value.emplace("display", Json(owner, source.to_string(owner)));
values.emplace_back(Json(owner, std::move(value)));
source = source.source();
}
return Json(owner, std::move(values));
}
static Json evaluate(Memory owner, const Json& input, bool raw_debug) {
auto error = make_error(owner, input);
auto other = make_error(owner, input);
Json::Object model(owner);
model.emplace("debug", formatted_debug(owner, error));
model.emplace("display", Json(owner, error.to_string(owner)));
model.emplace("self_equal", Json(owner, error == error));
model.emplace("fresh_equal", Json(owner, error == other));
model.emplace("chain", chain(owner, error.source()));
auto converted = std::move(error).into_driver_error(owner);
auto range = converted.kind() == SqliteDriverError::Kind::IntegralValueOutOfRange;
Json::Object result(owner), driver(owner);
result.emplace("model", Json(owner, std::move(model)));
driver.emplace("kind",
Json(owner, range ? "IntegralValueOutOfRange" : "FromSqlConversionFailure"));
driver.emplace(
"unknown_index",
Json(owner,
range ? converted.simple_error().index() == SIZE_MAX
: std::get<SqliteDriverError::BoxedFailure>(converted.payload()).index ==
SIZE_MAX));
auto blob = !range && std::get<SqliteDriverError::BoxedFailure>(converted.payload()).type ==
SqliteValueType::Blob;
driver.emplace("type", range ? Json(owner) : Json(owner, blob ? "Blob" : "Null"));
driver.emplace("blob_type", Json(owner, blob));
driver.emplace("display", Json(owner, converted.to_string(owner)));
driver.emplace("chain", chain(owner, converted.source()));
driver.emplace("self_equal", Json(owner, converted == converted));
driver.emplace("native_none", Json(owner, converted.sqlite_error() == nullptr));
result.emplace("converted", Json(owner, std::move(driver)));
if (raw_debug) {
result.emplace("converted_raw_debug", formatted_debug(owner, converted));
}
return Json(owner, std::move(result));
}
int main(int argc, char** argv) {
const bool raw_debug = argc == 2 && std::string_view(argv[1]) == "--raw-debug";
GlobalContext global;
std::string line;
while (std::getline(std::cin, line)) {
auto user = global.make_user_context();
auto owner = user->memory_resource();
auto input = Json::parse(owner, line);
if (!input) {
throw std::invalid_argument("Invalid column-conversion fixture JSON");
}
std::cout << evaluate(owner, *input, raw_debug).dump(owner) << '\n';
}
}