Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

new command line of create database , add collection and list collection #297

Merged
merged 10 commits into from
Feb 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,4 @@ jobs:
cargo build --release
cd tools
sh start_localnet.sh release >tm.log 2>&1 &
- name: Benchmark rust sdk
run: |
cargo bench --package db3-sdk

3 changes: 0 additions & 3 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
[submodule "thirdparty/pg_wire"]
path = thirdparty/pg_wire
url = https://github.com/rtstore/pg_wire.git
[submodule "thirdparty/msql-srv"]
path = thirdparty/msql-srv
url = https://github.com/imotai/msql-srv.git
Expand Down
41 changes: 40 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,46 @@ cd db3 && bash install_env.sh && cargo build
cd tools && sh start_localnet.sh
```

### Start building
### Use Console

Start db3 console

```shell
./target/debug/db3 console
db3>-$ new-db
database address | transaction id
--------------------------------------------+----------------------------------------------
0xa9f5c8170aad7a0f924d89c6edacae6db24ef57d | 0ALy/hH7CQe9lv294K6dOxGP14xWHsbRs+/pXBZa8oU=
```

Show database

```shell
db3>-$ show-db --addr 0x7e16cb6524e2fc21ae9bf2d7ee18b05767b9dc33
database address | sender address | releated transactions | collections
--------------------------------------------+--------------------------------------------+----------------------------------------------+-------------
0x7e16cb6524e2fc21ae9bf2d7ee18b05767b9dc33 | 0x96bdb8e20fbd831fcb37dde9f81930a82ab5436b | EMYw64xlI2q4v1MShoKw3T60asNbWJ9//ca75M3JO3Q= |
```

Add a collection to database

```shell
db3>$ new-collection --addr 0xcfb524677673af15edebbec018b16d42d87b1251 --name books --index '{"name":"idx1","fields":[{"field_path":"test1","value_mode":{"Order":1}}]}'
send add collection done with tx
3V7r7VRg+9zUXeGNmqRR0YdVXWtBSl4sk+Z50h9BrOc=

