feat: impl select (grpc) (#138)

* SelectExpr: change to oneof expr

* Convert between Vec<u8> and SelectResult

* Chore: use encode_to_vec and decode, instead of encode_length_delimited_to_vec and decode_length_delimited

* Chore: move bitset into separate file

* Grpc select impl
This commit is contained in:
fys
2022-08-15 18:31:47 +08:00
committed by GitHub
parent 60dc77d1d9
commit 34133fae5a
22 changed files with 981 additions and 180 deletions

View File

@@ -13,3 +13,5 @@ tonic = "0.8"
[dev-dependencies]
tokio = { version = "1.0", features = ["full"] }
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }

View File

@@ -1,15 +1,19 @@
use api::v1::*;
use api::v1::{codec::InsertBatch, *};
use client::{Client, Database};
#[tokio::main]
async fn main() {
let url = "http://127.0.0.1:3001";
let db_name = "db";
let table_name = "demo";
fn main() {
tracing::subscriber::set_global_default(tracing_subscriber::FmtSubscriber::builder().finish())
.unwrap();
let client = Client::connect(url).await.unwrap();
let db = Database::new(db_name, client);
db.insert(table_name, insert_batches()).await.unwrap();
run();
}
#[tokio::main]
async fn run() {
let client = Client::connect("http://127.0.0.1:3001").await.unwrap();
let db = Database::new("greptime", client);
db.insert("demo", insert_batches()).await.unwrap();
}
fn insert_batches() -> Vec<Vec<u8>> {

View File

@@ -0,0 +1,23 @@
use api::v1::{select_expr, SelectExpr};
use client::{Client, Database};
use tracing::{event, Level};
fn main() {
tracing::subscriber::set_global_default(tracing_subscriber::FmtSubscriber::builder().finish())
.unwrap();
run();
}
#[tokio::main]
async fn run() {
let client = Client::connect("http://127.0.0.1:3001").await.unwrap();
let db = Database::new("greptime", client);
let select_expr = SelectExpr {
expr: Some(select_expr::Expr::Sql("select * from demo".to_string())),
};
let result = db.select(select_expr).await.unwrap();
event!(Level::INFO, "result: {:#?}", result);
}

View File

@@ -1,9 +1,15 @@
use api::v1::object_expr;
use api::v1::*;
use snafu::ensure;
use api::v1::codec::SelectResult as GrpcSelectResult;
use api::v1::{
object_expr, object_result, DatabaseRequest, ExprHeader, InsertExpr,
MutateResult as GrpcMutateResult, ObjectExpr, ObjectResult as GrpcObjectResult, SelectExpr,
};
use common_error::status_code::StatusCode;
use snafu::{ensure, OptionExt, ResultExt};
use crate::error;
use crate::{Client, Result};
use crate::error::{self, MissingResultSnafu};
use crate::{
error::DataNodeSnafu, error::DecodeSelectSnafu, error::MissingHeaderSnafu, Client, Result,
};
pub const PROTOCOL_VERSION: u32 = 1;
@@ -28,7 +34,7 @@ impl Database {
}
pub async fn insert(&self, table: impl Into<String>, values: Vec<Bytes>) -> Result<()> {
let header = Header {
let header = ExprHeader {
version: PROTOCOL_VERSION,
};
let insert = InsertExpr {
@@ -45,14 +51,53 @@ impl Database {
Ok(())
}
// TODO(jiachun) select/update/delete
pub async fn select(&self, select_expr: SelectExpr) -> Result<ObjectResult> {
let header = ExprHeader {
version: PROTOCOL_VERSION,
};
async fn object(&self, expr: ObjectExpr) -> Result<ObjectResult> {
let expr = ObjectExpr {
header: Some(header),
expr: Some(object_expr::Expr::Select(select_expr)),
};
let obj_result = self.object(expr).await?;
let header = obj_result.header.context(MissingHeaderSnafu)?;
if StatusCode::is_success(header.code) {
return DataNodeSnafu {
code: header.code,
msg: header.err_msg,
}
.fail();
}
let obj_result = obj_result.result.context(MissingResultSnafu {
name: "select_result".to_string(),
expected: 1_usize,
actual: 0_usize,
})?;
let result = match obj_result {
object_result::Result::Select(select) => {
let result = select.raw_data.try_into().context(DecodeSelectSnafu)?;
ObjectResult::Select(result)
}
object_result::Result::Mutate(mutate) => ObjectResult::Mutate(mutate),
};
Ok(result)
}
// TODO(jiachun) update/delete
async fn object(&self, expr: ObjectExpr) -> Result<GrpcObjectResult> {
let res = self.objects(vec![expr]).await?.pop().unwrap();
Ok(res)
}
async fn objects(&self, exprs: Vec<ObjectExpr>) -> Result<Vec<ObjectResult>> {
async fn objects(&self, exprs: Vec<ObjectExpr>) -> Result<Vec<GrpcObjectResult>> {
let expr_count = exprs.len();
let req = DatabaseRequest {
name: self.name.clone(),
@@ -74,3 +119,9 @@ impl Database {
Ok(res)
}
}
#[derive(Debug)]
pub enum ObjectResult {
Select(GrpcSelectResult),
Mutate(GrpcMutateResult),
}

View File

@@ -1,3 +1,4 @@
use api::convert::DecodeError;
use common_error::prelude::*;
#[derive(Debug, Snafu)]
@@ -17,11 +18,20 @@ pub enum Error {
actual: usize,
},
#[snafu(display("Missing result header"))]
MissingHeader,
#[snafu(display("Tonic internal error, source: {}", source))]
TonicStatus {
source: tonic::Status,
backtrace: Backtrace,
},
#[snafu(display("Fail to decode select result, source: {}", source))]
DecodeSelect { source: DecodeError },
#[snafu(display("Error occurred on the data node, code: {}, msg: {}", code, msg))]
DataNode { code: u32, msg: String },
}
pub type Result<T> = std::result::Result<T, Error>;