12
12
#define CPPHTTPLIB_OPENSSL_SUPPORT
13
13
#include " httplib.hpp"
14
14
15
+ // Include yyjson for JSON handling
16
+ #include " yyjson.hpp"
17
+
15
18
#include < thread>
16
19
#include < memory>
17
20
#include < cstdlib>
18
21
22
+ using namespace duckdb_yyjson ; // NOLINT
23
+
19
24
namespace duckdb {
20
25
21
26
struct HttpServerState {
@@ -30,6 +35,54 @@ struct HttpServerState {
30
35
31
36
static HttpServerState global_state;
32
37
38
+ // Convert the query result to JSON format
39
+ static std::string ConvertResultToJSON (MaterializedQueryResult &result) {
40
+ auto doc = yyjson_mut_doc_new (nullptr );
41
+ auto root = yyjson_mut_obj (doc);
42
+ yyjson_mut_doc_set_root (doc, root);
43
+
44
+ // Add meta information
45
+ auto meta_array = yyjson_mut_arr (doc);
46
+ for (idx_t col = 0 ; col < result.ColumnCount (); ++col) {
47
+ auto column_obj = yyjson_mut_obj (doc);
48
+ yyjson_mut_obj_add_str (doc, column_obj, " name" , result.ColumnName (col).c_str ());
49
+ yyjson_mut_arr_append (meta_array, column_obj);
50
+ }
51
+ yyjson_mut_obj_add_val (doc, root, " meta" , meta_array);
52
+
53
+ // Add data
54
+ auto data_array = yyjson_mut_arr (doc);
55
+ for (idx_t row = 0 ; row < result.RowCount (); ++row) {
56
+ auto row_array = yyjson_mut_arr (doc);
57
+ for (idx_t col = 0 ; col < result.ColumnCount (); ++col) {
58
+ Value value = result.GetValue (col, row);
59
+ if (value.IsNull ()) {
60
+ yyjson_mut_arr_append (row_array, yyjson_mut_null (doc));
61
+ } else {
62
+ std::string value_str = value.ToString ();
63
+ yyjson_mut_arr_append (row_array, yyjson_mut_strncpy (doc, value_str.c_str (), value_str.length ()));
64
+ }
65
+ }
66
+ yyjson_mut_arr_append (data_array, row_array);
67
+ }
68
+ yyjson_mut_obj_add_val (doc, root, " data" , data_array);
69
+
70
+ // Add row count
71
+ yyjson_mut_obj_add_int (doc, root, " rows" , result.RowCount ());
72
+
73
+ // Write to string
74
+ auto data = yyjson_mut_write (doc, 0 , nullptr );
75
+ if (!data) {
76
+ yyjson_mut_doc_free (doc);
77
+ throw InternalException (" Failed to render the result as JSON, yyjson failed" );
78
+ }
79
+
80
+ std::string json_output (data);
81
+ free (data);
82
+ yyjson_mut_doc_free (doc);
83
+ return json_output;
84
+ }
85
+
33
86
static void HandleQuery (const string& query, duckdb_httplib_openssl::Response& res) {
34
87
try {
35
88
if (!global_state.db_instance ) {
@@ -45,13 +98,16 @@ static void HandleQuery(const string& query, duckdb_httplib_openssl::Response& r
45
98
return ;
46
99
}
47
100
48
- res.set_content (result->ToString (), " text/plain" );
101
+ // Convert result to JSON
102
+ std::string json_output = ConvertResultToJSON (*result);
103
+ res.set_content (json_output, " application/json" );
49
104
} catch (const Exception& ex) {
50
105
res.status = 400 ;
51
106
res.set_content (ex.what (), " text/plain" );
52
107
}
53
108
}
54
109
110
+
55
111
void HttpServerStart (DatabaseInstance& db, string_t host, int32_t port) {
56
112
if (global_state.is_running ) {
57
113
throw IOException (" HTTP server is already running" );
@@ -150,7 +206,6 @@ static void LoadInternal(DatabaseInstance &instance) {
150
206
151
207
// Register the cleanup function to be called at exit
152
208
std::atexit (HttpServerCleanup);
153
-
154
209
}
155
210
156
211
void HttpserverExtension::Load (DuckDB &db) {
0 commit comments