@@ -6,8 +6,11 @@ use crate::query::batch_statement::ScyllaBatchStatement;
66use crate :: query:: scylla_prepared_statement:: PreparedStatement ;
77use crate :: query:: scylla_query:: Query ;
88use crate :: types:: uuid:: Uuid ;
9- use napi:: bindgen_prelude:: { Either3 , Either4 } ;
109use napi:: Either ;
10+ use napi:: bindgen_prelude:: { Either3 , Either4 } ;
11+ use serde_json:: json;
12+
13+ use scylla:: statement:: query:: Query as ScyllaQuery ;
1114
1215use super :: metrics;
1316use super :: topology:: ScyllaClusterData ;
@@ -45,6 +48,64 @@ impl ScyllaSession {
4548 cluster_data. into ( )
4649 }
4750
51+ #[ allow( clippy:: type_complexity) ]
52+ #[ napi]
53+ pub async fn execute_with_tracing (
54+ & self ,
55+ query : Either3 < String , & Query , & PreparedStatement > ,
56+ parameters : Option <
57+ Vec < Either4 < u32 , String , & Uuid , HashMap < String , Either3 < u32 , String , & Uuid > > > > ,
58+ > ,
59+ options : Option < QueryOptions > ,
60+ ) -> napi:: Result < serde_json:: Value > {
61+ let values = QueryParameter :: parser ( parameters. clone ( ) ) . ok_or_else ( || {
62+ napi:: Error :: new (
63+ napi:: Status :: InvalidArg ,
64+ format ! (
65+ "Something went wrong with your query parameters. {:?}" ,
66+ parameters
67+ ) ,
68+ )
69+ } ) ?;
70+
71+ let should_prepare = options. map_or ( false , |options| options. prepare . unwrap_or ( false ) ) ;
72+
73+ match query {
74+ Either3 :: A ( ref query_str) if should_prepare => {
75+ let mut prepared = self . session . prepare ( query_str. clone ( ) ) . await . map_err ( |e| {
76+ napi:: Error :: new (
77+ napi:: Status :: InvalidArg ,
78+ format ! (
79+ "Something went wrong preparing your statement. - [{}]\n {}" ,
80+ query_str, e
81+ ) ,
82+ )
83+ } ) ?;
84+ prepared. set_tracing ( true ) ;
85+ self . execute_prepared ( & prepared, values, query_str) . await
86+ }
87+ Either3 :: A ( query_str) => {
88+ let mut query = ScyllaQuery :: new ( query_str) ;
89+ query. set_tracing ( true ) ;
90+ self . execute_query ( Either :: B ( query) , values) . await
91+ }
92+ Either3 :: B ( query_ref) => {
93+ let mut query = query_ref. query . clone ( ) ;
94+ query. set_tracing ( true ) ;
95+
96+ self . execute_query ( Either :: B ( query) , values) . await
97+ }
98+ Either3 :: C ( prepared_ref) => {
99+ let mut prepared = prepared_ref. prepared . clone ( ) ;
100+ prepared. set_tracing ( true ) ;
101+
102+ self
103+ . execute_prepared ( & prepared, values, prepared_ref. prepared . get_statement ( ) )
104+ . await
105+ }
106+ }
107+ }
108+
48109 /// Sends a query to the database and receives a response.\
49110 /// Returns only a single page of results, to receive multiple pages use (TODO: Not implemented yet)
50111 ///
@@ -110,6 +171,18 @@ impl ScyllaSession {
110171 . await
111172 }
112173 }
174+ . map_err ( |e| {
175+ napi:: Error :: new (
176+ napi:: Status :: InvalidArg ,
177+ format ! ( "Something went wrong with your query. - \n {}" , e) , // TODO: handle different queries here
178+ )
179+ } ) ?
180+ . get ( "result" )
181+ . cloned ( )
182+ . ok_or ( napi:: Error :: new (
183+ napi:: Status :: InvalidArg ,
184+ r#"Something went wrong with your query."# . to_string ( ) , // TODO: handle different queries here
185+ ) )
113186 }
114187
115188 // Helper method to handle prepared statements
@@ -128,7 +201,36 @@ impl ScyllaSession {
128201 ) ,
129202 )
130203 } ) ?;
131- Ok ( QueryResult :: parser ( query_result) )
204+
205+ let tracing = if let Some ( tracing_id) = query_result. tracing_id {
206+ Some ( crate :: types:: tracing:: TracingInfo :: from (
207+ self
208+ . session
209+ . get_tracing_info ( & tracing_id)
210+ . await
211+ . map_err ( |e| {
212+ napi:: Error :: new (
213+ napi:: Status :: InvalidArg ,
214+ format ! (
215+ "Something went wrong with your tracing info. - [{}]\n {}" ,
216+ query, e
217+ ) ,
218+ )
219+ } ) ?,
220+ ) )
221+ } else {
222+ None
223+ } ;
224+
225+ let result = QueryResult :: parser ( query_result) ;
226+
227+ dbg ! ( result. clone( ) ) ;
228+ dbg ! ( tracing. clone( ) ) ;
229+
230+ Ok ( json ! ( {
231+ "result" : result,
232+ "tracing" : tracing
233+ } ) )
132234 }
133235
134236 // Helper method to handle direct queries
@@ -142,7 +244,7 @@ impl ScyllaSession {
142244 Either :: B ( query_ref) => self . session . query ( query_ref. clone ( ) , values) . await ,
143245 }
144246 . map_err ( |e| {
145- let query_str = match query {
247+ let query_str = match query. clone ( ) {
146248 Either :: A ( query_str) => query_str,
147249 Either :: B ( query_ref) => query_ref. contents . clone ( ) ,
148250 } ;
@@ -155,7 +257,34 @@ impl ScyllaSession {
155257 )
156258 } ) ?;
157259
158- Ok ( QueryResult :: parser ( query_result) )
260+ let tracing_info = if let Some ( tracing_id) = query_result. tracing_id {
261+ Some ( crate :: types:: tracing:: TracingInfo :: from (
262+ self
263+ . session
264+ . get_tracing_info ( & tracing_id)
265+ . await
266+ . map_err ( |e| {
267+ napi:: Error :: new (
268+ napi:: Status :: InvalidArg ,
269+ format ! (
270+ "Something went wrong with your tracing info. - [{}]\n {}" ,
271+ match query {
272+ Either :: A ( query_str) => query_str,
273+ Either :: B ( query_ref) => query_ref. contents. clone( ) ,
274+ } ,
275+ e
276+ ) ,
277+ )
278+ } ) ?,
279+ ) )
280+ } else {
281+ None
282+ } ;
283+
284+ Ok ( json ! ( {
285+ "result" : QueryResult :: parser( query_result) ,
286+ "tracing" : tracing_info
287+ } ) )
159288 }
160289
161290 #[ allow( clippy:: type_complexity) ]
0 commit comments