From 25ea196aad3660dbf0a0a515dbe773401e4ff583 Mon Sep 17 00:00:00 2001 From: Andy Lok Date: Fri, 15 Jan 2021 16:41:59 +0800 Subject: [PATCH 1/7] Add key_exists method Signed-off-by: Andy Lok --- src/transaction/snapshot.rs | 5 +++++ src/transaction/transaction.rs | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/src/transaction/snapshot.rs b/src/transaction/snapshot.rs index 95b57cf..28711c4 100644 --- a/src/transaction/snapshot.rs +++ b/src/transaction/snapshot.rs @@ -23,6 +23,11 @@ impl Snapshot { self.transaction.get(key).await } + /// Check whether the key exists. + pub async fn key_exists(&self, key: impl Into) -> Result { + self.transaction.key_exists(key).await + } + /// Get the values associated with the given keys. pub async fn batch_get( &self, diff --git a/src/transaction/transaction.rs b/src/transaction/transaction.rs index b85777c..1cca46f 100644 --- a/src/transaction/transaction.rs +++ b/src/transaction/transaction.rs @@ -146,6 +146,24 @@ impl Transaction { } } + /// Check whether the key exists. + /// + /// # Examples + /// ```rust,no_run + /// # use tikv_client::{Value, Config, TransactionClient}; + /// # use futures::prelude::*; + /// # futures::executor::block_on(async { + /// # let client = TransactionClient::new(vec!["192.168.0.100", "192.168.0.101"]).await.unwrap(); + /// let mut txn = client.begin_pessimistic().await.unwrap(); + /// let exists = txn.key_exists("k1".to_owned()).await.unwrap(); + /// txn.commit().await.unwrap(); + /// # }); + /// ``` + pub async fn key_exists(&self, key: impl Into) -> Result { + let key = key.into(); + Ok(self.scan_keys(key.clone()..=key, 1).await?.next().is_some()) + } + /// Create a new 'batch get' request. /// /// Once resolved this request will result in the fetching of the values associated with the From c8c7c02dcd0d35a852d8e7de0741c92eb51471ce Mon Sep 17 00:00:00 2001 From: Andy Lok Date: Mon, 18 Jan 2021 18:18:54 +0800 Subject: [PATCH 2/7] Add example for key_exists Signed-off-by: Andy Lok --- examples/transaction.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/examples/transaction.rs b/examples/transaction.rs index 4c82354..8cec582 100644 --- a/examples/transaction.rs +++ b/examples/transaction.rs @@ -29,6 +29,21 @@ async fn get(client: &Client, key: Key) -> Option { res } +async fn key_exists(client: &Client, key: Key) -> bool { + let mut txn = client + .begin_optimistic() + .await + .expect("Could not begin a transaction"); + let res = txn + .key_exists(key) + .await + .expect("Could not check key exists"); + txn.commit() + .await + .expect("Committing read-only transaction should not fail"); + res +} + async fn scan(client: &Client, range: impl Into, limit: u32) { let mut txn = client .begin_optimistic() @@ -82,6 +97,16 @@ async fn main() { let value1 = get(&txn, key1.clone()).await; println!("{:?}", (key1, value1)); + // check key exists + let key1: Key = b"key1".to_vec().into(); + let key1_exists = key_exists(&txn, key1.clone()).await; + let key2: Key = b"key_not_exist".to_vec().into(); + let key2_exists = key_exists(&txn, key2.clone()).await; + println!( + "check exists {:?}", + vec![(key1, key1_exists), (key2, key2_exists)] + ); + // scan let key1: Key = b"key1".to_vec().into(); scan(&txn, key1.., 10).await; From ef14345b2bcfec976a7b5f5f654c2d7b5ba2377a Mon Sep 17 00:00:00 2001 From: Andy Lok Date: Mon, 18 Jan 2021 18:24:05 +0800 Subject: [PATCH 3/7] Update README.md Signed-off-by: Andy Lok --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 7ba8950..3ccefd5 100644 --- a/README.md +++ b/README.md @@ -74,8 +74,10 @@ There are some [examples](examples) which show how to use the client in a Rust p | ----------- | ------------------- | ---------------------- | ------------------------------------------------------------------ | | `put` | `KvPair` | `()` | | | `get` | `Key` | `Option` | | +| `key_exits` | `Key` | `bool` | | | `delete` | `Key` | `()` | | | `scan` | `BoundRange` | `Iter` | | +| `scan_keys` | `BoundRange` | `Iter` | | | `batch_get` | `Iter` | `Iter` | Skip non-existent keys; Does not retain order | | `lock_keys` | `Iter` | `()` | | | `gc` | `Timestamp` | `bool` | It returns whether the latest safepoint in PD equals the parameter | From e165566e431e142ccc717a31faecd9d37cd459d6 Mon Sep 17 00:00:00 2001 From: Andy Lok Date: Mon, 18 Jan 2021 21:31:28 +0800 Subject: [PATCH 4/7] fix typo Signed-off-by: Andy Lok --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3ccefd5..5da9113 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ There are some [examples](examples) which show how to use the client in a Rust p | ----------- | ------------------- | ---------------------- | ------------------------------------------------------------------ | | `put` | `KvPair` | `()` | | | `get` | `Key` | `Option` | | -| `key_exits` | `Key` | `bool` | | +| `key_exists` | `Key` | `bool` | | | `delete` | `Key` | `()` | | | `scan` | `BoundRange` | `Iter` | | | `scan_keys` | `BoundRange` | `Iter` | | From 42ad8a5065d33c9ac43be2c12318433ae6308a77 Mon Sep 17 00:00:00 2001 From: Stepan Henek Date: Wed, 20 Jan 2021 12:38:42 +0100 Subject: [PATCH 5/7] Fix warnings when generating docs And use travis to check whether there are warnings in docs and treat them as errors. Signed-off-by: Stepan Henek --- .travis.yml | 2 ++ src/transaction/client.rs | 2 +- src/transaction/transaction.rs | 2 +- tikv-client-common/src/errors.rs | 2 +- tikv-client-proto/proto/backup.proto | 6 +++--- tikv-client-proto/proto/kvrpcpb.proto | 4 ++-- 6 files changed, 10 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index b199b88..578f0c0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,6 +13,7 @@ env: global: - RUST_BACKTRACE=1 - RUSTFLAGS="-D warnings" + - RUSTDOCFLAGS="-D warnings" addons: apt: @@ -42,6 +43,7 @@ script: - if [[ $TRAVIS_OS_NAME == "linux" && $TRAVIS_RUST_VERSION == "stable" ]]; then cargo clippy -- -D clippy::all; fi - cargo build --all - cargo build --examples + - if [[ $TRAVIS_OS_NAME == "linux" && $TRAVIS_RUST_VERSION == "nightly" ]]; then cargo doc --document-private-items; fi - if [[ $TRAVIS_RUST_VERSION == "nightly" ]]; then cargo test --all -- --nocapture; fi # For now we only run full integration tests on Linux. Here's why: # * Docker on OS X is not supported by Travis. diff --git a/src/transaction/client.rs b/src/transaction/client.rs index 7dcb9a1..b3930d4 100644 --- a/src/transaction/client.rs +++ b/src/transaction/client.rs @@ -18,7 +18,7 @@ const SCAN_LOCK_BATCH_SIZE: u32 = 1024; // TODO: cargo-culted value /// The TiKV transactional `Client` is used to interact with TiKV using transactional (MVCC) requests. /// /// A [`Transaction`](crate::transaction::Transaction) provides a SQL-like interface. -/// It begins with a [`begin`](Client::begin) or [`begin_pessimistic`](Client::begin_pessimistic) request +/// It begins with a [`begin_optimistic`](Client::begin_optimistic) or [`begin_pessimistic`](Client::begin_pessimistic) request /// and ends with a `rollback` or `commit` request. /// If a `Transaction` is dropped before it's rolled back or committed, it is automatically rolled back. /// diff --git a/src/transaction/transaction.rs b/src/transaction/transaction.rs index 1cca46f..0849fb0 100644 --- a/src/transaction/transaction.rs +++ b/src/transaction/transaction.rs @@ -907,7 +907,7 @@ impl Committer { #[derive(PartialEq)] enum TransactionStatus { - /// The transaction is read-only [`Snapshot`](super::Snapshot::Snapshot), no need to commit or rollback or panic on drop. + /// The transaction is read-only [`Snapshot`](super::Snapshot), no need to commit or rollback or panic on drop. ReadOnly, /// The transaction have not been committed or rolled back. Active, diff --git a/tikv-client-common/src/errors.rs b/tikv-client-common/src/errors.rs index 4feec94..c5460d9 100644 --- a/tikv-client-common/src/errors.rs +++ b/tikv-client-common/src/errors.rs @@ -80,7 +80,7 @@ impl From for Error { } } -/// A result holding an [`Error`](Error). +/// A result holding an [`Error`](enum@Error). pub type Result = result::Result; #[macro_export] diff --git a/tikv-client-proto/proto/backup.proto b/tikv-client-proto/proto/backup.proto index b739ec4..77f0110 100644 --- a/tikv-client-proto/proto/backup.proto +++ b/tikv-client-proto/proto/backup.proto @@ -74,7 +74,7 @@ message Schema { uint32 tiflash_replicas = 6; // stats represents the dump stats for a analyzed table, which generate by DumpStatsToJSON - // https://github.com/pingcap/tidb/blob/e136429d8dc5d70f43cd3f94179b0b9f47595097/statistics/handle/dump.go#L116 + // `` bytes stats = 7; } @@ -175,11 +175,11 @@ message GCS { string prefix = 3; string storage_class = 4; // If not empty, applies a predefined set of access controls. - // See https://cloud.google.com/storage/docs/access-control/lists#predefined-acl + // See `` // for valid values. string predefined_acl = 5; // Service Account Credentials JSON blob - // You can get one from https://console.cloud.google.com/apis/credentials, and + // You can get one from ``, and // copy the content, set it as string here. string credentials_blob = 6; } diff --git a/tikv-client-proto/proto/kvrpcpb.proto b/tikv-client-proto/proto/kvrpcpb.proto index 27e9790..60fe97c 100644 --- a/tikv-client-proto/proto/kvrpcpb.proto +++ b/tikv-client-proto/proto/kvrpcpb.proto @@ -872,7 +872,7 @@ message ScanDetailV2 { uint64 rocksdb_delete_skipped_count = 3; // Total number of internal keys skipped over during iteration. - // See https://github.com/facebook/rocksdb/blob/9f1c84ca471d8b1ad7be9f3eebfc2c7e07dfd7a7/include/rocksdb/perf_context.h#L84 for details. + // See `` for details. uint64 rocksdb_key_skipped_count = 4; // Total number of RocksDB block cache hits. @@ -892,7 +892,7 @@ message ExecDetails { // Available when ctx.record_scan_stat = true or meet slow query. ScanDetail scan_detail = 2; - // See https://github.com/pingcap/kvproto/pull/689 + // See `` reserved 3; reserved 4; } From c42305a045fbf6dc4884a3f2147850c0e03638b9 Mon Sep 17 00:00:00 2001 From: ekexium Date: Fri, 22 Jan 2021 17:47:56 +0800 Subject: [PATCH 6/7] give examples default pd addresses Signed-off-by: ekexium --- examples/common/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/common/mod.rs b/examples/common/mod.rs index 49f9a1d..6cdd126 100644 --- a/examples/common/mod.rs +++ b/examples/common/mod.rs @@ -24,7 +24,8 @@ pub fn parse_args(app_name: &str) -> CommandArgs { .takes_value(true) .multiple(true) .value_delimiter(",") - .required(true), + .required(false) + .default_value("localhost:2379"), ) // A cyclic dependency between CA, cert and key is made // to ensure that no security options are missing. From ad1a8fdf73acb9fb08387edcdd1eddc660add490 Mon Sep 17 00:00:00 2001 From: Stepan Henek Date: Fri, 22 Jan 2021 00:42:54 +0100 Subject: [PATCH 7/7] fixup! Fix warnings when generating docs Signed-off-by: Stepan Henek --- .travis.yml | 2 +- tikv-client-proto/proto/backup.proto | 6 +++--- tikv-client-proto/proto/kvrpcpb.proto | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 578f0c0..d028895 100644 --- a/.travis.yml +++ b/.travis.yml @@ -43,7 +43,7 @@ script: - if [[ $TRAVIS_OS_NAME == "linux" && $TRAVIS_RUST_VERSION == "stable" ]]; then cargo clippy -- -D clippy::all; fi - cargo build --all - cargo build --examples - - if [[ $TRAVIS_OS_NAME == "linux" && $TRAVIS_RUST_VERSION == "nightly" ]]; then cargo doc --document-private-items; fi + - if [[ $TRAVIS_OS_NAME == "linux" && $TRAVIS_RUST_VERSION == "nightly" ]]; then cargo doc --exclude tikv-client-proto --document-private-items; fi - if [[ $TRAVIS_RUST_VERSION == "nightly" ]]; then cargo test --all -- --nocapture; fi # For now we only run full integration tests on Linux. Here's why: # * Docker on OS X is not supported by Travis. diff --git a/tikv-client-proto/proto/backup.proto b/tikv-client-proto/proto/backup.proto index 77f0110..b739ec4 100644 --- a/tikv-client-proto/proto/backup.proto +++ b/tikv-client-proto/proto/backup.proto @@ -74,7 +74,7 @@ message Schema { uint32 tiflash_replicas = 6; // stats represents the dump stats for a analyzed table, which generate by DumpStatsToJSON - // `` + // https://github.com/pingcap/tidb/blob/e136429d8dc5d70f43cd3f94179b0b9f47595097/statistics/handle/dump.go#L116 bytes stats = 7; } @@ -175,11 +175,11 @@ message GCS { string prefix = 3; string storage_class = 4; // If not empty, applies a predefined set of access controls. - // See `` + // See https://cloud.google.com/storage/docs/access-control/lists#predefined-acl // for valid values. string predefined_acl = 5; // Service Account Credentials JSON blob - // You can get one from ``, and + // You can get one from https://console.cloud.google.com/apis/credentials, and // copy the content, set it as string here. string credentials_blob = 6; } diff --git a/tikv-client-proto/proto/kvrpcpb.proto b/tikv-client-proto/proto/kvrpcpb.proto index 60fe97c..27e9790 100644 --- a/tikv-client-proto/proto/kvrpcpb.proto +++ b/tikv-client-proto/proto/kvrpcpb.proto @@ -872,7 +872,7 @@ message ScanDetailV2 { uint64 rocksdb_delete_skipped_count = 3; // Total number of internal keys skipped over during iteration. - // See `` for details. + // See https://github.com/facebook/rocksdb/blob/9f1c84ca471d8b1ad7be9f3eebfc2c7e07dfd7a7/include/rocksdb/perf_context.h#L84 for details. uint64 rocksdb_key_skipped_count = 4; // Total number of RocksDB block cache hits. @@ -892,7 +892,7 @@ message ExecDetails { // Available when ctx.record_scan_stat = true or meet slow query. ScanDetail scan_detail = 2; - // See `` + // See https://github.com/pingcap/kvproto/pull/689 reserved 3; reserved 4; }