Skip to content

Commit

Permalink
Support show db and tables (#65)
Browse files Browse the repository at this point in the history
  • Loading branch information
w41ter authored May 29, 2024
1 parent 212bead commit 50e8f76
Show file tree
Hide file tree
Showing 8 changed files with 121 additions and 11 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 6 additions & 2 deletions src/bin/src/shell/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ impl Session {
Statement::Echo(echo) => Ok(Some(ExecuteResult::Msg(echo.message))),
Statement::CreateDb(_) => todo!(),
Statement::CreateTable(_) => todo!(),
Statement::Config(_) => Ok(None),
Statement::Config(_) | Statement::Show(_) => Ok(None),
}
}

Expand All @@ -103,7 +103,10 @@ impl Session {
total_columns
);
}
builder.push_record(row.values.iter().map(ToString::to_string));
builder.push_record(row.values.iter().map(|v| match v {
serde_json::Value::String(str) => str.clone(),
_ => v.to_string(),
}));
}

let table = builder.build().with(Style::ascii_rounded()).to_string();
Expand All @@ -112,6 +115,7 @@ impl Session {
ExecuteResult::Msg(msg) => {
println!("{}", msg);
}
ExecuteResult::None => (),
}
}
}
Expand Down
27 changes: 24 additions & 3 deletions src/parser/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub enum Statement {
Debug(DebugStatement),
Echo(EchoStatement),
Help(HelpStatement),
Show(ShowStatement),
}

#[derive(Debug)]
Expand Down Expand Up @@ -58,6 +59,12 @@ pub struct HelpStatement {
pub topic: Option<String>,
}

#[derive(Debug)]
pub struct ShowStatement {
pub property: String,
pub from: Option<String>,
}

