1
1
#define DUCKDB_EXTENSION_MAIN
2
2
#include " http_client_extension.hpp"
3
3
#include " duckdb.hpp"
4
+ #include " duckdb/common/types.hpp"
5
+ #include " duckdb/common/vector_operations/generic_executor.hpp"
4
6
#include " duckdb/function/scalar_function.hpp"
5
7
#include " duckdb/main/extension_util.hpp"
6
8
#include " duckdb/common/atomic.hpp"
@@ -118,14 +120,18 @@ static void HTTPGetRequestFunction(DataChunk &args, ExpressionState &state, Vect
118
120
static void HTTPPostRequestFunction (DataChunk &args, ExpressionState &state, Vector &result) {
119
121
D_ASSERT (args.data .size () == 3 );
120
122
123
+ using STRING_TYPE = PrimitiveType<string_t >;
124
+ using LENTRY_TYPE = PrimitiveType<list_entry_t >;
125
+
121
126
auto &url_vector = args.data [0 ];
122
127
auto &headers_vector = args.data [1 ];
128
+ auto &headers_entry = ListVector::GetEntry (headers_vector);
123
129
auto &body_vector = args.data [2 ];
124
130
125
- TernaryExecutor::Execute< string_t , string_t , string_t , string_t >(
131
+ GenericExecutor::ExecuteTernary<STRING_TYPE, LENTRY_TYPE, STRING_TYPE, STRING_TYPE >(
126
132
url_vector, headers_vector, body_vector, result, args.size (),
127
- [&](string_t url, string_t headers, string_t body) {
128
- std::string url_str = url.GetString ();
133
+ [&](STRING_TYPE url, LENTRY_TYPE headers, STRING_TYPE body) {
134
+ std::string url_str = url.val . GetString ();
129
135
130
136
// Use helper to setup client and parse URL
131
137
auto client_and_path = SetupHttpClient (url_str);
@@ -134,24 +140,24 @@ static void HTTPPostRequestFunction(DataChunk &args, ExpressionState &state, Vec
134
140
135
141
// Prepare headers
136
142
duckdb_httplib_openssl::Headers header_map;
137
- std::istringstream header_stream ( headers.GetString ()) ;
138
- std::string header;
139
- while ( std::getline (header_stream, header)) {
140
- size_t colon_pos = header. find ( ' : ' );
141
- if (colon_pos != std::string::npos) {
142
- std::string key = header. substr ( 0 , colon_pos );
143
- std::string value = header. substr (colon_pos + 1 );
144
- // Trim leading and trailing whitespace
145
- key. erase ( 0 , key. find_first_not_of ( " \t " ) );
146
- key. erase (key. find_last_not_of ( " \t " ) + 1 );
147
- value. erase ( 0 , value. find_first_not_of ( " \t " ) );
148
- value. erase (value. find_last_not_of ( " \t " ) + 1 );
149
- header_map.emplace (key, value );
143
+ auto header_list = headers.val ;
144
+ for ( idx_t i = header_list. offset ; i < header_list. offset + header_list. length ; i++) {
145
+ const auto &child_value = headers_entry. GetValue (i);
146
+
147
+ Vector tmp (child_value);
148
+ auto &children = StructVector::GetEntries (tmp );
149
+
150
+ if (children. size () == 2 ) {
151
+ auto name = FlatVector::GetData< string_t >(*children[ 0 ] );
152
+ auto data = FlatVector::GetData< string_t >(*children[ 1 ] );
153
+ std::string key = name-> GetString ( );
154
+ std::string val = data-> GetString ( );
155
+ header_map.emplace (key, val );
150
156
}
151
157
}
152
158
153
159
// Make the POST request with headers and body
154
- auto res = client.Post (path.c_str (), header_map, body.GetString (), " application/json" );
160
+ auto res = client.Post (path.c_str (), header_map, body.val . GetString (), " application/json" );
155
161
if (res) {
156
162
if (res->status == 200 ) {
157
163
return StringVector::AddString (result, res->body );
@@ -175,7 +181,7 @@ static void LoadInternal(DatabaseInstance &instance) {
175
181
176
182
ScalarFunctionSet http_post (" http_post" );
177
183
http_post.AddFunction (ScalarFunction (
178
- {LogicalType::VARCHAR, LogicalType::VARCHAR, LogicalType::VARCHAR},
184
+ {LogicalType::VARCHAR, LogicalType::MAP (LogicalType:: VARCHAR, LogicalType::VARCHAR), LogicalType::JSON () },
179
185
LogicalType::VARCHAR, HTTPPostRequestFunction));
180
186
ExtensionUtil::RegisterFunction (instance, http_post);
181
187
}
0 commit comments