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

@@ -1,5 +1,12 @@
fn main() {
tonic_build::configure()
.compile(&["greptime/v1/greptime.proto"], &["."])
.compile(
&[
"greptime/v1/insert.proto",
"greptime/v1/select.proto",
"greptime/v1/greptime.proto",
],
&["."],
)
.expect("compile proto");
}

View File

@@ -12,7 +12,7 @@ message DatabaseResponse {
}
message ObjectExpr {
Header header = 1;
ExprHeader header = 1;
oneof expr {
InsertExpr insert = 2;
SelectExpr select = 3;
@@ -21,8 +21,16 @@ message ObjectExpr {
}
}
message ExprHeader {
uint32 version = 1;
}
// TODO(fys): Only support sql now, and
// will support promql etc in the future
message SelectExpr {
string select = 1; // sql, promql, etc.
oneof expr {
string sql = 1;
}
}
message InsertExpr {
@@ -37,17 +45,23 @@ message DeleteExpr {}
message ObjectResult {
ResultHeader header = 1;
bytes results = 2;
oneof result {
SelectResult select = 2;
MutateResult mutate = 3;
}
}
message Header {
uint32 version = 1;
message SelectResult {
bytes raw_data = 1;
}
message ResultHeader {
uint32 version = 1;
uint32 success = 2;
uint32 failure = 3;
uint32 code = 4;
string err_msg = 5;
uint32 code = 2;
string err_msg = 3;
}
message MutateResult {
uint32 success = 1;
uint32 failure = 2;
}

View File

@@ -4,8 +4,6 @@ package greptime.v1;
import "greptime/v1/admin.proto";
import "greptime/v1/database.proto";
import "greptime/v1/insert.proto";
import "greptime/v1/select.proto";
service Greptime {
rpc Batch(BatchRequest) returns (BatchResponse) {}

View File

@@ -1,6 +1,6 @@
syntax = "proto3";
package greptime.v1;
package greptime.v1.codec;
import "greptime/v1/column.proto";
@@ -8,4 +8,3 @@ message InsertBatch {
repeated Column columns = 1;
uint32 row_count = 2;
}

View File

@@ -1,6 +1,6 @@
syntax = "proto3";
package greptime.v1;
package greptime.v1.codec;
import "greptime/v1/column.proto";

View File

@@ -1,11 +1,11 @@
pub use prost::DecodeError;
use prost::Message;
use crate::v1::InsertBatch;
use crate::v1::codec::{InsertBatch, SelectResult};
impl From<InsertBatch> for Vec<u8> {
fn from(insert: InsertBatch) -> Self {
insert.encode_length_delimited_to_vec()
insert.encode_to_vec()
}
}
@@ -13,13 +13,29 @@ impl TryFrom<Vec<u8>> for InsertBatch {
type Error = DecodeError;
fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
InsertBatch::decode_length_delimited(value.as_ref())
InsertBatch::decode(value.as_ref())
}
}
impl From<SelectResult> for Vec<u8> {
fn from(result: SelectResult) -> Self {
result.encode_to_vec()
}
}
impl TryFrom<Vec<u8>> for SelectResult {
type Error = DecodeError;
fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
SelectResult::decode(value.as_ref())
}
}
#[cfg(test)]
mod tests {
use crate::v1::*;
use crate::v1::codec::*;
use crate::v1::column;
use crate::v1::Column;
const SEMANTIC_TAG: i32 = 0;
@@ -69,6 +85,52 @@ mod tests {
);
}
#[test]
fn test_convert_select_result() {
let select_result = mock_select_result();
let bytes: Vec<u8> = select_result.into();
let result: SelectResult = bytes.try_into().unwrap();
assert_eq!(8, result.row_count);
assert_eq!(1, result.columns.len());
let column = &result.columns[0];
assert_eq!("foo", column.column_name);
assert_eq!(SEMANTIC_TAG, column.semantic_type);
assert_eq!(vec![1], column.null_mask);
assert_eq!(
vec![2, 3, 4, 5, 6, 7, 8],
column.values.as_ref().unwrap().i32_values
);
}
#[should_panic]
#[test]
fn test_convert_select_result_wrong() {
let select_result = mock_select_result();
let mut bytes: Vec<u8> = select_result.into();
// modify some bytes
bytes[0] = 0b1;
bytes[1] = 0b1;
let result: SelectResult = bytes.try_into().unwrap();
assert_eq!(8, result.row_count);
assert_eq!(1, result.columns.len());
let column = &result.columns[0];
assert_eq!("foo", column.column_name);
assert_eq!(SEMANTIC_TAG, column.semantic_type);
assert_eq!(vec![1], column.null_mask);
assert_eq!(
vec![2, 3, 4, 5, 6, 7, 8],
column.values.as_ref().unwrap().i32_values
);
}
fn mock_insert_batch() -> InsertBatch {
let values = column::Values {
i32_values: vec![2, 3, 4, 5, 6, 7, 8],
@@ -86,4 +148,22 @@ mod tests {
row_count: 8,
}
}
fn mock_select_result() -> SelectResult {
let values = column::Values {
i32_values: vec![2, 3, 4, 5, 6, 7, 8],
..Default::default()
};
let null_mask = vec![1];
let column = Column {
column_name: "foo".to_string(),
semantic_type: SEMANTIC_TAG,
values: Some(values),
null_mask,
};
SelectResult {
columns: vec![column],
row_count: 8,
}
}
}

View File

@@ -1 +1,5 @@
tonic::include_proto!("greptime.v1");
pub mod codec {
tonic::include_proto!("greptime.v1.codec");
}