Skip to content

Commit

Permalink
Implement hidden selected fields
Browse files Browse the repository at this point in the history
  • Loading branch information
AmrDeveloper committed Jul 14, 2023
1 parent 96ca8cb commit a409a54
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 49 deletions.
5 changes: 3 additions & 2 deletions src/engine.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::object::{render_objects, GQLObject};
use crate::object::GQLObject;
use crate::render::render_objects;
use crate::statement::GQLQuery;

const GQL_COMMANDS_IN_ORDER: [&'static str; 8] = [
Expand Down Expand Up @@ -37,5 +38,5 @@ pub fn evaluate(repo: &git2::Repository, query: GQLQuery) {
group.drain(1..);
}

render_objects(&objects);
render_objects(&objects, &query.hidden_selections);
}
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ mod engine_function;
mod expression;
mod object;
mod parser;
mod render;
mod statement;
mod tokenizer;
mod transformation;
Expand Down
41 changes: 0 additions & 41 deletions src/object.rs
Original file line number Diff line number Diff line change
@@ -1,47 +1,6 @@
use prettytable::{Cell, Row, Table};
use std::collections::HashMap;

#[derive(Clone)]
pub struct GQLObject {
pub attributes: HashMap<String, String>,
}

pub fn render_objects(groups: &Vec<Vec<GQLObject>>) {
if groups.is_empty() || groups[0].is_empty() {
return;
}

let mut titles: Vec<&str> = groups[0][0].attributes.keys().map(|k| k.as_ref()).collect();
titles.sort();

let mut table = Table::new();
let mut table_titles: Vec<Cell> = Vec::new();
for key in titles {
table_titles.push(Cell::new(key));
}

table.add_row(Row::new(table_titles));

let table_field_max_len = 40;
for group in groups {
for object in group {
let mut keys: Vec<&str> = object.attributes.keys().map(|k| k.as_ref()).collect();
keys.sort();

let mut table_row = Row::new(Vec::new());
for key in keys {
let value = &object.attributes[key];
if value.len() > table_field_max_len {
let wrapped = textwrap::wrap(value, table_field_max_len);
let formatted = wrapped.join("\n");
table_row.add_cell(Cell::new(&formatted));
} else {
table_row.add_cell(Cell::new(value));
}
}
table.add_row(table_row);
}
}

table.printstd();
}
29 changes: 23 additions & 6 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ pub fn parse_gql(tokens: Vec<Token>) -> Result<GQLQuery, GQLError> {
let mut statements: HashMap<String, Box<dyn Statement>> = HashMap::new();
let mut aggregations: HashMap<String, AggregateFunction> = HashMap::new();
let mut extra_type_table: HashMap<String, DataType> = HashMap::new();
let mut hidden_selections: Vec<String> = Vec::new();

let mut select_aggregations_only = false;

while position < len {
Expand All @@ -77,7 +79,9 @@ pub fn parse_gql(tokens: Vec<Token>) -> Result<GQLQuery, GQLError> {
&mut position,
&mut aggregations,
&mut extra_type_table,
&mut hidden_selections,
);

if parse_result.is_err() {
return Err(parse_result.err().unwrap());
}
Expand Down Expand Up @@ -189,6 +193,7 @@ pub fn parse_gql(tokens: Vec<Token>) -> Result<GQLQuery, GQLError> {
return Ok(GQLQuery {
statements,
select_aggregations_only,
hidden_selections,
});
}

Expand All @@ -197,11 +202,13 @@ fn parse_select_statement(
position: &mut usize,
aggregations: &mut HashMap<String, AggregateFunction>,
extra_type_table: &mut HashMap<String, DataType>,
hidden_selections: &mut Vec<String>,
) -> Result<(Box<dyn Statement>, bool), GQLError> {
*position += 1;
let mut fields: Vec<String> = Vec::new();
let mut selected_fields: Vec<String> = Vec::new();
let mut fields_set: HashSet<String> = HashSet::new();
let mut alias_table: HashMap<String, String> = HashMap::new();

let mut select_aggregations_only = true;

if *position >= tokens.len() {
Expand All @@ -213,6 +220,7 @@ fn parse_select_statement(

if tokens[*position].kind == TokenKind::Star {
*position += 1;
select_aggregations_only = false;
} else if tokens[*position].kind == TokenKind::Symbol {
let mut fields_names: HashSet<String> = HashSet::new();
let mut aggregation_function_index = 0;
Expand Down Expand Up @@ -252,6 +260,11 @@ fn parse_select_statement(
});
}

if !fields_set.contains(&argument.literal) {
selected_fields.push(argument.literal.to_string());
hidden_selections.push(argument.literal.to_string());
}

// Consume argument
*position += 1;

Expand Down Expand Up @@ -345,7 +358,12 @@ fn parse_select_statement(
});
}

fields.push(field_name.to_string());
let index = hidden_selections.iter().position(|r| r == &field_name);
if let Some(position) = index {
hidden_selections.remove(position);
}

selected_fields.push(field_name.to_string());

if tokens[*position].kind == TokenKind::As {
*position += 1;
Expand Down Expand Up @@ -394,7 +412,6 @@ fn parse_select_statement(
}

if tokens[*position].kind != TokenKind::From {
println!("{}", tokens[*position].literal);
return Err(GQLError {
message: "Expect `from` keyword after attributes".to_owned(),
location: tokens[*position].location,
Expand Down Expand Up @@ -422,10 +439,10 @@ fn parse_select_statement(
unsafe { CURRENT_TABLE_FIELDS.clear() };

let valid_fields = TABLES_FIELDS_NAMES.get(table_name.as_str()).unwrap();
for field in &fields {
for field in &selected_fields {
if !valid_fields.contains(&field.as_str()) {
return Err(GQLError {
message: "Invalid Field name".to_owned(),
message: format!("Table {} has no field with name {}", table_name, field),
location: tokens[*position].location,
});
}
Expand All @@ -447,7 +464,7 @@ fn parse_select_statement(

let statement = SelectStatement {
table_name: table_name.to_string(),
fields,
fields: selected_fields,
alias_table,
};

Expand Down
45 changes: 45 additions & 0 deletions src/render.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
use prettytable::{Cell, Row, Table};

use crate::object::GQLObject;

pub fn render_objects(groups: &Vec<Vec<GQLObject>>, hidden_selections: &Vec<String>) {
if groups.is_empty() || groups[0].is_empty() {
return;
}

let titles: Vec<&str> = groups[0][0]
.attributes
.keys()
.filter(|s| !hidden_selections.contains(s))
.map(|k| k.as_ref())
.collect();

let mut table = Table::new();
let mut table_titles: Vec<Cell> = Vec::new();

for key in &titles {
table_titles.push(Cell::new(key));
}

table.add_row(Row::new(table_titles));

let table_field_max_len = 40;
for group in groups {
for object in group {
let mut table_row = Row::new(Vec::new());
for key in &titles {
let value = &object.attributes.get(&key as &str).unwrap();
if value.len() > table_field_max_len {
let wrapped = textwrap::wrap(value, table_field_max_len);
let formatted = wrapped.join("\n");
table_row.add_cell(Cell::new(&formatted));
} else {
table_row.add_cell(Cell::new(value));
}
}
table.add_row(table_row);
}
}

table.printstd();
}
1 change: 1 addition & 0 deletions src/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub trait Statement {
pub struct GQLQuery {
pub statements: HashMap<String, Box<dyn Statement>>,
pub select_aggregations_only: bool,
pub hidden_selections: Vec<String>,
}

pub struct SelectStatement {
Expand Down

0 comments on commit a409a54

Please sign in to comment.