1#include "duckdb/main/prepared_statement_data.hpp"
2#include "duckdb/execution/physical_operator.hpp"
3#include "duckdb/parser/sql_statement.hpp"
4
5namespace duckdb {
6
7PreparedStatementData::PreparedStatementData(StatementType type) : statement_type(type) {
8}
9
10PreparedStatementData::~PreparedStatementData() {
11}
12
13void 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
21bool 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
44void 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
65bool 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
78LogicalType 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