@@ -18,14 +18,92 @@ use uuid::Uuid;
1818use super :: { PageSize , StatementConfig } ;
1919use crate :: client:: execution_profile:: ExecutionProfileHandle ;
2020use crate :: errors:: { BadQuery , ExecutionError } ;
21- use crate :: frame:: response:: result:: PreparedMetadata ;
21+ use crate :: frame:: response:: result:: { self , PreparedMetadata } ;
2222use crate :: frame:: types:: { Consistency , SerialConsistency } ;
2323use crate :: observability:: history:: HistoryListener ;
2424use crate :: policies:: load_balancing:: LoadBalancingPolicy ;
2525use crate :: policies:: retry:: RetryPolicy ;
2626use crate :: response:: query_result:: ColumnSpecs ;
2727use crate :: routing:: Token ;
2828use crate :: routing:: partitioner:: { Partitioner , PartitionerHasher , PartitionerName } ;
29+ use crate :: statement:: Statement ;
30+
31+ /// Parts which are needed to construct [PreparedStatement].
32+ ///
33+ /// Kept separate for performance reasons, because constructing
34+ /// [PreparedStatement] involves allocations.
35+ ///
36+ /// # Lifecycle of prepared statement
37+ ///
38+ /// When PREPARE request is issued, RawPreparedStatement is returned,
39+ /// and later converted to PreparedStatement.
40+ /// PreparedStatement can be cloned. Clone is a new handle to the same
41+ /// underlying shared data - if the result metadata is updated, it is
42+ /// updated for all clones.
43+ /// PreparedStatement can be turned into UnconfiguredPreparedStatement.
44+ /// Similarly to clone, unconfigured statement is also a handle to the
45+ /// same shared data.
46+ /// UnconfiguredPreparedStatement can be used to create new PreparedStatement
47+ /// objects. Those are also handles to the same shared data.
48+ pub ( crate ) struct RawPreparedStatement < ' statement > {
49+ statement : & ' statement Statement ,
50+ prepared_response : result:: Prepared ,
51+ is_lwt : bool ,
52+ tracing_id : Option < Uuid > ,
53+ }
54+
55+ impl < ' statement > RawPreparedStatement < ' statement > {
56+ pub ( crate ) fn new (
57+ statement : & ' statement Statement ,
58+ prepared_response : result:: Prepared ,
59+ is_lwt : bool ,
60+ tracing_id : Option < Uuid > ,
61+ ) -> Self {
62+ Self {
63+ statement,
64+ prepared_response,
65+ is_lwt,
66+ tracing_id,
67+ }
68+ }
69+
70+ pub ( crate ) fn get_id ( & self ) -> & Bytes {
71+ & self . prepared_response . id
72+ }
73+
74+ pub ( crate ) fn tracing_id ( & self ) -> Option < Uuid > {
75+ self . tracing_id
76+ }
77+ }
78+
79+ /// Constructs the fully-fledged [PreparedStatement].
80+ ///
81+ /// This involves allocations.
82+ impl RawPreparedStatement < ' _ > {
83+ pub ( crate ) fn into_prepared_statement ( self ) -> PreparedStatement {
84+ let Self {
85+ statement,
86+ prepared_response,
87+ is_lwt,
88+ tracing_id,
89+ } = self ;
90+ let mut prepared_statement = PreparedStatement :: new (
91+ prepared_response. id ,
92+ is_lwt,
93+ prepared_response. prepared_metadata ,
94+ Arc :: new ( prepared_response. result_metadata ) ,
95+ statement. contents . clone ( ) ,
96+ statement. get_validated_page_size ( ) ,
97+ statement. config . clone ( ) ,
98+ ) ;
99+
100+ if let Some ( tracing_id) = tracing_id {
101+ prepared_statement. prepare_tracing_ids . push ( tracing_id) ;
102+ }
103+
104+ prepared_statement
105+ }
106+ }
29107
30108/// Represents a statement prepared on the server.
31109///
@@ -108,7 +186,7 @@ pub struct PreparedStatement {
108186struct PreparedStatementSharedData {
109187 id : Bytes ,
110188 metadata : PreparedMetadata ,
111- result_metadata : Arc < ResultMetadata < ' static > > ,
189+ initial_result_metadata : Arc < ResultMetadata < ' static > > ,
112190 statement : String ,
113191 is_confirmed_lwt : bool ,
114192}
@@ -126,7 +204,7 @@ impl Clone for PreparedStatement {
126204}
127205
128206impl PreparedStatement {
129- pub ( crate ) fn new (
207+ fn new (
130208 id : Bytes ,
131209 is_lwt : bool ,
132210 metadata : PreparedMetadata ,
@@ -139,7 +217,7 @@ impl PreparedStatement {
139217 shared : Arc :: new ( PreparedStatementSharedData {
140218 id,
141219 metadata,
142- result_metadata,
220+ initial_result_metadata : result_metadata,
143221 statement,
144222 is_confirmed_lwt : is_lwt,
145223 } ) ,
@@ -430,12 +508,12 @@ impl PreparedStatement {
430508
431509 /// Access metadata about the result of prepared statement returned by the database
432510 pub ( crate ) fn get_result_metadata ( & self ) -> & Arc < ResultMetadata < ' static > > {
433- & self . shared . result_metadata
511+ & self . shared . initial_result_metadata
434512 }
435513
436514 /// Access column specifications of the result set returned after the execution of this statement
437515 pub fn get_result_set_col_specs ( & self ) -> ColumnSpecs < ' _ , ' static > {
438- ColumnSpecs :: new ( self . shared . result_metadata . col_specs ( ) )
516+ ColumnSpecs :: new ( self . shared . initial_result_metadata . col_specs ( ) )
439517 }
440518
441519 /// Get the name of the partitioner used for this statement.
@@ -506,6 +584,41 @@ impl PreparedStatement {
506584 let ctx = RowSerializationContext :: from_prepared ( self . get_prepared_metadata ( ) ) ;
507585 SerializedValues :: from_serializable ( & ctx, values)
508586 }
587+
588+ pub ( crate ) fn make_unconfigured_handle ( & self ) -> UnconfiguredPreparedStatement {
589+ UnconfiguredPreparedStatement {
590+ shared : Arc :: clone ( & self . shared ) ,
591+ partitioner_name : self . get_partitioner_name ( ) . clone ( ) ,
592+ }
593+ }
594+ }
595+
596+ /// This is a [PreparedStatement] without parts that are available to be configured
597+ /// on an unprepared [Statement]. It is intended to be used in [CachingSession] cache,
598+ /// as a type safety measue: it first needs to be configured with config taken from
599+ /// statement provided by the user.
600+ /// It contains partitioner_name field. It is configurable on prepared statement,
601+ /// but not on unprepared statement, so we need to keep it.
602+ #[ derive( Debug ) ]
603+ pub ( crate ) struct UnconfiguredPreparedStatement {
604+ shared : Arc < PreparedStatementSharedData > ,
605+ partitioner_name : PartitionerName ,
606+ }
607+
608+ impl UnconfiguredPreparedStatement {
609+ pub ( crate ) fn make_configured_handle (
610+ & self ,
611+ config : StatementConfig ,
612+ page_size : PageSize ,
613+ ) -> PreparedStatement {
614+ PreparedStatement {
615+ shared : Arc :: clone ( & self . shared ) ,
616+ prepare_tracing_ids : Vec :: new ( ) ,
617+ page_size,
618+ partitioner_name : self . partitioner_name . clone ( ) ,
619+ config,
620+ }
621+ }
509622}
510623
511624/// Error when extracting partition key from bound values.
0 commit comments