```

Show collections in database

```shell
db3>-$ show-collection --addr 0xcfb524677673af15edebbec018b16d42d87b1251
name | index
-------+----------------------------------------------------------------------------
books | {"name":"idx1","fields":[{"field_path":"test1","value_mode":{"Order":1}}]}
```

### Use DB3.js

```typescript
/*
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
11 changes: 10 additions & 1 deletion src/cmd/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,16 @@ rand = "0.7"
rand_core = "0.6"
dirs = "4.0.0"
bip32 = "0.4.0"

rustyline = "9.1.2"
rustyline-derive = "0.7.0"
colored = "2.0.0"
unescape = "0.1.0"
shell-words = "1.1.0"
clap = { version = "4.0.20", features = ["derive"] }
async-trait = "0.1.64"
anyhow = "1.0.68"
serde = { version = "1.0.144", features = ["derive"] }
serde_json = "1.0.88"
[dev-dependencies]
db3-session={ path = "../session"}
db3-crypto={ path = "../crypto"}
Expand Down
260 changes: 260 additions & 0 deletions src/cmd/src/command.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,260 @@
//
// command.rs
// Copyright (C) 2023 db3.network Author imotai <codego.me@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

use clap::*;

use crate::keystore::KeyStore;
use db3_crypto::id::{AccountId, DbId, TxId};
use db3_proto::db3_base_proto::{BroadcastMeta, ChainId, ChainRole};
use db3_proto::db3_database_proto::{Database, Index};
use db3_proto::db3_mutation_proto::{CollectionMutation, DatabaseAction, DatabaseMutation};
use db3_sdk::{mutation_sdk::MutationSDK, store_sdk::StoreSDK};
use prettytable::{format, Table};
use std::time::{SystemTime, UNIX_EPOCH};

pub struct DB3ClientContext {
pub mutation_sdk: Option<MutationSDK>,
pub store_sdk: Option<StoreSDK>,
}

#[derive(Debug, Parser)]
#[clap(rename_all = "kebab-case")]
pub enum DB3ClientCommand {
/// Init the client config file
#[clap(name = "init")]
Init {},
/// Create a new key
#[clap(name = "show-key")]
ShowKey {},
/// Create a database
#[clap(name = "new-db")]
NewDB {},
/// Show the database with an address
#[clap(name = "show-db")]
ShowDB {
/// the address of database
#[clap(long)]
addr: String,
},
/// Create a new collection
#[clap(name = "new-collection")]
NewCollection {
/// the address of database
#[clap(long)]
addr: String,
/// the name of collection
#[clap(long)]
name: String,
/// the json style config of index
#[clap(long = "index")]
index_list: Vec<String>,
},
#[clap(name = "show-collection")]
ShowCollection {
/// the address of database
#[clap(long)]
addr: String,
},
}

impl DB3ClientCommand {
fn current_seconds() -> u64 {
match SystemTime::now().duration_since(UNIX_EPOCH) {
Ok(n) => n.as_secs(),
Err(_) => 0,
}
}

fn show_collection(database: &Database) {
let mut table = Table::new();
table.set_format(*format::consts::FORMAT_NO_BORDER_LINE_SEPARATOR);
table.set_titles(row!["name", "index",]);
for collection in &database.collections {
let index_str: String = collection
.index_list
.iter()
.map(|i| serde_json::to_string(&i).unwrap())
.intersperse("\n ".to_string())
.collect();
table.add_row(row![collection.name, index_str]);
}
table.printstd();
}

fn show_database(database: &Database) {
let mut table = Table::new();
table.set_format(*format::consts::FORMAT_NO_BORDER_LINE_SEPARATOR);
table.set_titles(row![
"database address",
"sender address",
"releated transactions",
"collections"
]);
let tx_list: String = database
.tx
.iter()
.map(|tx| TxId::try_from_bytes(tx).unwrap().to_base64())
.intersperse("\n ".to_string())
.collect();
let collections: String = database
.collections
.iter()
.map(|c| c.name.to_string())
.intersperse("\n ".to_string())
.collect();
let address_ref: &[u8] = database.address.as_ref();
let sender_ref: &[u8] = database.sender.as_ref();
table.add_row(row![
DbId::try_from(address_ref).unwrap().to_hex(),
AccountId::try_from(sender_ref).unwrap().to_hex(),
tx_list,
collections
]);
table.printstd();
}

pub async fn execute(self, ctx: &mut DB3ClientContext) {
match self {
DB3ClientCommand::Init {} => {
if let Ok(_) = KeyStore::recover_keypair() {
println!("Init key successfully!");
}
}

DB3ClientCommand::ShowKey {} => {
if let Ok(ks) = KeyStore::recover_keypair() {
ks.show_key();
} else {
println!("no key was found, you can use init command to create a new one");
}
}
DB3ClientCommand::NewCollection {
addr,
name,
index_list,
} => {
//TODO validate the index
let index_vec: Vec<Index> = index_list
.iter()
.map(|i| serde_json::from_str::<Index>(i.as_str()).unwrap())
.collect();
let collection = CollectionMutation {
index: index_vec.to_owned(),
collection_id: name.to_string(),
};
//TODO check database id and collection name
let db_id = DbId::try_from(addr.as_str()).unwrap();
let meta = BroadcastMeta {
//TODO get from network
nonce: Self::current_seconds(),
//TODO use config
chain_id: ChainId::DevNet.into(),
//TODO use config
chain_role: ChainRole::StorageShardChain.into(),
};
let dm = DatabaseMutation {
meta: Some(meta),
collection_mutations: vec![collection],
db_address: db_id.as_ref().to_vec(),
action: DatabaseAction::AddCollection.into(),
};
if let Ok((_, tx_id)) = ctx
.mutation_sdk
.as_ref()
.unwrap()
.submit_database_mutation(&dm)
.await
{
println!("send add collection done with tx\n{}", tx_id.to_base64());
} else {
println!("fail to add collection");
}
}
DB3ClientCommand::ShowCollection { addr } => {
match ctx
.store_sdk
.as_mut()
.unwrap()
.get_database(addr.as_ref())
.await
{
Ok(Some(database)) => {
Self::show_collection(&database);
}
Ok(None) => {
println!("no collection with target address");
}
Err(e) => {
println!("fail to show collections with error {e}");
}
}
}

DB3ClientCommand::ShowDB { addr } => {
match ctx
.store_sdk
.as_mut()
.unwrap()
.get_database(addr.as_ref())
.await
{
Ok(Some(database)) => {
Self::show_database(&database);
}
Ok(None) => {
println!("no database with target address");
}
Err(e) => {
println!("fail to show database with error {e}");
}
}
}

DB3ClientCommand::NewDB {} => {
let meta = BroadcastMeta {
//TODO get from network
nonce: Self::current_seconds(),
//TODO use config
chain_id: ChainId::DevNet.into(),
//TODO use config
chain_role: ChainRole::StorageShardChain.into(),
};
let dm = DatabaseMutation {
meta: Some(meta),
collection_mutations: vec![],
db_address: vec![],
action: DatabaseAction::CreateDb.into(),
};
if let Ok((db_id, tx_id)) = ctx
.mutation_sdk
.as_ref()
.unwrap()
.submit_database_mutation(&dm)
.await
{
let mut table = Table::new();
table.set_format(*format::consts::FORMAT_NO_BORDER_LINE_SEPARATOR);
table.set_titles(row!["database address", "transaction id"]);
table.add_row(row![db_id.to_hex(), tx_id.to_base64()]);
table.printstd();
} else {
println!("fail to create database");
}
}
}
}
}
Loading