impl DebugStatement {
#[inline]
pub fn execute(&self) -> ExecuteResult {
Expand All @@ -78,6 +85,7 @@ impl HelpStatement {
fn display_topic(topic: &str) -> String {
match topic {
"create" | "CREATE" => Self::display_create_topic(),
"show" | "SHOW" => Self::display_show_topic(),
_ => {
format!("unkonwn command `{}`. Try `help`?", topic)
}
Expand All @@ -86,14 +94,27 @@ impl HelpStatement {

fn display_create_topic() -> String {
r##"
CREATE DATABASE [IF NOT EXISTS] <name>
CREATE DATABASE [IF NOT EXISTS] <name:ident>
Create a new database.
CREATE TABLE [IF NOT EXISTS] [<db>.]<name>
CREATE TABLE [IF NOT EXISTS] [<db:ident>.]<name:ident>
Create a new table.
Note:
The <name> accepts characters [a-zA-Z0-9_-].
The ident accepts characters [a-zA-Z0-9_-].
"##
.to_owned()
}

fn display_show_topic() -> String {
r##"
SHOW <property:ident> [FROM <name:ident>]
Show properties. supported properties:
- databases
- tables FROM <database>
Note:
The ident accepts characters [a-zA-Z0-9_-].
"##
.to_owned()
}
Expand Down
1 change: 1 addition & 0 deletions src/parser/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,5 @@ pub struct ColumnResult {
pub enum ExecuteResult {
Data(ColumnResult),
Msg(String),
None,
}
15 changes: 13 additions & 2 deletions src/parser/src/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
use crate::token::{TokenRule, Tokenizer};
use crate::{
ConfigStatement, CreateDbStatement, CreateTableStatement, DebugStatement, EchoStatement,
HelpStatement, ParseError, ParseResult, Statement, Token,
HelpStatement, ParseError, ParseResult, ShowStatement, Statement, Token,
};

#[derive(Debug)]
Expand Down Expand Up @@ -137,9 +137,20 @@ fn parse_set_stmt(parser: &mut Parser) -> ParseResult<Statement> {
todo!()
}

// Syntax:
// SHOW <property:ident> [FROM <name:ident>]
fn parse_show_stmt(parser: &mut Parser) -> ParseResult<Statement> {
parser.next::<Token![show]>()?;
todo!()
let ident = parser.next::<Token![ident]>()?;
let from = if parser.peek::<Token![from]>() {
parser.next::<Token![from]>()?;
let name = parser.next::<Token![ident]>()?;
Some(name.value().to_owned())
} else {
None
};
parser.next::<Token![;]>()?;
Ok(Statement::Show(ShowStatement { property: ident.value().to_owned(), from }))
}

// Syntax:
Expand Down
2 changes: 2 additions & 0 deletions src/parser/src/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ keyword!(database);
keyword!(debug);
keyword!(echo);
keyword!(exists);
keyword!(from);
keyword!(get);
keyword!(help);
keyword!(if);
Expand Down Expand Up @@ -253,6 +254,7 @@ macro_rules! Token {
[debug] => { $crate::token::Debug };
[echo] => { $crate::token::Echo };
[exists] => { $crate::token::Exists };
[from] => { $crate::token::From };
[get] => { $crate::token::Get };
[help] => { $crate::token::Help };
[if] => { $crate::token::If };
Expand Down
1 change: 1 addition & 0 deletions src/server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ description = "The Sekas server."
sekas-api = { path = "../api", version = "0.5" }
sekas-client = { path = "../client", version = "0.5" }
sekas-macro = { path = "../macro", version = "0.5" }
sekas-parser = { path = "../parser", version = "0.5" }
sekas-rock = { path = "../rock", version = "0.5" }
sekas-runtime = { path = "../runtime", version = "0.5" }
sekas-schema = { path = "../schema", version = "0.5" }
Expand Down
77 changes: 73 additions & 4 deletions src/server/src/root/stmt_executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,82 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use log::warn;
use sekas_parser::{ColumnResult, ConfigStatement, ExecuteResult, Row, ShowStatement};

use super::Root;
use crate::Result;
use crate::{Error, Result};

impl Root {
/// Handle statement and return with json.
pub async fn handle_statement(&self, statement: &str) -> Result<Vec<u8>> {
let _ = statement;
todo!()
pub async fn handle_statement(&self, input: &str) -> Result<Vec<u8>> {
let result = self.handle_statement_inner(input).await?;
match serde_json::to_vec(&result) {
Ok(bytes) => Ok(bytes),
Err(err) => {
warn!("serialize result {:?}: {:?}", result, err);
Ok(br#"{"Msg":"internal error, serialize execute result failed"}"#.to_vec())
}
}
}

async fn handle_statement_inner(&self, input: &str) -> Result<ExecuteResult> {
use sekas_parser::Statement::*;

let Some(stmt) = sekas_parser::parse(input).unwrap() else {
return Ok(ExecuteResult::None);
};
match stmt {
Config(config) => self.handle_config_stmt(config).await,
Show(show) => self.handle_show_stmt(show).await,
CreateDb(_) | CreateTable(_) | Debug(_) | Echo(_) | Help(_) => {
Err(Error::InvalidArgument(", local stmt is sent to root server".to_owned()))
}
}
}
async fn handle_config_stmt(&self, config_stmt: ConfigStatement) -> Result<ExecuteResult> {
let _ = config_stmt;
Ok(ExecuteResult::Msg("the CONFIG statement is not supported yet".to_owned()))
}

async fn handle_show_stmt(&self, show_stmt: ShowStatement) -> Result<ExecuteResult> {
match show_stmt.property.as_str() {
"databases" => {
if show_stmt.from.is_some() {
return Ok(ExecuteResult::Msg(
"FROM clause is not required by 'databases' property".to_owned(),
));
}
let databases = self.list_database().await?;
let columns =
["id", "name"].into_iter().map(ToString::to_string).collect::<Vec<_>>();
let rows = databases
.into_iter()
.map(|db| Row { values: vec![db.id.into(), db.name.into()] })
.collect::<Vec<_>>();
Ok(ExecuteResult::Data(ColumnResult { columns, rows }))
}
"tables" => {
let Some(db) = show_stmt.from.as_ref() else {
return Ok(ExecuteResult::Msg(
"the database is not specified, add it via the FROM clause".to_owned(),
));
};
let Some(db_desc) = self.get_database(db).await? else {
return Ok(ExecuteResult::Msg(format!("database '{db}' is not exists")));
};

let tables = self.list_table(&db_desc).await?;
let columns =
["id", "name"].into_iter().map(ToString::to_string).collect::<Vec<_>>();
let rows = tables
.into_iter()
.map(|table| Row { values: vec![table.id.into(), table.name.into()] })
.collect::<Vec<_>>();
Ok(ExecuteResult::Data(ColumnResult { columns, rows }))
}
others => Ok(ExecuteResult::Msg(format!("unknown property: {others}"))),
}
}
}

0 comments on commit 50e8f76

Please sign in to comment.