1 | #include "duckdb/main/prepared_statement_data.hpp" |
2 | #include "duckdb/execution/physical_operator.hpp" |
3 | #include "duckdb/parser/sql_statement.hpp" |
4 | |
5 | namespace duckdb { |
6 | |
7 | PreparedStatementData::PreparedStatementData(StatementType type) : statement_type(type) { |
8 | } |
9 | |
10 | PreparedStatementData::~PreparedStatementData() { |
11 | } |
12 | |
13 | void PreparedStatementData::CheckParameterCount(idx_t parameter_count) { |
14 | const auto required = properties.parameter_count; |
15 | if (parameter_count != required) { |
16 | throw BinderException("Parameter/argument count mismatch for prepared statement. Expected %llu, got %llu" , |
17 | required, parameter_count); |
18 | } |
19 | } |
20 | |
21 | bool PreparedStatementData::RequireRebind(ClientContext &context, const vector<Value> &values) { |
22 | CheckParameterCount(parameter_count: values.size()); |
23 | if (!unbound_statement) { |
24 | // no unbound statement!? cannot rebind? |
25 | return false; |
26 | } |
27 | if (!properties.bound_all_parameters) { |
28 | // parameters not yet bound: query always requires a rebind |
29 | return true; |
30 | } |
31 | if (Catalog::GetSystemCatalog(context).GetCatalogVersion() != catalog_version) { |
32 | //! context is out of bounds |
33 | return true; |
34 | } |
35 | for (auto &it : value_map) { |
36 | const idx_t i = it.first - 1; |
37 | if (values[i].type() != it.second->return_type) { |
38 | return true; |
39 | } |
40 | } |
41 | return false; |
42 | } |
43 | |
44 | void PreparedStatementData::Bind(vector<Value> values) { |
45 | // set parameters |
46 | D_ASSERT(!unbound_statement || unbound_statement->n_param == properties.parameter_count); |
47 | CheckParameterCount(parameter_count: values.size()); |
48 | |
49 | // bind the required values |
50 | for (auto &it : value_map) { |
51 | const idx_t i = it.first - 1; |
52 | if (i >= values.size()) { |
53 | throw BinderException("Could not find parameter with index %llu" , i + 1); |
54 | } |
55 | D_ASSERT(it.second); |
56 | if (!values[i].DefaultTryCastAs(target_type: it.second->return_type)) { |
57 | throw BinderException( |
58 | "Type mismatch for binding parameter with index %llu, expected type %s but got type %s" , i + 1, |
59 | it.second->return_type.ToString().c_str(), values[i].type().ToString().c_str()); |
60 | } |
61 | it.second->value = values[i]; |
62 | } |
63 | } |
64 | |
65 | bool PreparedStatementData::TryGetType(idx_t param_idx, LogicalType &result) { |
66 | auto it = value_map.find(x: param_idx); |
67 | if (it == value_map.end()) { |
68 | return false; |
69 | } |
70 | if (it->second->return_type.id() != LogicalTypeId::INVALID) { |
71 | result = it->second->return_type; |
72 | } else { |
73 | result = it->second->value.type(); |
74 | } |
75 | return true; |
76 | } |
77 | |
78 | LogicalType PreparedStatementData::GetType(idx_t param_idx) { |
79 | LogicalType result; |
80 | if (!TryGetType(param_idx, result)) { |
81 | throw BinderException("Could not find parameter with index %llu" , param_idx); |
82 | } |
83 | return result; |
84 | } |
85 | |
86 | } // namespace duckdb |
87 | |