Skip to content

Commit 1d78cbe

Browse files
authored
Merge pull request #986 from muzarski/docstrings_for_cached_metadata
prepared: docs for `PreparedStatement`
2 parents 099b9fd + 10556e3 commit 1d78cbe

File tree

3 files changed

+70
-1
lines changed

3 files changed

+70
-1
lines changed

docs/source/queries/prepared.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33
Prepared queries provide much better performance than simple queries,
44
but they need to be prepared before use.
55

6+
Benefits that prepared statements have to offer:
7+
- Type safety - thanks to metadata provided by the server, the driver can verify bound values' types before serialization. This way, we can be always sure that the Rust type provided by the user is compatible (and if not, the error is returned) with the destined native type. The same applies for deserialization.
8+
- Performance - when executing a simple query with non-empty values list, the driver
9+
prepares the statement before execution. The reason for this is to provide type safety for simple queries. However, this implies 2 round trips per simple query execution. On the other hand, the cost of prepared statement's execution is only 1 round trip.
10+
- Improved load-balancing - using the statement metadata, the driver can compute a set of destined replicas for current statement execution. These replicas will be preferred when choosing the node (and shard) to send the request to. For more insight on this, see [performance section](#performance).
11+
612
```rust
713
# extern crate scylla;
814
# use scylla::Session;

scylla/src/statement/prepared_statement.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,68 @@ use crate::transport::execution_profile::ExecutionProfileHandle;
2323
use crate::transport::partitioner::{Partitioner, PartitionerHasher, PartitionerName};
2424

2525
/// Represents a statement prepared on the server.
26+
///
27+
/// To prepare a statement, simply execute [`Session::prepare`](crate::transport::session::Session::prepare).
28+
///
29+
/// If you plan on reusing the statement, or bounding some values to it during execution, always
30+
/// prefer using prepared statements over [`Session::query`](crate::transport::session::Session::query).
31+
///
32+
/// Benefits that prepared statements have to offer:
33+
/// * Performance - a prepared statement holds information about metadata
34+
/// that allows to carry out a statement execution in a type safe manner.
35+
/// When [`Session::query`](crate::transport::session::Session::query) is called with
36+
/// non-empty bound values, the driver has to prepare the statement before execution (to provide type safety).
37+
/// This implies 2 round trips per [`Session::query`](crate::transport::session::Session::query).
38+
/// On the other hand, the cost of [`Session::execute`](crate::transport::session::Session::execute) is only 1 round trip.
39+
/// * Increased type-safety - bound values' types are validated with
40+
/// the [`PreparedMetadata`] received from the server during the serialization.
41+
/// * Improved load balancing - thanks to statement metadata, the driver is able
42+
/// to compute a set of destined replicas for the statement execution. These replicas
43+
/// will be preferred when choosing the node (and shard) to send the request to.
44+
/// * Result deserialization optimization - see [`PreparedStatement::set_use_cached_result_metadata`].
45+
///
46+
/// # Clone implementation
47+
/// Cloning a prepared statement is a cheap operation. It only
48+
/// requires copying a couple of small fields and some [Arc] pointers.
49+
/// Always prefer cloning over executing [`Session::prepare`](crate::transport::session::Session::prepare)
50+
/// multiple times to save some roundtrips.
51+
///
52+
/// # Statement repreparation
53+
/// When schema is updated, the server is supposed to invalidate its
54+
/// prepared statement caches. Then, if client tries to execute a given statement,
55+
/// the server will respond with an error. Users should not worry about it, since
56+
/// the driver handles it properly and tries to reprepare the statement.
57+
/// However, there are some cases when client-side prepared statement should be dropped
58+
/// and prepared once again via [`Session::prepare`](crate::transport::session::Session::prepare) -
59+
/// see the mention about altering schema below.
60+
///
61+
/// # Altering schema
62+
/// If for some reason you decided to alter the part of schema that corresponds to given prepared
63+
/// statement, then the corresponding statement (and its copies obtained via [`PreparedStatement::clone`]) should
64+
/// be dropped. The statement should be prepared again.
65+
///
66+
/// There are two reasons for this:
67+
///
68+
/// ### CQL v4 protocol limitations
69+
/// The driver only supports CQL version 4.
70+
///
71+
/// In multi-client scenario, only the first client which reprepares the statement
72+
/// will receive the updated metadata from the server.
73+
/// The rest of the clients will still hold on the outdated metadata.
74+
/// In version 4 of CQL protocol there is currently no way for the server to notify other
75+
/// clients about prepared statement's metadata update.
76+
///
77+
/// ### Client-side metadata immutability
78+
/// The decision was made to keep client-side metadata immutable.
79+
/// Mainly because of the CQLv4 limitations mentioned above. This means
80+
/// that metadata is not updated during statement repreparation.
81+
/// This raises two issues:
82+
/// * bound values serialization errors - since [`PreparedMetadata`] is not updated
83+
/// * result deserialization errors - when [`PreparedStatement::set_use_cached_result_metadata`] is enabled,
84+
/// since [`ResultMetadata`] is not updated
85+
///
86+
/// So, to mitigate those issues, drop the outdated [`PreparedStatement`] manually
87+
/// and prepare it again against the new schema.
2688
#[derive(Debug)]
2789
pub struct PreparedStatement {
2890
pub(crate) config: StatementConfig,

scylla/src/transport/session.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -845,7 +845,8 @@ impl Session {
845845
/// > must be sent as bound values
846846
/// > (see [performance section](https://rust-driver.docs.scylladb.com/stable/queries/prepared.html#performance))
847847
///
848-
/// See [the book](https://rust-driver.docs.scylladb.com/stable/queries/prepared.html) for more information
848+
/// See [the book](https://rust-driver.docs.scylladb.com/stable/queries/prepared.html) for more information.
849+
/// See the documentation of [`PreparedStatement`].
849850
///
850851
/// # Arguments
851852
/// * `query` - query to prepare, can be just a `&str` or the [Query] struct.

0 commit comments

Comments
 (0)