Repository navigation
Expand file tree
/
Copy pathbindings.cpp
More file actions
104 lines (96 loc) · 3.58 KB
/
Copy pathbindings.cpp
File metadata and controls
104 lines (96 loc) · 3.58 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
102
103
104
#include <teaql/sql/bindings.hpp>
namespace teaql {
namespace {
template <class T>
void append_binding(Vector<Value>& values,
Vector<SqlParameterLogPolicy>& policies,
T&& value,
SqlParameterLogPolicy policy) {
// Keep amortized vector growth and restore logical alignment if cloning the
// value fails. Scalar policy rollback cannot allocate or throw.
policies.push_back(policy);
try {
values.emplace_back(std::forward<T>(value));
} catch (...) {
policies.pop_back();
throw;
}
}
}
void SqlBindings::append(const Value& value, SqlParameterLogPolicy policy) {
append_binding(values_, policies_, value, policy);
}
void SqlBindings::append(Value&& value, SqlParameterLogPolicy policy) {
append_binding(values_, policies_, std::move(value), policy);
}
SqlLogContext SqlBindings::log_context(Memory r, DatabaseKind kind) const {
SqlLogContext result(r);
result.parameter_policies = policies_;
result.generated_sql = !untrusted_sql_;
switch (kind) {
case DatabaseKind::Sqlite:
result.database_kind.emplace("sqlite", r);
break;
case DatabaseKind::PostgreSql:
result.database_kind.emplace("postgresql", r);
break;
case DatabaseKind::MySql:
result.database_kind.emplace("mysql", r);
break;
}
return rebind_log_context(r, result);
}
SqlLogContext SqlBindings::rebind_log_context(Memory r, const SqlLogContext& source) const {
auto result = detail::clone_in(r, source);
SqlLogContext original_source(r);
original_source.generated_sql = source.generated_sql;
Vector<Value> values(r);
for (const auto& [index, value] : originals_) {
values.emplace_back(value);
original_source.parameter_policies.push_back(index < source.parameter_policies.size()
? source.parameter_policies[index]
: SqlParameterLogPolicy::Unknown);
}
result.intent_redactions = SqlIntentRedactions::from_bindings(r, original_source, values, {});
return result;
}
namespace detail {
SqlParameterLogPolicy sql_field_policy(const EntityDescriptor& entity, std::string_view field) {
return SqlIntentRedactions::field_policy(entity, field);
}
std::optional<SqlParameterLogPolicy> combine_sql_policy(std::optional<SqlParameterLogPolicy> a,
std::optional<SqlParameterLogPolicy> b) {
if (!a) {
return b;
}
if (!b) {
return a;
}
using P = SqlParameterLogPolicy;
for (auto policy : {P::Credential, P::Unknown, P::Masked}) {
if (a == policy || b == policy) {
return policy;
}
}
return P::Plain;
}
std::optional<SqlParameterLogPolicy> sql_expression_policy(const EntityDescriptor& entity,
const Expr& expr) {
using K = Expr::Kind;
if (expr.kind == K::Column) {
return sql_field_policy(entity, expr.name);
}
if (expr.kind == K::Value || expr.kind == K::LikePattern || expr.kind == K::And ||
expr.kind == K::Or || expr.kind == K::Not) {
return {};
}
std::optional<SqlParameterLogPolicy> result;
// SubQuery args contain only its left expression; its entity/query live in
// subquery_data, so their field policies cannot leak into this scalar scope.
for (const auto& arg : expr.args) {
result = combine_sql_policy(result, sql_expression_policy(entity, arg));
}
return result;
}
}
}