11//! Defines the [`PreparedStatement`] type, which represents a statement
22//! that has been prepared in advance on the server.
33
4+ use arc_swap:: { ArcSwap , Guard } ;
45use bytes:: { Bytes , BytesMut } ;
56use scylla_cql:: frame:: response:: result:: {
67 ColumnSpec , PartitionKeyIndex , ResultMetadata , TableSpec ,
@@ -187,6 +188,7 @@ struct PreparedStatementSharedData {
187188 id : Bytes ,
188189 metadata : PreparedMetadata ,
189190 initial_result_metadata : Arc < ResultMetadata < ' static > > ,
191+ current_result_metadata : ArcSwap < ResultMetadata < ' static > > ,
190192 statement : String ,
191193 is_confirmed_lwt : bool ,
192194}
@@ -203,6 +205,18 @@ impl Clone for PreparedStatement {
203205 }
204206}
205207
208+ /// Stores a snapshot of current result metadata column specs.
209+ pub struct ColumnSpecsGuard {
210+ result : Guard < Arc < ResultMetadata < ' static > > > ,
211+ }
212+
213+ impl ColumnSpecsGuard {
214+ /// Retrieves current result metadata column specs.
215+ pub fn get ( & self ) -> ColumnSpecs < ' _ , ' static > {
216+ ColumnSpecs :: new ( self . result . col_specs ( ) )
217+ }
218+ }
219+
206220impl PreparedStatement {
207221 fn new (
208222 id : Bytes ,
@@ -217,7 +231,8 @@ impl PreparedStatement {
217231 shared : Arc :: new ( PreparedStatementSharedData {
218232 id,
219233 metadata,
220- initial_result_metadata : result_metadata,
234+ initial_result_metadata : Arc :: clone ( & result_metadata) ,
235+ current_result_metadata : ArcSwap :: from ( result_metadata) ,
221236 statement,
222237 is_confirmed_lwt : is_lwt,
223238 } ) ,
@@ -507,15 +522,42 @@ impl PreparedStatement {
507522 }
508523
509524 /// Access metadata about the result of prepared statement returned by the database
510- pub ( crate ) fn get_result_metadata ( & self ) -> & Arc < ResultMetadata < ' static > > {
511- & self . shared . initial_result_metadata
525+ pub ( crate ) fn get_current_result_metadata ( & self ) -> Arc < ResultMetadata < ' static > > {
526+ self . shared . current_result_metadata . load_full ( )
512527 }
513528
514- /// Access column specifications of the result set returned after the execution of this statement
529+ /// Update metadata about the result of prepared statement.
530+ // Will be used when we implement support for metadata id extension.
531+ #[ allow( dead_code) ]
532+ pub ( crate ) fn update_current_result_metadata (
533+ & self ,
534+ new_metadata : Arc < ResultMetadata < ' static > > ,
535+ ) {
536+ self . shared . current_result_metadata . store ( new_metadata) ;
537+ }
538+
539+ /// Access column specifications of the result set returned after the preparation of this statement
540+ ///
541+ /// In 1.4.0, result metadata became mutable to allow us to update it when server
542+ /// sends a new one (which happens in CQLv5, or CQLv4 with Scylla's metadata id extension). This method can't
543+ /// be changed to support it because of Copy bound on ColumnSpecs. This method now uses metadata initially sent
544+ /// by the server, which may be different than the one currently used. Please use get_current_result_set_col_specs instead."
545+ // TODO(2.0): Remove this
546+ #[ deprecated(
547+ since = "1.4.0" ,
548+ note = "This method may return outdated metadata. Use get_current_result_set_col_specs() instead."
549+ ) ]
515550 pub fn get_result_set_col_specs ( & self ) -> ColumnSpecs < ' _ , ' static > {
516551 ColumnSpecs :: new ( self . shared . initial_result_metadata . col_specs ( ) )
517552 }
518553
554+ /// Access column specifications of the result set returned after the execution of this statement
555+ pub fn get_current_result_set_col_specs ( & self ) -> ColumnSpecsGuard {
556+ ColumnSpecsGuard {
557+ result : self . shared . current_result_metadata . load ( ) ,
558+ }
559+ }
560+
519561 /// Get the name of the partitioner used for this statement.
520562 pub fn get_partitioner_name ( & self ) -> & PartitionerName {
521563 & self . partitioner_name
0 commit comments