duckdb 0.8.2-dev2399.0 → 0.8.2-dev2669.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.
Files changed (73) hide show
  1. package/binding.gyp +1 -0
  2. package/package.json +1 -1
  3. package/src/duckdb/extension/icu/icu-datepart.cpp +3 -3
  4. package/src/duckdb/src/catalog/catalog_entry/duck_table_entry.cpp +1 -1
  5. package/src/duckdb/src/catalog/default/default_functions.cpp +5 -0
  6. package/src/duckdb/src/common/enum_util.cpp +35 -1
  7. package/src/duckdb/src/common/http_state.cpp +78 -0
  8. package/src/duckdb/src/core_functions/function_list.cpp +2 -2
  9. package/src/duckdb/src/core_functions/scalar/list/array_slice.cpp +314 -82
  10. package/src/duckdb/src/execution/expression_executor/execute_parameter.cpp +2 -2
  11. package/src/duckdb/src/execution/index/art/art.cpp +43 -31
  12. package/src/duckdb/src/execution/index/art/leaf.cpp +47 -33
  13. package/src/duckdb/src/execution/index/art/node.cpp +31 -24
  14. package/src/duckdb/src/execution/index/art/prefix.cpp +100 -16
  15. package/src/duckdb/src/execution/operator/schema/physical_create_index.cpp +54 -31
  16. package/src/duckdb/src/execution/physical_plan/plan_create_index.cpp +32 -15
  17. package/src/duckdb/src/function/table/arrow/arrow_duck_schema.cpp +57 -0
  18. package/src/duckdb/src/function/table/arrow.cpp +95 -92
  19. package/src/duckdb/src/function/table/arrow_conversion.cpp +45 -68
  20. package/src/duckdb/src/function/table/version/pragma_version.cpp +2 -2
  21. package/src/duckdb/src/include/duckdb/common/case_insensitive_map.hpp +1 -0
  22. package/src/duckdb/src/include/duckdb/common/enum_util.hpp +8 -0
  23. package/src/duckdb/src/include/duckdb/common/helper.hpp +8 -3
  24. package/src/duckdb/src/include/duckdb/common/http_state.hpp +61 -28
  25. package/src/duckdb/src/include/duckdb/common/types/value.hpp +4 -1
  26. package/src/duckdb/src/include/duckdb/core_functions/scalar/list_functions.hpp +4 -4
  27. package/src/duckdb/src/include/duckdb/execution/index/art/art.hpp +7 -5
  28. package/src/duckdb/src/include/duckdb/execution/index/art/leaf.hpp +6 -6
  29. package/src/duckdb/src/include/duckdb/execution/index/art/node.hpp +6 -0
  30. package/src/duckdb/src/include/duckdb/execution/index/art/prefix.hpp +9 -11
  31. package/src/duckdb/src/include/duckdb/execution/operator/schema/physical_create_index.hpp +8 -1
  32. package/src/duckdb/src/include/duckdb/function/table/arrow/arrow_duck_schema.hpp +99 -0
  33. package/src/duckdb/src/include/duckdb/function/table/arrow.hpp +6 -36
  34. package/src/duckdb/src/include/duckdb/main/capi/capi_internal.hpp +3 -1
  35. package/src/duckdb/src/include/duckdb/main/client_context.hpp +15 -14
  36. package/src/duckdb/src/include/duckdb/main/prepared_statement.hpp +73 -5
  37. package/src/duckdb/src/include/duckdb/main/prepared_statement_data.hpp +6 -6
  38. package/src/duckdb/src/include/duckdb/parser/expression/operator_expression.hpp +20 -3
  39. package/src/duckdb/src/include/duckdb/parser/expression/parameter_expression.hpp +17 -1
  40. package/src/duckdb/src/include/duckdb/parser/statement/execute_statement.hpp +1 -1
  41. package/src/duckdb/src/include/duckdb/parser/transformer.hpp +5 -3
  42. package/src/duckdb/src/include/duckdb/planner/bound_parameter_map.hpp +2 -1
  43. package/src/duckdb/src/include/duckdb/planner/expression/bound_parameter_data.hpp +20 -5
  44. package/src/duckdb/src/include/duckdb/planner/expression/bound_parameter_expression.hpp +3 -3
  45. package/src/duckdb/src/include/duckdb/planner/planner.hpp +4 -3
  46. package/src/duckdb/src/include/duckdb/storage/object_cache.hpp +1 -1
  47. package/src/duckdb/src/include/duckdb/verification/prepared_statement_verifier.hpp +1 -1
  48. package/src/duckdb/src/include/duckdb.h +16 -0
  49. package/src/duckdb/src/main/capi/pending-c.cpp +6 -0
  50. package/src/duckdb/src/main/capi/prepared-c.cpp +52 -4
  51. package/src/duckdb/src/main/client_context.cpp +27 -17
  52. package/src/duckdb/src/main/client_verify.cpp +17 -0
  53. package/src/duckdb/src/main/extension/extension_helper.cpp +2 -1
  54. package/src/duckdb/src/main/prepared_statement.cpp +38 -11
  55. package/src/duckdb/src/main/prepared_statement_data.cpp +23 -18
  56. package/src/duckdb/src/parser/expression/parameter_expression.cpp +7 -7
  57. package/src/duckdb/src/parser/statement/execute_statement.cpp +2 -2
  58. package/src/duckdb/src/parser/transform/expression/transform_array_access.cpp +13 -4
  59. package/src/duckdb/src/parser/transform/expression/transform_param_ref.cpp +45 -26
  60. package/src/duckdb/src/parser/transform/statement/transform_prepare.cpp +28 -6
  61. package/src/duckdb/src/parser/transformer.cpp +27 -9
  62. package/src/duckdb/src/planner/binder/expression/bind_parameter_expression.cpp +10 -10
  63. package/src/duckdb/src/planner/binder/statement/bind_execute.cpp +13 -7
  64. package/src/duckdb/src/planner/expression/bound_parameter_expression.cpp +13 -13
  65. package/src/duckdb/src/planner/planner.cpp +7 -6
  66. package/src/duckdb/src/storage/checkpoint_manager.cpp +1 -1
  67. package/src/duckdb/src/storage/serialization/serialize_expression.cpp +3 -3
  68. package/src/duckdb/src/storage/serialization/serialize_parsed_expression.cpp +2 -2
  69. package/src/duckdb/src/verification/prepared_statement_verifier.cpp +16 -11
  70. package/src/duckdb/third_party/libpg_query/include/nodes/parsenodes.hpp +1 -0
  71. package/src/duckdb/third_party/libpg_query/src_backend_parser_gram.cpp +12855 -12282
  72. package/src/duckdb/ub_src_common.cpp +2 -0
  73. package/src/duckdb/ub_src_function_table_arrow.cpp +2 -0
