duckdb 0.8.2-dev2509.0 → 0.8.2-dev2673.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/binding.gyp +1 -0
- package/package.json +1 -1
- package/src/duckdb/extension/icu/icu-datepart.cpp +3 -3
- package/src/duckdb/src/catalog/catalog_entry/duck_table_entry.cpp +1 -1
- package/src/duckdb/src/catalog/default/default_functions.cpp +5 -0
- package/src/duckdb/src/common/enum_util.cpp +35 -1
- package/src/duckdb/src/core_functions/aggregate/nested/list.cpp +6 -1
- package/src/duckdb/src/core_functions/scalar/list/array_slice.cpp +6 -0
- package/src/duckdb/src/execution/expression_executor/execute_parameter.cpp +2 -2
- package/src/duckdb/src/execution/index/art/art.cpp +43 -31
- package/src/duckdb/src/execution/index/art/leaf.cpp +47 -33
- package/src/duckdb/src/execution/index/art/node.cpp +31 -24
- package/src/duckdb/src/execution/index/art/prefix.cpp +100 -16
- package/src/duckdb/src/execution/operator/schema/physical_create_index.cpp +54 -31
- package/src/duckdb/src/execution/physical_plan/plan_create_index.cpp +32 -15
- package/src/duckdb/src/function/table/arrow/arrow_duck_schema.cpp +57 -0
- package/src/duckdb/src/function/table/arrow.cpp +95 -92
- package/src/duckdb/src/function/table/arrow_conversion.cpp +45 -68
- package/src/duckdb/src/function/table/version/pragma_version.cpp +2 -2
- package/src/duckdb/src/include/duckdb/common/case_insensitive_map.hpp +1 -0
- package/src/duckdb/src/include/duckdb/common/enum_util.hpp +8 -0
- package/src/duckdb/src/include/duckdb/common/helper.hpp +8 -3
- package/src/duckdb/src/include/duckdb/common/types/value.hpp +4 -1
- package/src/duckdb/src/include/duckdb/execution/index/art/art.hpp +7 -5
- package/src/duckdb/src/include/duckdb/execution/index/art/leaf.hpp +6 -6
- package/src/duckdb/src/include/duckdb/execution/index/art/node.hpp +6 -0
- package/src/duckdb/src/include/duckdb/execution/index/art/prefix.hpp +9 -11
- package/src/duckdb/src/include/duckdb/execution/operator/schema/physical_create_index.hpp +8 -1
- package/src/duckdb/src/include/duckdb/function/table/arrow/arrow_duck_schema.hpp +99 -0
- package/src/duckdb/src/include/duckdb/function/table/arrow.hpp +6 -36
- package/src/duckdb/src/include/duckdb/main/capi/capi_internal.hpp +3 -1
- package/src/duckdb/src/include/duckdb/main/client_context.hpp +15 -14
- package/src/duckdb/src/include/duckdb/main/prepared_statement.hpp +73 -5
- package/src/duckdb/src/include/duckdb/main/prepared_statement_data.hpp +6 -6
- package/src/duckdb/src/include/duckdb/parser/expression/parameter_expression.hpp +17 -1
- package/src/duckdb/src/include/duckdb/parser/statement/execute_statement.hpp +1 -1
- package/src/duckdb/src/include/duckdb/parser/transformer.hpp +5 -3
- package/src/duckdb/src/include/duckdb/planner/bound_parameter_map.hpp +2 -1
- package/src/duckdb/src/include/duckdb/planner/expression/bound_parameter_data.hpp +20 -5
- package/src/duckdb/src/include/duckdb/planner/expression/bound_parameter_expression.hpp +3 -3
- package/src/duckdb/src/include/duckdb/planner/planner.hpp +4 -3
- package/src/duckdb/src/include/duckdb/storage/object_cache.hpp +1 -1
- package/src/duckdb/src/include/duckdb/verification/prepared_statement_verifier.hpp +1 -1
- package/src/duckdb/src/include/duckdb.h +16 -0
- package/src/duckdb/src/main/capi/pending-c.cpp +6 -0
- package/src/duckdb/src/main/capi/prepared-c.cpp +52 -4
- package/src/duckdb/src/main/client_context.cpp +27 -17
- package/src/duckdb/src/main/client_verify.cpp +17 -0
- package/src/duckdb/src/main/prepared_statement.cpp +38 -11
- package/src/duckdb/src/main/prepared_statement_data.cpp +23 -18
- package/src/duckdb/src/parallel/executor.cpp +3 -0
- package/src/duckdb/src/parser/expression/parameter_expression.cpp +7 -7
- package/src/duckdb/src/parser/statement/execute_statement.cpp +2 -2
- package/src/duckdb/src/parser/transform/expression/transform_param_ref.cpp +45 -26
- package/src/duckdb/src/parser/transform/statement/transform_prepare.cpp +28 -6
- package/src/duckdb/src/parser/transformer.cpp +27 -9
- package/src/duckdb/src/planner/binder/expression/bind_parameter_expression.cpp +10 -10
- package/src/duckdb/src/planner/binder/statement/bind_execute.cpp +13 -7
- package/src/duckdb/src/planner/expression/bound_parameter_expression.cpp +13 -13
- package/src/duckdb/src/planner/planner.cpp +7 -6
- package/src/duckdb/src/storage/checkpoint_manager.cpp +1 -1
- package/src/duckdb/src/storage/serialization/serialize_expression.cpp +3 -3
- package/src/duckdb/src/storage/serialization/serialize_parsed_expression.cpp +2 -2
- package/src/duckdb/src/verification/prepared_statement_verifier.cpp +16 -11
- package/src/duckdb/third_party/libpg_query/src_backend_parser_gram.cpp +9652 -9482
- package/src/duckdb/ub_src_function_table_arrow.cpp +2 -0
@@ -23,6 +23,7 @@
|
|
23
23
|
#include "nodes/parsenodes.hpp"
|
24
24
|
#include "nodes/primnodes.hpp"
|
25
25
|
#include "pg_definitions.hpp"
|
26
|
+
#include "duckdb/parser/expression/parameter_expression.hpp"
|
26
27
|
|
27
28
|
namespace duckdb {
|
28
29
|
|
@@ -67,6 +68,8 @@ private:
|
|
67
68
|
idx_t prepared_statement_parameter_index = 0;
|
68
69
|
//! Map from named parameter to parameter index;
|
69
70
|
case_insensitive_map_t<idx_t> named_param_map;
|
71
|
+
//! Last parameter type
|
72
|
+
PreparedParamType last_param_type = PreparedParamType::INVALID;
|
70
73
|
//! Holds window expressions defined by name. We need those when transforming the expressions referring to them.
|
71
74
|
unordered_map<string, duckdb_libpgquery::PGWindowDef *> window_clauses;
|
72
75
|
//! The set of pivot entries to create
|
@@ -82,9 +85,8 @@ private:
|
|
82
85
|
Transformer &RootTransformer();
|
83
86
|
const Transformer &RootTransformer() const;
|
84
87
|
void SetParamCount(idx_t new_count);
|
85
|
-
void
|
86
|
-
bool
|
87
|
-
bool HasNamedParameters() const;
|
88
|
+
void SetParam(const string &name, idx_t index, PreparedParamType type);
|
89
|
+
bool GetParam(const string &name, idx_t &index, PreparedParamType type);
|
88
90
|
|
89
91
|
void AddPivotEntry(string enum_name, unique_ptr<SelectNode> source, unique_ptr<ParsedExpression> column,
|
90
92
|
unique_ptr<QueryNode> subquery);
|
@@ -10,11 +10,12 @@
|
|
10
10
|
|
11
11
|
#include "duckdb/common/types.hpp"
|
12
12
|
#include "duckdb/common/unordered_map.hpp"
|
13
|
+
#include "duckdb/common/case_insensitive_map.hpp"
|
13
14
|
|
14
15
|
namespace duckdb {
|
15
16
|
|
16
17
|
struct BoundParameterData;
|
17
18
|
|
18
|
-
using bound_parameter_map_t =
|
19
|
+
using bound_parameter_map_t = case_insensitive_map_t<shared_ptr<BoundParameterData>>;
|
19
20
|
|
20
21
|
} // namespace duckdb
|
@@ -11,19 +11,32 @@
|
|
11
11
|
#include "duckdb/common/types/value.hpp"
|
12
12
|
#include "duckdb/planner/bound_parameter_map.hpp"
|
13
13
|
#include "duckdb/common/field_writer.hpp"
|
14
|
+
#include "duckdb/common/case_insensitive_map.hpp"
|
14
15
|
|
15
16
|
namespace duckdb {
|
16
17
|
|
17
18
|
struct BoundParameterData {
|
19
|
+
public:
|
18
20
|
BoundParameterData() {
|
19
21
|
}
|
20
22
|
explicit BoundParameterData(Value val) : value(std::move(val)), return_type(value.type()) {
|
21
23
|
}
|
22
24
|
|
25
|
+
private:
|
23
26
|
Value value;
|
27
|
+
|
28
|
+
public:
|
24
29
|
LogicalType return_type;
|
25
30
|
|
26
31
|
public:
|
32
|
+
void SetValue(Value val) {
|
33
|
+
value = std::move(val);
|
34
|
+
}
|
35
|
+
|
36
|
+
const Value &GetValue() const {
|
37
|
+
return value;
|
38
|
+
}
|
39
|
+
|
27
40
|
void Serialize(Serializer &serializer) const {
|
28
41
|
FieldWriter writer(serializer);
|
29
42
|
value.Serialize(writer.GetSerializer());
|
@@ -45,17 +58,19 @@ public:
|
|
45
58
|
};
|
46
59
|
|
47
60
|
struct BoundParameterMap {
|
48
|
-
explicit BoundParameterMap(
|
61
|
+
explicit BoundParameterMap(case_insensitive_map_t<BoundParameterData> ¶meter_data)
|
62
|
+
: parameter_data(parameter_data) {
|
49
63
|
}
|
50
64
|
|
51
65
|
bound_parameter_map_t parameters;
|
52
|
-
|
66
|
+
case_insensitive_map_t<BoundParameterData> ¶meter_data;
|
53
67
|
|
54
|
-
LogicalType GetReturnType(
|
55
|
-
|
68
|
+
LogicalType GetReturnType(const string &identifier) {
|
69
|
+
auto it = parameter_data.find(identifier);
|
70
|
+
if (it == parameter_data.end()) {
|
56
71
|
return LogicalTypeId::UNKNOWN;
|
57
72
|
}
|
58
|
-
return
|
73
|
+
return it->second.return_type;
|
59
74
|
}
|
60
75
|
};
|
61
76
|
|
@@ -18,9 +18,9 @@ public:
|
|
18
18
|
static constexpr const ExpressionClass TYPE = ExpressionClass::BOUND_PARAMETER;
|
19
19
|
|
20
20
|
public:
|
21
|
-
explicit BoundParameterExpression(
|
21
|
+
explicit BoundParameterExpression(const string &identifier);
|
22
22
|
|
23
|
-
|
23
|
+
string identifier;
|
24
24
|
shared_ptr<BoundParameterData> parameter_data;
|
25
25
|
|
26
26
|
public:
|
@@ -47,7 +47,7 @@ public:
|
|
47
47
|
static unique_ptr<Expression> FormatDeserialize(FormatDeserializer &deserializer);
|
48
48
|
|
49
49
|
private:
|
50
|
-
BoundParameterExpression(bound_parameter_map_t &global_parameter_set,
|
50
|
+
BoundParameterExpression(bound_parameter_map_t &global_parameter_set, string identifier, LogicalType return_type,
|
51
51
|
shared_ptr<BoundParameterData> parameter_data);
|
52
52
|
};
|
53
53
|
|
@@ -25,21 +25,22 @@ class Planner {
|
|
25
25
|
public:
|
26
26
|
explicit Planner(ClientContext &context);
|
27
27
|
|
28
|
+
public:
|
28
29
|
unique_ptr<LogicalOperator> plan;
|
29
30
|
vector<string> names;
|
30
31
|
vector<LogicalType> types;
|
31
|
-
|
32
|
-
vector<BoundParameterData> parameter_data;
|
32
|
+
case_insensitive_map_t<BoundParameterData> parameter_data;
|
33
33
|
|
34
34
|
shared_ptr<Binder> binder;
|
35
35
|
ClientContext &context;
|
36
36
|
|
37
37
|
StatementProperties properties;
|
38
|
+
bound_parameter_map_t value_map;
|
38
39
|
|
39
40
|
public:
|
40
41
|
void CreatePlan(unique_ptr<SQLStatement> statement);
|
41
42
|
static void VerifyPlan(ClientContext &context, unique_ptr<LogicalOperator> &op,
|
42
|
-
bound_parameter_map_t
|
43
|
+
optional_ptr<bound_parameter_map_t> map = nullptr);
|
43
44
|
|
44
45
|
private:
|
45
46
|
void CreatePlan(SQLStatement &statement);
|
@@ -21,7 +21,7 @@ public:
|
|
21
21
|
const std::function<unique_ptr<QueryResult>(const string &, unique_ptr<SQLStatement>)> &run) override;
|
22
22
|
|
23
23
|
private:
|
24
|
-
|
24
|
+
case_insensitive_map_t<unique_ptr<ParsedExpression>> values;
|
25
25
|
unique_ptr<SQLStatement> prepare_statement;
|
26
26
|
unique_ptr<SQLStatement> execute_statement;
|
27
27
|
unique_ptr<SQLStatement> dealloc_statement;
|
@@ -944,6 +944,16 @@ Returns 0 if the query was not successfully prepared.
|
|
944
944
|
*/
|
945
945
|
DUCKDB_API idx_t duckdb_nparams(duckdb_prepared_statement prepared_statement);
|
946
946
|
|
947
|
+
/*!
|
948
|
+
Returns the name used to identify the parameter
|
949
|
+
The returned string should be freed using `duckdb_free`.
|
950
|
+
|
951
|
+
Returns NULL if the index is out of range for the provided prepared statement.
|
952
|
+
|
953
|
+
* prepared_statement: The prepared statement for which to get the parameter name from.
|
954
|
+
*/
|
955
|
+
const char *duckdb_parameter_name(duckdb_prepared_statement prepared_statement, idx_t index);
|
956
|
+
|
947
957
|
/*!
|
948
958
|
Returns the parameter type for the parameter at the given index.
|
949
959
|
|
@@ -960,6 +970,12 @@ Clear the params bind to the prepared statement.
|
|
960
970
|
*/
|
961
971
|
DUCKDB_API duckdb_state duckdb_clear_bindings(duckdb_prepared_statement prepared_statement);
|
962
972
|
|
973
|
+
/*!
|
974
|
+
Retrieve the index of the parameter for the prepared statement, identified by name
|
975
|
+
*/
|
976
|
+
DUCKDB_API duckdb_state duckdb_bind_parameter_index(duckdb_prepared_statement prepared_statement, idx_t *param_idx_out,
|
977
|
+
const char *name);
|
978
|
+
|
963
979
|
/*!
|
964
980
|
Binds a bool value to the prepared statement at the specified index.
|
965
981
|
*/
|
@@ -2,12 +2,17 @@
|
|
2
2
|
#include "duckdb/main/query_result.hpp"
|
3
3
|
#include "duckdb/main/pending_query_result.hpp"
|
4
4
|
#include "duckdb/common/preserved_error.hpp"
|
5
|
+
#include "duckdb/common/case_insensitive_map.hpp"
|
6
|
+
#include "duckdb/common/optional_ptr.hpp"
|
5
7
|
|
8
|
+
using duckdb::case_insensitive_map_t;
|
6
9
|
using duckdb::make_uniq;
|
10
|
+
using duckdb::optional_ptr;
|
7
11
|
using duckdb::PendingExecutionResult;
|
8
12
|
using duckdb::PendingQueryResult;
|
9
13
|
using duckdb::PendingStatementWrapper;
|
10
14
|
using duckdb::PreparedStatementWrapper;
|
15
|
+
using duckdb::Value;
|
11
16
|
|
12
17
|
duckdb_state duckdb_pending_prepared_internal(duckdb_prepared_statement prepared_statement,
|
13
18
|
duckdb_pending_result *out_result, bool allow_streaming) {
|
@@ -17,6 +22,7 @@ duckdb_state duckdb_pending_prepared_internal(duckdb_prepared_statement prepared
|
|
17
22
|
auto wrapper = reinterpret_cast<PreparedStatementWrapper *>(prepared_statement);
|
18
23
|
auto result = new PendingStatementWrapper();
|
19
24
|
result->allow_streaming = allow_streaming;
|
25
|
+
|
20
26
|
try {
|
21
27
|
result->statement = wrapper->statement->PendingQuery(wrapper->values, allow_streaming);
|
22
28
|
} catch (const duckdb::Exception &ex) {
|
@@ -2,7 +2,10 @@
|
|
2
2
|
#include "duckdb/main/query_result.hpp"
|
3
3
|
#include "duckdb/main/prepared_statement_data.hpp"
|
4
4
|
#include "duckdb/common/types/decimal.hpp"
|
5
|
+
#include "duckdb/common/optional_ptr.hpp"
|
6
|
+
#include "duckdb/common/case_insensitive_map.hpp"
|
5
7
|
|
8
|
+
using duckdb::case_insensitive_map_t;
|
6
9
|
using duckdb::Connection;
|
7
10
|
using duckdb::date_t;
|
8
11
|
using duckdb::dtime_t;
|
@@ -10,8 +13,10 @@ using duckdb::ExtractStatementsWrapper;
|
|
10
13
|
using duckdb::hugeint_t;
|
11
14
|
using duckdb::LogicalType;
|
12
15
|
using duckdb::MaterializedQueryResult;
|
16
|
+
using duckdb::optional_ptr;
|
13
17
|
using duckdb::PreparedStatementWrapper;
|
14
18
|
using duckdb::QueryResultType;
|
19
|
+
using duckdb::StringUtil;
|
15
20
|
using duckdb::timestamp_t;
|
16
21
|
using duckdb::Value;
|
17
22
|
|
@@ -84,13 +89,42 @@ idx_t duckdb_nparams(duckdb_prepared_statement prepared_statement) {
|
|
84
89
|
return wrapper->statement->n_param;
|
85
90
|
}
|
86
91
|
|
92
|
+
static duckdb::string duckdb_parameter_name_internal(duckdb_prepared_statement prepared_statement, idx_t index) {
|
93
|
+
auto wrapper = (PreparedStatementWrapper *)prepared_statement;
|
94
|
+
if (!wrapper || !wrapper->statement || wrapper->statement->HasError()) {
|
95
|
+
return duckdb::string();
|
96
|
+
}
|
97
|
+
if (index > wrapper->statement->n_param) {
|
98
|
+
return duckdb::string();
|
99
|
+
}
|
100
|
+
for (auto &item : wrapper->statement->named_param_map) {
|
101
|
+
auto &identifier = item.first;
|
102
|
+
auto ¶m_idx = item.second;
|
103
|
+
if (param_idx == index) {
|
104
|
+
// Found the matching parameter
|
105
|
+
return identifier;
|
106
|
+
}
|
107
|
+
}
|
108
|
+
// No parameter was found with this index
|
109
|
+
return duckdb::string();
|
110
|
+
}
|
111
|
+
|
112
|
+
const char *duckdb_parameter_name(duckdb_prepared_statement prepared_statement, idx_t index) {
|
113
|
+
auto identifier = duckdb_parameter_name_internal(prepared_statement, index);
|
114
|
+
if (identifier == duckdb::string()) {
|
115
|
+
return NULL;
|
116
|
+
}
|
117
|
+
return strdup(identifier.c_str());
|
118
|
+
}
|
119
|
+
|
87
120
|
duckdb_type duckdb_param_type(duckdb_prepared_statement prepared_statement, idx_t param_idx) {
|
88
121
|
auto wrapper = reinterpret_cast<PreparedStatementWrapper *>(prepared_statement);
|
89
122
|
if (!wrapper || !wrapper->statement || wrapper->statement->HasError()) {
|
90
123
|
return DUCKDB_TYPE_INVALID;
|
91
124
|
}
|
92
125
|
LogicalType param_type;
|
93
|
-
|
126
|
+
auto identifier = std::to_string(param_idx);
|
127
|
+
if (!wrapper->statement->data->TryGetType(identifier, param_type)) {
|
94
128
|
return DUCKDB_TYPE_INVALID;
|
95
129
|
}
|
96
130
|
return ConvertCPPTypeToC(param_type);
|
@@ -113,10 +147,23 @@ static duckdb_state duckdb_bind_value(duckdb_prepared_statement prepared_stateme
|
|
113
147
|
if (param_idx <= 0 || param_idx > wrapper->statement->n_param) {
|
114
148
|
return DuckDBError;
|
115
149
|
}
|
116
|
-
|
117
|
-
|
150
|
+
auto identifier = duckdb_parameter_name_internal(prepared_statement, param_idx);
|
151
|
+
wrapper->values[identifier] = val;
|
152
|
+
return DuckDBSuccess;
|
153
|
+
}
|
154
|
+
|
155
|
+
duckdb_state duckdb_bind_parameter_index(duckdb_prepared_statement prepared_statement, idx_t *param_idx_out,
|
156
|
+
const char *name) {
|
157
|
+
auto wrapper = (PreparedStatementWrapper *)prepared_statement;
|
158
|
+
if (!wrapper || !wrapper->statement || wrapper->statement->HasError()) {
|
159
|
+
return DuckDBError;
|
160
|
+
}
|
161
|
+
auto &statement = wrapper->statement;
|
162
|
+
auto entry = statement->named_param_map.find(name);
|
163
|
+
if (entry == statement->named_param_map.end()) {
|
164
|
+
return DuckDBError;
|
118
165
|
}
|
119
|
-
|
166
|
+
*param_idx_out = entry->second;
|
120
167
|
return DuckDBSuccess;
|
121
168
|
}
|
122
169
|
|
@@ -232,6 +279,7 @@ duckdb_state duckdb_execute_prepared(duckdb_prepared_statement prepared_statemen
|
|
232
279
|
if (!wrapper || !wrapper->statement || wrapper->statement->HasError()) {
|
233
280
|
return DuckDBError;
|
234
281
|
}
|
282
|
+
|
235
283
|
auto result = wrapper->statement->Execute(wrapper->values, false);
|
236
284
|
return duckdb_translate_result(std::move(result), out_result);
|
237
285
|
}
|
@@ -304,9 +304,9 @@ static bool IsExplainAnalyze(SQLStatement *statement) {
|
|
304
304
|
return explain.explain_type == ExplainType::EXPLAIN_ANALYZE;
|
305
305
|
}
|
306
306
|
|
307
|
-
shared_ptr<PreparedStatementData>
|
308
|
-
|
309
|
-
|
307
|
+
shared_ptr<PreparedStatementData>
|
308
|
+
ClientContext::CreatePreparedStatement(ClientContextLock &lock, const string &query, unique_ptr<SQLStatement> statement,
|
309
|
+
optional_ptr<case_insensitive_map_t<Value>> values) {
|
310
310
|
StatementType statement_type = statement->type;
|
311
311
|
auto result = make_shared<PreparedStatementData>(statement_type);
|
312
312
|
|
@@ -315,8 +315,9 @@ shared_ptr<PreparedStatementData> ClientContext::CreatePreparedStatement(ClientC
|
|
315
315
|
profiler.StartPhase("planner");
|
316
316
|
Planner planner(*this);
|
317
317
|
if (values) {
|
318
|
-
|
319
|
-
|
318
|
+
auto ¶meter_values = *values;
|
319
|
+
for (auto &value : parameter_values) {
|
320
|
+
planner.parameter_data.emplace(value);
|
320
321
|
}
|
321
322
|
}
|
322
323
|
|
@@ -370,7 +371,7 @@ double ClientContext::GetProgress() {
|
|
370
371
|
|
371
372
|
unique_ptr<PendingQueryResult> ClientContext::PendingPreparedStatement(ClientContextLock &lock,
|
372
373
|
shared_ptr<PreparedStatementData> statement_p,
|
373
|
-
PendingQueryParameters parameters) {
|
374
|
+
const PendingQueryParameters ¶meters) {
|
374
375
|
D_ASSERT(active_query);
|
375
376
|
auto &statement = *statement_p;
|
376
377
|
if (ValidChecker::IsInvalidated(ActiveTransaction()) && statement.properties.requires_valid_transaction) {
|
@@ -392,7 +393,14 @@ unique_ptr<PendingQueryResult> ClientContext::PendingPreparedStatement(ClientCon
|
|
392
393
|
}
|
393
394
|
|
394
395
|
// bind the bound values before execution
|
395
|
-
|
396
|
+
case_insensitive_map_t<Value> owned_values;
|
397
|
+
if (parameters.parameters) {
|
398
|
+
auto ¶ms = *parameters.parameters;
|
399
|
+
for (auto &val : params) {
|
400
|
+
owned_values.emplace(val);
|
401
|
+
}
|
402
|
+
}
|
403
|
+
statement.Bind(std::move(owned_values));
|
396
404
|
|
397
405
|
active_query->executor = make_uniq<Executor>(*this);
|
398
406
|
auto &executor = *active_query->executor;
|
@@ -566,7 +574,7 @@ unique_ptr<PreparedStatement> ClientContext::Prepare(const string &query) {
|
|
566
574
|
|
567
575
|
unique_ptr<PendingQueryResult> ClientContext::PendingQueryPreparedInternal(ClientContextLock &lock, const string &query,
|
568
576
|
shared_ptr<PreparedStatementData> &prepared,
|
569
|
-
PendingQueryParameters parameters) {
|
577
|
+
const PendingQueryParameters ¶meters) {
|
570
578
|
try {
|
571
579
|
InitialCleanup(lock);
|
572
580
|
} catch (const Exception &ex) {
|
@@ -579,13 +587,13 @@ unique_ptr<PendingQueryResult> ClientContext::PendingQueryPreparedInternal(Clien
|
|
579
587
|
|
580
588
|
unique_ptr<PendingQueryResult> ClientContext::PendingQuery(const string &query,
|
581
589
|
shared_ptr<PreparedStatementData> &prepared,
|
582
|
-
PendingQueryParameters parameters) {
|
590
|
+
const PendingQueryParameters ¶meters) {
|
583
591
|
auto lock = LockContext();
|
584
592
|
return PendingQueryPreparedInternal(*lock, query, prepared, parameters);
|
585
593
|
}
|
586
594
|
|
587
595
|
unique_ptr<QueryResult> ClientContext::Execute(const string &query, shared_ptr<PreparedStatementData> &prepared,
|
588
|
-
PendingQueryParameters parameters) {
|
596
|
+
const PendingQueryParameters ¶meters) {
|
589
597
|
auto lock = LockContext();
|
590
598
|
auto pending = PendingQueryPreparedInternal(*lock, query, prepared, parameters);
|
591
599
|
if (pending->HasError()) {
|
@@ -595,7 +603,7 @@ unique_ptr<QueryResult> ClientContext::Execute(const string &query, shared_ptr<P
|
|
595
603
|
}
|
596
604
|
|
597
605
|
unique_ptr<QueryResult> ClientContext::Execute(const string &query, shared_ptr<PreparedStatementData> &prepared,
|
598
|
-
|
606
|
+
case_insensitive_map_t<Value> &values, bool allow_stream_result) {
|
599
607
|
PendingQueryParameters parameters;
|
600
608
|
parameters.parameters = &values;
|
601
609
|
parameters.allow_stream_result = allow_stream_result;
|
@@ -604,10 +612,11 @@ unique_ptr<QueryResult> ClientContext::Execute(const string &query, shared_ptr<P
|
|
604
612
|
|
605
613
|
unique_ptr<PendingQueryResult> ClientContext::PendingStatementInternal(ClientContextLock &lock, const string &query,
|
606
614
|
unique_ptr<SQLStatement> statement,
|
607
|
-
PendingQueryParameters parameters) {
|
615
|
+
const PendingQueryParameters ¶meters) {
|
608
616
|
// prepare the query for execution
|
609
617
|
auto prepared = CreatePreparedStatement(lock, query, std::move(statement), parameters.parameters);
|
610
|
-
|
618
|
+
idx_t parameter_count = !parameters.parameters ? 0 : parameters.parameters->size();
|
619
|
+
if (prepared->properties.parameter_count > 0 && parameter_count == 0) {
|
611
620
|
string error_message = StringUtil::Format("Expected %lld parameters, but none were supplied",
|
612
621
|
prepared->properties.parameter_count);
|
613
622
|
return make_uniq<PendingQueryResult>(PreservedError(error_message));
|
@@ -640,7 +649,7 @@ bool ClientContext::IsActiveResult(ClientContextLock &lock, BaseQueryResult *res
|
|
640
649
|
|
641
650
|
unique_ptr<PendingQueryResult> ClientContext::PendingStatementOrPreparedStatementInternal(
|
642
651
|
ClientContextLock &lock, const string &query, unique_ptr<SQLStatement> statement,
|
643
|
-
shared_ptr<PreparedStatementData> &prepared, PendingQueryParameters parameters) {
|
652
|
+
shared_ptr<PreparedStatementData> &prepared, const PendingQueryParameters ¶meters) {
|
644
653
|
// check if we are on AutoCommit. In this case we should start a transaction.
|
645
654
|
if (statement && config.AnyVerification()) {
|
646
655
|
// query verification is enabled
|
@@ -697,7 +706,7 @@ unique_ptr<PendingQueryResult> ClientContext::PendingStatementOrPreparedStatemen
|
|
697
706
|
|
698
707
|
unique_ptr<PendingQueryResult> ClientContext::PendingStatementOrPreparedStatement(
|
699
708
|
ClientContextLock &lock, const string &query, unique_ptr<SQLStatement> statement,
|
700
|
-
shared_ptr<PreparedStatementData> &prepared, PendingQueryParameters parameters) {
|
709
|
+
shared_ptr<PreparedStatementData> &prepared, const PendingQueryParameters ¶meters) {
|
701
710
|
unique_ptr<PendingQueryResult> result;
|
702
711
|
|
703
712
|
try {
|
@@ -722,7 +731,7 @@ unique_ptr<PendingQueryResult> ClientContext::PendingStatementOrPreparedStatemen
|
|
722
731
|
if (statement) {
|
723
732
|
result = PendingStatementInternal(lock, query, std::move(statement), parameters);
|
724
733
|
} else {
|
725
|
-
if (prepared->RequireRebind(*this,
|
734
|
+
if (prepared->RequireRebind(*this, parameters.parameters)) {
|
726
735
|
// catalog was modified: rebind the statement before execution
|
727
736
|
auto new_prepared =
|
728
737
|
CreatePreparedStatement(lock, query, prepared->unbound_statement->Copy(), parameters.parameters);
|
@@ -884,7 +893,8 @@ unique_ptr<PendingQueryResult> ClientContext::PendingQuery(unique_ptr<SQLStateme
|
|
884
893
|
|
885
894
|
unique_ptr<PendingQueryResult> ClientContext::PendingQueryInternal(ClientContextLock &lock,
|
886
895
|
unique_ptr<SQLStatement> statement,
|
887
|
-
PendingQueryParameters parameters,
|
896
|
+
const PendingQueryParameters ¶meters,
|
897
|
+
bool verify) {
|
888
898
|
auto query = statement->query;
|
889
899
|
shared_ptr<PreparedStatementData> prepared;
|
890
900
|
if (verify) {
|
@@ -7,6 +7,20 @@
|
|
7
7
|
|
8
8
|
namespace duckdb {
|
9
9
|
|
10
|
+
static void ThrowIfExceptionIsInternal(StatementVerifier &verifier) {
|
11
|
+
if (!verifier.materialized_result) {
|
12
|
+
return;
|
13
|
+
}
|
14
|
+
auto &result = *verifier.materialized_result;
|
15
|
+
if (!result.HasError()) {
|
16
|
+
return;
|
17
|
+
}
|
18
|
+
auto &error = result.GetErrorObject();
|
19
|
+
if (error.Type() == ExceptionType::INTERNAL) {
|
20
|
+
error.Throw();
|
21
|
+
}
|
22
|
+
}
|
23
|
+
|
10
24
|
PreservedError ClientContext::VerifyQuery(ClientContextLock &lock, const string &query,
|
11
25
|
unique_ptr<SQLStatement> statement) {
|
12
26
|
D_ASSERT(statement->type == StatementType::SELECT_STATEMENT);
|
@@ -81,6 +95,9 @@ PreservedError ClientContext::VerifyQuery(ClientContextLock &lock, const string
|
|
81
95
|
if (!failed) {
|
82
96
|
// PreparedStatementVerifier fails if it runs into a ParameterNotAllowedException, which is OK
|
83
97
|
statement_verifiers.push_back(std::move(prepared_statement_verifier));
|
98
|
+
} else {
|
99
|
+
// If it does fail, let's make sure it's not an internal exception
|
100
|
+
ThrowIfExceptionIsInternal(*prepared_statement_verifier);
|
84
101
|
}
|
85
102
|
} else {
|
86
103
|
if (ValidChecker::IsInvalidated(*db)) {
|
@@ -6,9 +6,9 @@
|
|
6
6
|
namespace duckdb {
|
7
7
|
|
8
8
|
PreparedStatement::PreparedStatement(shared_ptr<ClientContext> context, shared_ptr<PreparedStatementData> data_p,
|
9
|
-
string query, idx_t n_param, case_insensitive_map_t<idx_t>
|
9
|
+
string query, idx_t n_param, case_insensitive_map_t<idx_t> named_param_map_p)
|
10
10
|
: context(std::move(context)), data(std::move(data_p)), query(std::move(query)), success(true), n_param(n_param),
|
11
|
-
named_param_map(std::move(
|
11
|
+
named_param_map(std::move(named_param_map_p)) {
|
12
12
|
D_ASSERT(data || !success);
|
13
13
|
}
|
14
14
|
|
@@ -56,19 +56,27 @@ const vector<string> &PreparedStatement::GetNames() {
|
|
56
56
|
return data->names;
|
57
57
|
}
|
58
58
|
|
59
|
-
|
59
|
+
case_insensitive_map_t<LogicalType> PreparedStatement::GetExpectedParameterTypes() const {
|
60
60
|
D_ASSERT(data);
|
61
|
-
|
61
|
+
case_insensitive_map_t<LogicalType> expected_types(data->value_map.size());
|
62
62
|
for (auto &it : data->value_map) {
|
63
|
-
|
64
|
-
|
65
|
-
D_ASSERT(param_index < expected_types.size());
|
63
|
+
auto &identifier = it.first;
|
64
|
+
D_ASSERT(data->value_map.count(identifier));
|
66
65
|
D_ASSERT(it.second);
|
67
|
-
expected_types[
|
66
|
+
expected_types[identifier] = it.second->GetValue().type();
|
68
67
|
}
|
69
68
|
return expected_types;
|
70
69
|
}
|
71
70
|
|
71
|
+
unique_ptr<QueryResult> PreparedStatement::Execute(case_insensitive_map_t<Value> &named_values,
|
72
|
+
bool allow_stream_result) {
|
73
|
+
auto pending = PendingQuery(named_values, allow_stream_result);
|
74
|
+
if (pending->HasError()) {
|
75
|
+
return make_uniq<MaterializedQueryResult>(pending->GetErrorObject());
|
76
|
+
}
|
77
|
+
return pending->Execute();
|
78
|
+
}
|
79
|
+
|
72
80
|
unique_ptr<QueryResult> PreparedStatement::Execute(vector<Value> &values, bool allow_stream_result) {
|
73
81
|
auto pending = PendingQuery(values, allow_stream_result);
|
74
82
|
if (pending->HasError()) {
|
@@ -78,14 +86,33 @@ unique_ptr<QueryResult> PreparedStatement::Execute(vector<Value> &values, bool a
|
|
78
86
|
}
|
79
87
|
|
80
88
|
unique_ptr<PendingQueryResult> PreparedStatement::PendingQuery(vector<Value> &values, bool allow_stream_result) {
|
89
|
+
case_insensitive_map_t<Value> named_values;
|
90
|
+
for (idx_t i = 0; i < values.size(); i++) {
|
91
|
+
auto &val = values[i];
|
92
|
+
named_values[std::to_string(i + 1)] = val;
|
93
|
+
}
|
94
|
+
return PendingQuery(named_values, allow_stream_result);
|
95
|
+
}
|
96
|
+
|
97
|
+
unique_ptr<PendingQueryResult> PreparedStatement::PendingQuery(case_insensitive_map_t<Value> &named_values,
|
98
|
+
bool allow_stream_result) {
|
81
99
|
if (!success) {
|
82
|
-
|
100
|
+
auto exception = InvalidInputException("Attempting to execute an unsuccessfully prepared statement!");
|
101
|
+
return make_uniq<PendingQueryResult>(PreservedError(exception));
|
83
102
|
}
|
84
|
-
D_ASSERT(data);
|
85
103
|
PendingQueryParameters parameters;
|
86
|
-
parameters.parameters = &
|
104
|
+
parameters.parameters = &named_values;
|
105
|
+
|
106
|
+
try {
|
107
|
+
VerifyParameters(named_values, named_param_map);
|
108
|
+
} catch (const Exception &ex) {
|
109
|
+
return make_uniq<PendingQueryResult>(PreservedError(ex));
|
110
|
+
}
|
111
|
+
|
112
|
+
D_ASSERT(data);
|
87
113
|
parameters.allow_stream_result = allow_stream_result && data->properties.allow_stream_result;
|
88
114
|
auto result = context->PendingQuery(query, data, parameters);
|
115
|
+
// The result should not contain any reference to the 'vector<Value> parameters.parameters'
|
89
116
|
return result;
|
90
117
|
}
|
91
118
|
|
@@ -18,8 +18,9 @@ void PreparedStatementData::CheckParameterCount(idx_t parameter_count) {
|
|
18
18
|
}
|
19
19
|
}
|
20
20
|
|
21
|
-
bool PreparedStatementData::RequireRebind(ClientContext &context,
|
22
|
-
|
21
|
+
bool PreparedStatementData::RequireRebind(ClientContext &context, optional_ptr<case_insensitive_map_t<Value>> values) {
|
22
|
+
idx_t count = values ? values->size() : 0;
|
23
|
+
CheckParameterCount(count);
|
23
24
|
if (!unbound_statement) {
|
24
25
|
// no unbound statement!? cannot rebind?
|
25
26
|
return false;
|
@@ -33,52 +34,56 @@ bool PreparedStatementData::RequireRebind(ClientContext &context, const vector<V
|
|
33
34
|
return true;
|
34
35
|
}
|
35
36
|
for (auto &it : value_map) {
|
36
|
-
|
37
|
-
|
37
|
+
auto &identifier = it.first;
|
38
|
+
auto lookup = values->find(identifier);
|
39
|
+
D_ASSERT(lookup != values->end());
|
40
|
+
if (lookup->second.type() != it.second->return_type) {
|
38
41
|
return true;
|
39
42
|
}
|
40
43
|
}
|
41
44
|
return false;
|
42
45
|
}
|
43
46
|
|
44
|
-
void PreparedStatementData::Bind(
|
47
|
+
void PreparedStatementData::Bind(case_insensitive_map_t<Value> values) {
|
45
48
|
// set parameters
|
46
49
|
D_ASSERT(!unbound_statement || unbound_statement->n_param == properties.parameter_count);
|
47
50
|
CheckParameterCount(values.size());
|
48
51
|
|
49
52
|
// bind the required values
|
50
53
|
for (auto &it : value_map) {
|
51
|
-
const
|
52
|
-
|
53
|
-
|
54
|
+
const string &identifier = it.first;
|
55
|
+
auto lookup = values.find(identifier);
|
56
|
+
if (lookup == values.end()) {
|
57
|
+
throw BinderException("Could not find parameter with identifier %s", identifier);
|
54
58
|
}
|
55
59
|
D_ASSERT(it.second);
|
56
|
-
|
60
|
+
auto &value = lookup->second;
|
61
|
+
if (!value.DefaultTryCastAs(it.second->return_type)) {
|
57
62
|
throw BinderException(
|
58
|
-
"Type mismatch for binding parameter with
|
59
|
-
it.second->return_type.ToString().c_str(),
|
63
|
+
"Type mismatch for binding parameter with identifier %s, expected type %s but got type %s", identifier,
|
64
|
+
it.second->return_type.ToString().c_str(), value.type().ToString().c_str());
|
60
65
|
}
|
61
|
-
it.second->value
|
66
|
+
it.second->SetValue(value);
|
62
67
|
}
|
63
68
|
}
|
64
69
|
|
65
|
-
bool PreparedStatementData::TryGetType(
|
66
|
-
auto it = value_map.find(
|
70
|
+
bool PreparedStatementData::TryGetType(const string &identifier, LogicalType &result) {
|
71
|
+
auto it = value_map.find(identifier);
|
67
72
|
if (it == value_map.end()) {
|
68
73
|
return false;
|
69
74
|
}
|
70
75
|
if (it->second->return_type.id() != LogicalTypeId::INVALID) {
|
71
76
|
result = it->second->return_type;
|
72
77
|
} else {
|
73
|
-
result = it->second->
|
78
|
+
result = it->second->GetValue().type();
|
74
79
|
}
|
75
80
|
return true;
|
76
81
|
}
|
77
82
|
|
78
|
-
LogicalType PreparedStatementData::GetType(
|
83
|
+
LogicalType PreparedStatementData::GetType(const string &identifier) {
|
79
84
|
LogicalType result;
|
80
|
-
if (!TryGetType(
|
81
|
-
throw BinderException("Could not find parameter with
|
85
|
+
if (!TryGetType(identifier, result)) {
|
86
|
+
throw BinderException("Could not find parameter identified with: %s", identifier);
|
82
87
|
}
|
83
88
|
return result;
|
84
89
|
}
|