11#define DUCKDB_EXTENSION_MAIN
22#include " http_client_extension.hpp"
33#include " duckdb.hpp"
4+ #include " duckdb/common/types.hpp"
5+ #include " duckdb/common/vector_operations/generic_executor.hpp"
46#include " duckdb/function/scalar_function.hpp"
57#include " duckdb/main/extension_util.hpp"
68#include " duckdb/common/atomic.hpp"
@@ -118,14 +120,18 @@ static void HTTPGetRequestFunction(DataChunk &args, ExpressionState &state, Vect
118120static void HTTPPostRequestFunction (DataChunk &args, ExpressionState &state, Vector &result) {
119121 D_ASSERT (args.data .size () == 3 );
120122
123+ using STRING_TYPE = PrimitiveType<string_t >;
124+ using LENTRY_TYPE = PrimitiveType<list_entry_t >;
125+
121126 auto &url_vector = args.data [0 ];
122127 auto &headers_vector = args.data [1 ];
128+ auto &headers_entry = ListVector::GetEntry (headers_vector);
123129 auto &body_vector = args.data [2 ];
124130
125- TernaryExecutor::Execute< string_t , string_t , string_t , string_t >(
131+ GenericExecutor::ExecuteTernary<STRING_TYPE, LENTRY_TYPE, STRING_TYPE, STRING_TYPE >(
126132 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 ();
129135
130136 // Use helper to setup client and parse URL
131137 auto client_and_path = SetupHttpClient (url_str);
@@ -134,24 +140,24 @@ static void HTTPPostRequestFunction(DataChunk &args, ExpressionState &state, Vec
134140
135141 // Prepare headers
136142 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 );
150156 }
151157 }
152158
153159 // 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" );
155161 if (res) {
156162 if (res->status == 200 ) {
157163 return StringVector::AddString (result, res->body );
@@ -175,7 +181,7 @@ static void LoadInternal(DatabaseInstance &instance) {
175181
176182 ScalarFunctionSet http_post (" http_post" );
177183 http_post.AddFunction (ScalarFunction (
178- {LogicalType::VARCHAR, LogicalType::VARCHAR, LogicalType::VARCHAR},
184+ {LogicalType::VARCHAR, LogicalType::MAP (LogicalType:: VARCHAR, LogicalType::VARCHAR), LogicalType::JSON () },
179185 LogicalType::VARCHAR, HTTPPostRequestFunction));
180186 ExtensionUtil::RegisterFunction (instance, http_post);
181187}
0 commit comments