pancake_db_client/client/
mod.rs

1use pancake_db_idl::ddl::*;
2use pancake_db_idl::dml::*;
3use pancake_db_idl::service::pancake_db_client::PancakeDbClient;
4use tonic::codegen::StdError;
5use tonic::transport::Channel;
6
7use crate::errors::ClientResult;
8
9#[cfg(feature = "read")]
10mod read;
11
12/// The best way to communicate with a PancakeDB server from Rust.
13///
14/// Supports the entire PancakeDB API.
15/// Additionally, since PancakeDB reads return raw byte data in a compressed
16/// format, `Client` supports some higher-level functionality for reading
17/// whole segments into a meaningful representation.
18///
19/// ```
20/// use pancake_db_client::Client;
21/// # use pancake_db_client::errors::ClientError;
22///
23/// # async { // we don't actually run this in the test, only compile
24/// let client = Client::connect("http://localhost:3842").await?;
25/// # Ok::<(), ClientError>(())
26/// # };
27/// ```
28#[derive(Clone, Debug)]
29pub struct Client {
30  /// The generated Tonic GRPC client.
31  ///
32  /// All client calls ultimately go through this.
33  /// You can manually make low-level calls like `read_segment_columns` through
34  /// this GRPC client.
35  pub grpc: PancakeDbClient<Channel>,
36}
37
38impl Client {
39  /// Creates a new client connected to the given endpoint.
40  ///
41  /// See [`tonic::transport::Endpoint`] for what qualifies as an endpoint.
42  /// One option is a string of format `"http://$HOST:$PORT"`
43  pub async fn connect<D>(dst: D) -> ClientResult<Self> where
44    D: std::convert::TryInto<tonic::transport::Endpoint>,
45    D::Error: Into<StdError>,
46  {
47    let grpc = PancakeDbClient::connect(dst).await?;
48    Ok(Client { grpc })
49  }
50
51  /// Alters a table, e.g. by adding columns.
52  pub async fn alter_table(&mut self, req: AlterTableRequest) -> ClientResult<AlterTableResponse> {
53    let resp = self.grpc.alter_table(req).await?.into_inner();
54    Ok(resp)
55  }
56
57  /// Creates or asserts or declaratively updates a table.
58  pub async fn create_table(&mut self, req: CreateTableRequest) -> ClientResult<CreateTableResponse> {
59    let resp = self.grpc.create_table(req).await?.into_inner();
60    Ok(resp)
61  }
62
63  /// Drops a table, deleting all its data.
64  pub async fn drop_table(&mut self, req: DropTableRequest) -> ClientResult<DropTableResponse> {
65    let resp = self.grpc.drop_table(req).await?.into_inner();
66    Ok(resp)
67  }
68
69  /// Returns the table's schema.
70  pub async fn get_schema(&mut self, req: GetSchemaRequest) -> ClientResult<GetSchemaResponse> {
71    let resp = self.grpc.get_schema(req).await?.into_inner();
72    Ok(resp)
73  }
74
75  /// Deletes specific rows from the segment.
76  pub async fn delete_from_segment(&mut self, req: DeleteFromSegmentRequest) -> ClientResult<DeleteFromSegmentResponse> {
77    let resp = self.grpc.delete_from_segment(req).await?.into_inner();
78    Ok(resp)
79  }
80
81  /// Lists of all tables.
82  pub async fn list_tables(&mut self, req: ListTablesRequest) -> ClientResult<ListTablesResponse> {
83    let resp = self.grpc.list_tables(req).await?.into_inner();
84    Ok(resp)
85  }
86
87  /// Lists all segments in the table, optionally subject to a partition
88  /// filter.
89  pub async fn list_segments(&mut self, req: ListSegmentsRequest) -> ClientResult<ListSegmentsResponse> {
90    let resp = self.grpc.list_segments(req).await?.into_inner();
91    Ok(resp)
92  }
93
94  /// Reads the binary data for the rows deleted.
95  ///
96  /// Uncommonly used; you should typically use
97  /// [`Client::decode_segment`] instead.
98  pub async fn read_segment_deletions(&mut self, req: ReadSegmentDeletionsRequest) -> ClientResult<ReadSegmentDeletionsResponse> {
99    let resp = self.grpc.read_segment_deletions(req).await?.into_inner();
100    Ok(resp)
101  }
102
103  /// Writes rows to a partition of a table.
104  ///
105  /// The request can be easily constructed with macros:
106  /// ```
107  /// use std::time::SystemTime;
108  /// use pancake_db_idl::dml::WriteToPartitionRequest;
109  /// use pancake_db_client::{make_row, make_partition};
110  ///
111  /// let req = WriteToPartitionRequest {
112  ///   table_name: "my_table".to_string(),
113  ///   partition: make_partition! {
114  ///     "string_partition_col" => "my_partition_value".to_string(),
115  ///     "int_partition_col" => 77,
116  ///   },
117  ///   rows: vec![
118  ///     make_row! {
119  ///       "timestamp_col" => SystemTime::now(),
120  ///       "bool_col" => false,
121  ///     }
122  ///   ],
123  /// };
124  /// ```
125  pub async fn write_to_partition(&mut self, req: WriteToPartitionRequest) -> ClientResult<WriteToPartitionResponse> {
126    let resp = self.grpc.write_to_partition(req).await?.into_inner();
127    Ok(resp)
128  }
129}