@@ -63,7 +63,7 @@ public:
63
63
  //! Returns the result names of the prepared statement
64
64
  DUCKDB_API const vector<string> &GetNames();
65
65
  //! Returns the map of parameter index to the expected type of parameter
66
- DUCKDB_API vector<LogicalType> GetExpectedParameterTypes() const;
66
+ DUCKDB_API case_insensitive_map_t<LogicalType> GetExpectedParameterTypes() const;
67
67
 
68
68
  //! Create a pending query result of the prepared statement with the given set of arguments
69
69
  template <typename... Args>
@@ -72,6 +72,20 @@ public:
72
72
  return PendingQueryRecursive(values, args...);
73
73
  }
74
74
 
75
+ //! Create a pending query result of the prepared statement with the given set of arguments
76
+ DUCKDB_API unique_ptr<PendingQueryResult> PendingQuery(vector<Value> &values, bool allow_stream_result = true);
77
+
78
+ //! Create a pending query result of the prepared statement with the given set named arguments
79
+ DUCKDB_API unique_ptr<PendingQueryResult> PendingQuery(case_insensitive_map_t<Value> &named_values,
80
+ bool allow_stream_result = true);
81
+
82
+ //! Execute the prepared statement with the given set of values
83
+ DUCKDB_API unique_ptr<QueryResult> Execute(vector<Value> &values, bool allow_stream_result = true);
84
+
85
+ //! Execute the prepared statement with the given set of named+unnamed values
86
+ DUCKDB_API unique_ptr<QueryResult> Execute(case_insensitive_map_t<Value> &named_values,
87
+ bool allow_stream_result = true);
88
+
75
89
  //! Execute the prepared statement with the given set of arguments
76
90
  template <typename... Args>
77
91
  unique_ptr<QueryResult> Execute(Args... args) {
@@ -79,11 +93,65 @@ public:
79
93
  return ExecuteRecursive(values, args...);
80
94
  }
81
95
 
82
- //! Create a pending query result of the prepared statement with the given set of arguments
83
- DUCKDB_API unique_ptr<PendingQueryResult> PendingQuery(vector<Value> &values, bool allow_stream_result = true);
96
+ template <class PAYLOAD>
97
+ static string ExcessValuesException(const case_insensitive_map_t<idx_t> &parameters,
98
+ case_insensitive_map_t<PAYLOAD> &values) {
99
+ // Too many values
100
+ set<string> excess_set;
101
+ for (auto &pair : values) {
102
+ auto &name = pair.first;
103
+ if (!parameters.count(name)) {
104
+ excess_set.insert(name);
105
+ }
106
+ }
107
+ vector<string> excess_values;
108
+ for (auto &val : excess_set) {
109
+ excess_values.push_back(val);
110
+ }
111
+ return StringUtil::Format("Parameter argument/count mismatch, identifiers of the excess parameters: %s",
112
+ StringUtil::Join(excess_values, ", "));
113
+ }
84
114
 
