fix all linter issues

This commit is contained in:
Nicholas Orlowsky 2023-08-08 15:56:41 -05:00 committed by Nicholas Orlowsky
parent 91193cf03e
commit 7f85e2debf
5 changed files with 89 additions and 118 deletions

View file

@ -10,7 +10,7 @@ pub use parser::command::Command;
mod table; mod table;
use parser::command::{CreateCommand, InsertCommand, SelectCommand}; use parser::command::{CreateCommand, InsertCommand, SelectCommand};
pub use table::datatypes::Datatype; pub use table::datatypes::Datatype;
pub use table::table::{ColumnDefinition, TableDefinition}; pub use table::table_definition::{ColumnDefinition, TableDefinition};
const BUFFER_SIZE: usize = 500; const BUFFER_SIZE: usize = 500;
@ -27,7 +27,7 @@ fn handle_create(command: CreateCommand) -> ::anyhow::Result<TableDefinition> {
column.data_type.as_str(), column.data_type.as_str(),
column.length column.length
); );
file.write_all(line.as_bytes()).unwrap(); file.write_all(line.as_bytes())?;
} }
Ok(command.table_definition) Ok(command.table_definition)
@ -43,7 +43,7 @@ fn read_tabledef(table_name: String) -> ::anyhow::Result<TableDefinition> {
let parts: Vec<&str> = line_str.split(' ').collect(); let parts: Vec<&str> = line_str.split(' ').collect();
let col_def = ColumnDefinition { let col_def = ColumnDefinition {
name: parts[0].to_string(), name: parts[0].to_string(),
data_type: Datatype::from_str(parts[1]).unwrap(), data_type: Datatype::parse_from_str(parts[1])?,
length: parts[2].parse::<u16>()?.into(), length: parts[2].parse::<u16>()?.into(),
}; };
column_defs.push(col_def); column_defs.push(col_def);
@ -60,10 +60,9 @@ fn handle_insert(command: InsertCommand) -> ::anyhow::Result<()> {
.create(true) .create(true)
.write(true) .write(true)
.append(true) .append(true)
.open(format!("./data/blobs/{}", command.table_name)) .open(format!("./data/blobs/{}", command.table_name))?;
.unwrap();
let tabledef = read_tabledef(command.table_name).unwrap(); let tabledef = read_tabledef(command.table_name)?;
for col_def in &tabledef.column_defs { for col_def in &tabledef.column_defs {
if let Some(insert_item) = command.items.get(&col_def.name) { if let Some(insert_item) = command.items.get(&col_def.name) {
@ -89,7 +88,7 @@ fn handle_insert(command: InsertCommand) -> ::anyhow::Result<()> {
fn handle_select(command: SelectCommand) -> ::anyhow::Result<String> { fn handle_select(command: SelectCommand) -> ::anyhow::Result<String> {
let mut file = fs::File::open(format!("./data/blobs/{}", command.table_name))?; let mut file = fs::File::open(format!("./data/blobs/{}", command.table_name))?;
let tabledef = read_tabledef(command.table_name).unwrap(); let tabledef = read_tabledef(command.table_name)?;
let mut response = String::new(); let mut response = String::new();
response += "| "; response += "| ";

View file

@ -1,6 +1,6 @@
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use crate::table::table::ColumnDefinition; use crate::table::table_definition::ColumnDefinition;
use crate::{Datatype, TableDefinition}; use crate::{Datatype, TableDefinition};
use anyhow::anyhow; use anyhow::anyhow;
@ -36,34 +36,34 @@ pub struct InsertItem {
} }
enum CreateParserState { enum CreateParserState {
FindObject, Object,
FindTableName, TableName,
FindColumnName, ColumnName,
FindColumnDefinitions, ColumnDefinitions,
FindColumnDatatype, ColumnDatatype,
FindColumnDefinitionEnd, ColumnDefinitionEnd,
FindColumnLength, ColumnLength,
FindSemicolon, Semicolon,
} }
enum SelectParserState { enum SelectParserState {
FindWildcard, // Temporary, col selection coming soon Wildcard, // Temporary, col selection coming soon
FindFrom, FromKeyword,
FindTableName, TableName,
FindSemicolon, Semicolon,
} }
enum InsertParserState { enum InsertParserState {
FindIntoKeyword, IntoKeyword,
FindTableName, TableName,
FindColumnListBegin, ColumnListBegin,
FindColumnName, ColumnName,
FindColumnNameEnd, ColumnNameEnd,
FindValuesKeyword, ValuesKeyword,
FindValuesListBegin, ValuesListBegin,
FindValue, Value,
FindValueEnd, ValueEnd,
FindSemicolon, Semicolon,
} }
pub fn tokenizer(text: String) -> Vec<String> { pub fn tokenizer(text: String) -> Vec<String> {
@ -95,7 +95,7 @@ pub fn tokenizer(text: String) -> Vec<String> {
impl Command { impl Command {
fn parse_insert_command(tokens: &mut Vec<String>) -> ::anyhow::Result<Command> { fn parse_insert_command(tokens: &mut Vec<String>) -> ::anyhow::Result<Command> {
let mut state: InsertParserState = InsertParserState::FindIntoKeyword; let mut state: InsertParserState = InsertParserState::IntoKeyword;
let mut table_name = String::new(); let mut table_name = String::new();
let mut column_name = String::new(); let mut column_name = String::new();
@ -106,35 +106,35 @@ impl Command {
while let Some(token) = &tokens.pop() { while let Some(token) = &tokens.pop() {
match state { match state {
InsertParserState::FindIntoKeyword => { InsertParserState::IntoKeyword => {
if !token.eq_ignore_ascii_case("INTO") { if !token.eq_ignore_ascii_case("INTO") {
return Err(anyhow!("Expected to find INTO at or near '{}'", token)); return Err(anyhow!("Expected to find INTO at or near '{}'", token));
} else { } else {
state = InsertParserState::FindTableName; state = InsertParserState::TableName;
} }
} }
InsertParserState::FindTableName => { InsertParserState::TableName => {
table_name = token.to_string(); table_name = token.to_string();
state = InsertParserState::FindColumnListBegin; state = InsertParserState::ColumnListBegin;
} }
InsertParserState::FindColumnListBegin => { InsertParserState::ColumnListBegin => {
if token != "(" { if token != "(" {
return Err(anyhow!( return Err(anyhow!(
"Unexpected token at or near '{}'. Expected start of column list", "Unexpected token at or near '{}'. Expected start of column list",
token token
)); ));
} }
state = InsertParserState::FindColumnName; state = InsertParserState::ColumnName;
} }
InsertParserState::FindColumnName => { InsertParserState::ColumnName => {
column_name = token.to_string(); column_name = token.to_string();
state = InsertParserState::FindColumnNameEnd; state = InsertParserState::ColumnNameEnd;
} }
InsertParserState::FindColumnNameEnd => { InsertParserState::ColumnNameEnd => {
if token == "," { if token == "," {
state = InsertParserState::FindColumnName; state = InsertParserState::ColumnName;
} else if token == ")" { } else if token == ")" {
state = InsertParserState::FindValuesKeyword; state = InsertParserState::ValuesKeyword;
} else { } else {
return Err(anyhow!( return Err(anyhow!(
"Unexpected token at or near '{}'. Expected comma or rparen.", "Unexpected token at or near '{}'. Expected comma or rparen.",
@ -143,33 +143,33 @@ impl Command {
} }
column_list.push(column_name.clone()); column_list.push(column_name.clone());
} }
InsertParserState::FindValuesKeyword => { InsertParserState::ValuesKeyword => {
if token != "VALUES" { if token != "VALUES" {
return Err(anyhow!( return Err(anyhow!(
"Unexpected token at or near '{}'. Expected 'VALUES'.", "Unexpected token at or near '{}'. Expected 'VALUES'.",
token token
)); ));
} }
state = InsertParserState::FindValuesListBegin; state = InsertParserState::ValuesListBegin;
} }
InsertParserState::FindValuesListBegin => { InsertParserState::ValuesListBegin => {
if token != "(" { if token != "(" {
return Err(anyhow!( return Err(anyhow!(
"Unexpected token at or near '{}'. Expected start of values list", "Unexpected token at or near '{}'. Expected start of values list",
token token
)); ));
} }
state = InsertParserState::FindValue; state = InsertParserState::Value;
} }
InsertParserState::FindValue => { InsertParserState::Value => {
column_val = token.to_string(); column_val = token.to_string();
state = InsertParserState::FindValueEnd; state = InsertParserState::ValueEnd;
} }
InsertParserState::FindValueEnd => { InsertParserState::ValueEnd => {
if token == "," { if token == "," {
state = InsertParserState::FindValue; state = InsertParserState::Value;
} else if token == ")" { } else if token == ")" {
state = InsertParserState::FindSemicolon; state = InsertParserState::Semicolon;
} else { } else {
return Err(anyhow!( return Err(anyhow!(
"Unexpected token at or near '{}'. Expected comma or rparen.", "Unexpected token at or near '{}'. Expected comma or rparen.",
@ -179,7 +179,7 @@ impl Command {
value_list.push(column_val.clone()); value_list.push(column_val.clone());
} }
InsertParserState::FindSemicolon => { InsertParserState::Semicolon => {
if token != ";" { if token != ";" {
return Err(anyhow!("Expected semicolon at or near '{}'", token)); return Err(anyhow!("Expected semicolon at or near '{}'", token));
} else { } else {
@ -208,32 +208,32 @@ impl Command {
} }
fn parse_select_command(tokens: &mut Vec<String>) -> ::anyhow::Result<Command> { fn parse_select_command(tokens: &mut Vec<String>) -> ::anyhow::Result<Command> {
let mut state: SelectParserState = SelectParserState::FindWildcard; let mut state: SelectParserState = SelectParserState::Wildcard;
// intermediate tmp vars // intermediate tmp vars
let mut table_name = String::new(); let mut table_name = String::new();
while let Some(token) = &tokens.pop() { while let Some(token) = &tokens.pop() {
match state { match state {
SelectParserState::FindWildcard => { SelectParserState::Wildcard => {
if token != "*" { if token != "*" {
return Err(anyhow!("Expected to find selection at or near '{}' (SQUIRREL does not support column seletion)", token)); return Err(anyhow!("Expected to find selection at or near '{}' (SQUIRREL does not support column seletion)", token));
} else { } else {
state = SelectParserState::FindFrom; state = SelectParserState::FromKeyword;
} }
} }
SelectParserState::FindFrom => { SelectParserState::FromKeyword => {
if !token.eq_ignore_ascii_case("FROM") { if !token.eq_ignore_ascii_case("FROM") {
return Err(anyhow!("Expected to find FROM at or near '{}'", token)); return Err(anyhow!("Expected to find FROM at or near '{}'", token));
} else { } else {
state = SelectParserState::FindTableName; state = SelectParserState::TableName;
} }
} }
SelectParserState::FindTableName => { SelectParserState::TableName => {
table_name = token.to_string(); table_name = token.to_string();
state = SelectParserState::FindSemicolon; state = SelectParserState::Semicolon;
} }
SelectParserState::FindSemicolon => { SelectParserState::Semicolon => {
if token != ";" { if token != ";" {
return Err(anyhow!("Expected semicolon at or near '{}'", token)); return Err(anyhow!("Expected semicolon at or near '{}'", token));
} else { } else {
@ -247,7 +247,7 @@ impl Command {
} }
fn parse_create_command(tokens: &mut Vec<String>) -> ::anyhow::Result<Command> { fn parse_create_command(tokens: &mut Vec<String>) -> ::anyhow::Result<Command> {
let mut state: CreateParserState = CreateParserState::FindObject; let mut state: CreateParserState = CreateParserState::Object;
let mut col_defs: Vec<ColumnDefinition> = vec![]; let mut col_defs: Vec<ColumnDefinition> = vec![];
// intermediate tmp vars // intermediate tmp vars
@ -258,41 +258,41 @@ impl Command {
while let Some(token) = &tokens.pop() { while let Some(token) = &tokens.pop() {
match state { match state {
CreateParserState::FindObject => match token.to_uppercase().as_str() { CreateParserState::Object => match token.to_uppercase().as_str() {
"TABLE" => { "TABLE" => {
state = CreateParserState::FindTableName; state = CreateParserState::TableName;
} }
_ => return Err(anyhow!("Can't create object of type '{}'", token.as_str())), _ => return Err(anyhow!("Can't create object of type '{}'", token.as_str())),
}, },
CreateParserState::FindTableName => { CreateParserState::TableName => {
state = CreateParserState::FindColumnDefinitions; state = CreateParserState::ColumnDefinitions;
table_name = token.to_string(); table_name = token.to_string();
} }
CreateParserState::FindColumnDefinitions => { CreateParserState::ColumnDefinitions => {
if token != "(" { if token != "(" {
return Err(anyhow!("Could not find column list")); return Err(anyhow!("Could not find column list"));
} else { } else {
state = CreateParserState::FindColumnName; state = CreateParserState::ColumnName;
} }
} }
CreateParserState::FindColumnName => { CreateParserState::ColumnName => {
col_name = token.to_string(); col_name = token.to_string();
state = CreateParserState::FindColumnDatatype; state = CreateParserState::ColumnDatatype;
} }
CreateParserState::FindColumnDatatype => { CreateParserState::ColumnDatatype => {
let dtype = Datatype::from_str(token).unwrap(); let dtype = Datatype::parse_from_str(token).unwrap();
if dtype.has_len() { if dtype.has_len() {
state = CreateParserState::FindColumnLength; state = CreateParserState::ColumnLength;
} else { } else {
state = CreateParserState::FindColumnDefinitionEnd; state = CreateParserState::ColumnDefinitionEnd;
} }
data_type = Some(dtype); data_type = Some(dtype);
} }
CreateParserState::FindColumnLength => { CreateParserState::ColumnLength => {
length = token.parse()?; length = token.parse()?;
state = CreateParserState::FindColumnDefinitionEnd; state = CreateParserState::ColumnDefinitionEnd;
} }
CreateParserState::FindColumnDefinitionEnd => { CreateParserState::ColumnDefinitionEnd => {
let column_def = ColumnDefinition { let column_def = ColumnDefinition {
data_type: data_type.unwrap(), data_type: data_type.unwrap(),
length, length,
@ -307,15 +307,15 @@ impl Command {
match token.as_str() { match token.as_str() {
"," => { "," => {
state = CreateParserState::FindColumnName; state = CreateParserState::ColumnName;
} }
")" => { ")" => {
state = CreateParserState::FindSemicolon; state = CreateParserState::Semicolon;
} }
_ => return Err(anyhow!("Expected end")), _ => return Err(anyhow!("Expected end")),
} }
} }
CreateParserState::FindSemicolon => { CreateParserState::Semicolon => {
if token != ";" { if token != ";" {
return Err(anyhow!("Expected semicolon at or near '{}'", token)); return Err(anyhow!("Expected semicolon at or near '{}'", token));
} else { } else {

View file

@ -1,3 +1,5 @@
use anyhow::anyhow;
#[derive(Debug, Eq, PartialEq)] #[derive(Debug, Eq, PartialEq)]
pub enum Datatype { pub enum Datatype {
Integer, Integer,
@ -54,14 +56,15 @@ impl Datatype {
} }
} }
} }
pub fn from_str(string: &str) -> Result<Datatype, String> {
pub fn parse_from_str(string: &str) -> ::anyhow::Result<Datatype> {
match string { match string {
"varchar" => return Ok(Datatype::CharacterVarying), "varchar" => Ok(Datatype::CharacterVarying),
"character varying" => return Ok(Datatype::CharacterVarying), "character varying" => Ok(Datatype::CharacterVarying),
"integer" => return Ok(Datatype::Integer), "integer" => Ok(Datatype::Integer),
"int" => return Ok(Datatype::Integer), "int" => Ok(Datatype::Integer),
"int8" => return Ok(Datatype::Integer), "int8" => Ok(Datatype::Integer),
_ => return Err(String::from("Undefined data type")), _ => Err(anyhow!("Undefined data type")),
} }
} }
} }

View file

@ -1,2 +1,2 @@
pub mod datatypes; pub mod datatypes;
pub mod table; pub mod table_definition;

View file

@ -1,31 +0,0 @@
use crate::Datatype;
#[derive(Debug, Eq, PartialEq)]
pub struct ColumnDefinition {
pub name: String,
pub data_type: Datatype,
pub length: usize, // used for char(n), varchar(n)
}
#[derive(Debug, Eq, PartialEq)]
pub struct TableDefinition {
pub name: String,
pub column_defs: Vec<ColumnDefinition>,
}
impl TableDefinition {
pub fn get_byte_size(&self) -> usize {
let mut sum: usize = 0;
for col_def in self.column_defs.iter() {
// TODO HACK FIXME
// We should keep track of length
// even for built-in datatypes.
sum += if col_def.length > 0 {
col_def.length
} else {
1
};
}
sum
}
}