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}