85
- //! Execute the prepared statement with the given set of values
86
- DUCKDB_API unique_ptr<QueryResult> Execute(vector<Value> &values, bool allow_stream_result = true);
115
+ template <class PAYLOAD>
116
+ static string MissingValuesException(const case_insensitive_map_t<idx_t> &parameters,
117
+ case_insensitive_map_t<PAYLOAD> &values) {
118
+ // Missing values
119
+ set<string> missing_set;
120
+ for (auto &pair : parameters) {
121
+ auto &name = pair.first;
122
+ if (!values.count(name)) {
123
+ missing_set.insert(name);
124
+ }
125
+ }
126
+ vector<string> missing_values;
127
+ for (auto &val : missing_set) {
128
+ missing_values.push_back(val);
129
+ }
130
+ return StringUtil::Format("Values were not provided for the following prepared statement parameters: %s",
131
+ StringUtil::Join(missing_values, ", "));
132
+ }
133
+
134
+ template <class PAYLOAD>
135
+ static void VerifyParameters(case_insensitive_map_t<PAYLOAD> &provided,
136
+ const case_insensitive_map_t<idx_t> &expected) {
137
+ if (expected.size() == provided.size()) {
138
+ // Same amount of identifiers, if
139
+ for (auto &pair : expected) {
140
+ auto &identifier = pair.first;
141
+ if (!provided.count(identifier)) {
142
+ throw InvalidInputException(MissingValuesException(expected, provided));
143
+ }
144
+ }
145
+ return;
146
+ }
147
+ // Mismatch in expected and provided parameters/values
148
+ if (expected.size() > provided.size()) {
149
+ throw InvalidInputException(MissingValuesException(expected, provided));
150
+ } else {
151
+ D_ASSERT(provided.size() > expected.size());
152
+ throw InvalidInputException(ExcessValuesException(expected, provided));
153
+ }
154
+ }
87
155
 
88
156
  private:
89
157
  unique_ptr<PendingQueryResult> PendingQueryRecursive(vector<Value> &values) {
@@ -31,8 +31,6 @@ public:
31
31
  unique_ptr<SQLStatement> unbound_statement;
32
32
  //! The fully prepared physical plan of the prepared statement
33
33
  unique_ptr<PhysicalOperator> plan;
34
- //! The map of parameter index to the actual value entry
35
- bound_parameter_map_t value_map;
36
34
 
37
35
  //! The result names of the transaction
38
36
  vector<string> names;
@@ -45,17 +43,19 @@ public:
45
43
  //! The catalog version of when the prepared statement was bound
46
44
  //! If this version is lower than the current catalog version, we have to rebind the prepared statement
47
45
  idx_t catalog_version;
46
+ //! The map of parameter index to the actual value entry
47
+ bound_parameter_map_t value_map;
48
48
 
49
49
  public:
50
50
  void CheckParameterCount(idx_t parameter_count);
51
51
  //! Whether or not the prepared statement data requires the query to rebound for the given parameters
52
- bool RequireRebind(ClientContext &context, const vector<Value> &values);
52
+ bool RequireRebind(ClientContext &context, optional_ptr<case_insensitive_map_t<Value>> values);
53
53
  //! Bind a set of values to the prepared statement data
54
- DUCKDB_API void Bind(vector<Value> values);
54
+ DUCKDB_API void Bind(case_insensitive_map_t<Value> values);
55
55
  //! Get the expected SQL Type of the bound parameter
56
- DUCKDB_API LogicalType GetType(idx_t param_index);
56
+ DUCKDB_API LogicalType GetType(const string &identifier);
57
57
  //! Try to get the expected SQL Type of the bound parameter
58
- DUCKDB_API bool TryGetType(idx_t param_idx, LogicalType &result);
58
+ DUCKDB_API bool TryGetType(const string &identifier, LogicalType &result);
59
59
  };
60
60
 
61
61
  } // namespace duckdb
@@ -12,6 +12,7 @@
12
12
  #include "duckdb/common/vector.hpp"
13
13
  #include "duckdb/common/string_util.hpp"
14
14
  #include "duckdb/parser/qualified_name.hpp"
15
+ #include "duckdb/parser/expression/constant_expression.hpp"
15
16
 
16
17
  namespace duckdb {
17
18
  //! Represents a built-in operator expression
@@ -86,9 +87,25 @@ public:
86
87
  return "(" + entry.children[0]->ToString() + " IS NOT NULL)";
87
88
  case ExpressionType::ARRAY_EXTRACT:
88
89
  return entry.children[0]->ToString() + "[" + entry.children[1]->ToString() + "]";
89
- case ExpressionType::ARRAY_SLICE:
90
- return entry.children[0]->ToString() + "[" + entry.children[1]->ToString() + ":" +
91
- entry.children[2]->ToString() + "]";
90
+ case ExpressionType::ARRAY_SLICE: {
91
+ string begin = entry.children[1]->ToString();
92
+ if (begin == "[]") {
93
+ begin = "";
94
+ }
95
+ string end = entry.children[2]->ToString();
96
+ if (end == "[]") {
97
+ if (entry.children.size() == 4) {
98
+ end = "-";
99
+ } else {
100
+ end = "";
101
+ }
102
+ }
103
+ if (entry.children.size() == 4) {
104
+ return entry.children[0]->ToString() + "[" + begin + ":" + end + ":" + entry.children[3]->ToString() +
105
+ "]";
106
+ }
107
+ return entry.children[0]->ToString() + "[" + begin + ":" + end + "]";
108
+ }
92
109
  case ExpressionType::STRUCT_EXTRACT: {
93
110
  if (entry.children[1]->type != ExpressionType::VALUE_CONSTANT) {
94
111
  return string();
@@ -11,6 +11,22 @@
11
11
  #include "duckdb/parser/parsed_expression.hpp"
12
12
 
13
13
  namespace duckdb {
14
+
15
+ // Parameters come in three different types:
16
+ // auto-increment:
17
+ // token: '?'
18
+ // name: -
19
+ // number: 0
20
+ // positional:
21
+ // token: '$<number>'
22
+ // name: -
23
+ // number: <number>
24
+ // named:
25
+ // token: '$<name>'
26
+ // name: <name>
27
+ // number: 0
28
+ enum class PreparedParamType : uint8_t { AUTO_INCREMENT, POSITIONAL, NAMED, INVALID };
29
+
14
30
  class ParameterExpression : public ParsedExpression {
15
31
  public:
16
32
  static constexpr const ExpressionClass TYPE = ExpressionClass::PARAMETER;
@@ -18,7 +34,7 @@ public:
18
34
  public:
19
35
  ParameterExpression();
20
36
 
21
- idx_t parameter_nr;
37
+ string identifier;
22
38
 
23
39
  public:
24
40
  bool IsScalar() const override {
@@ -22,7 +22,7 @@ public:
22
22
  ExecuteStatement();
23
23
 
24
24
  string name;
25
- vector<unique_ptr<ParsedExpression>> values;
25
+ case_insensitive_map_t<unique_ptr<ParsedExpression>> named_values;
26
26
 
27
27
  protected:
28
28
  ExecuteStatement(const ExecuteStatement &other);
@@ -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 SetNamedParam(const string &name, int32_t index);
86
- bool GetNamedParam(const string &name, int32_t &index);
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 = unordered_map<idx_t, shared_ptr<BoundParameterData>>;
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(vector<BoundParameterData> &parameter_data) : parameter_data(parameter_data) {
61
+ explicit BoundParameterMap(case_insensitive_map_t<BoundParameterData> &parameter_data)
62
+ : parameter_data(parameter_data) {
49
63
  }
50
64
 
51
65
  bound_parameter_map_t parameters;
52
- vector<BoundParameterData> &parameter_data;
66
+ case_insensitive_map_t<BoundParameterData> &parameter_data;
53
67
 
54
- LogicalType GetReturnType(idx_t index) {
55
- if (index >= parameter_data.size()) {
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 parameter_data[index].return_type;
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(idx_t parameter_nr);
21
+ explicit BoundParameterExpression(const string &identifier);
22
22
 
23
- idx_t parameter_nr;
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, idx_t parameter_nr, LogicalType return_type,
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
- bound_parameter_map_t value_map;
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 *map = nullptr);
43
+ optional_ptr<bound_parameter_map_t> map = nullptr);
43
44
 
44
45
  private:
45
46
  void CreatePlan(SQLStatement &statement);
@@ -48,7 +48,7 @@ public:
48
48
  }
49
49
 
50
50
  template <class T, class... Args>
51
- shared_ptr<T> GetOrCreate(const string &key, Args &&... args) {
51
+ shared_ptr<T> GetOrCreate(const string &key, Args &&...args) {
52
52
  lock_guard<mutex> glock(lock);
53
53
 
54
54
  auto entry = cache.find(key);
@@ -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
- vector<unique_ptr<ParsedExpression>> values;
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 &param_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
- if (!wrapper->statement->data->TryGetType(param_idx, param_type)) {
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
- if (param_idx > wrapper->values.size()) {
117
- wrapper->values.resize(param_idx);
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
- wrapper->values[param_idx - 1] = val;
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
  }