Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
0e2d408
query struct + WIP procesar query
sttesta3 Sep 2, 2024
c13aeca
WIP: validacion formato y exec
sttesta3 Sep 4, 2024
cd942d6
WIP: Por iniciar exec
sttesta3 Sep 7, 2024
fb84775
WIP: Por iniciar exec
sttesta3 Sep 7, 2024
fce4e38
SEPARACION EN LIBS
sttesta3 Sep 7, 2024
6809828
WIP: Parse y exec. OK: separacion en libs
sttesta3 Sep 7, 2024
f5e05ea
WIP: Dios que complejo
sttesta3 Sep 8, 2024
f81db0f
WIP: Arbol de expresiones binarias
sttesta3 Sep 8, 2024
d7540f7
WIP: Nuevo branch para simplificar
sttesta3 Sep 8, 2024
ef08de5
WIP: corrigiendo el arbol
sttesta3 Sep 8, 2024
b359e61
MOD: where simple sin relaciones complejas. TODO complejas
sttesta3 Sep 8, 2024
831f566
WIP gdb: SELECT * FROM clientes
sttesta3 Sep 8, 2024
2ce7a79
OK: SELECT * FROM
sttesta3 Sep 8, 2024
509a0cf
OK: Select columns FROM tabla
sttesta3 Sep 9, 2024
d092944
Corregido SELECT *
sttesta3 Sep 9, 2024
166c9cc
limpiando clippy
sttesta3 Sep 9, 2024
31183a8
SELECT last_column OK
sttesta3 Sep 9, 2024
c19cfa4
WIP gdb INSERT INTO
sttesta3 Sep 9, 2024
d12be3e
Edit README entrega
sttesta3 Sep 9, 2024
4e31d73
INSERT INTO DEBUGGED
sttesta3 Sep 9, 2024
f8d4b7e
WIP select WHERE
sttesta3 Sep 9, 2024
ee7f6f9
gdb OK SELECT * FROM
sttesta3 Sep 9, 2024
79e92e0
SELECT c/ WHERE
sttesta3 Sep 9, 2024
d6a3d39
WIP: Minor func para delete/update
sttesta3 Sep 10, 2024
39d8ea3
WIP DELETE
sttesta3 Sep 11, 2024
01893fd
DELETE CREA TMP FILE OK
sttesta3 Sep 11, 2024
cbf5ffc
DELETE OK
sttesta3 Sep 14, 2024
341592c
cargo fmt: DELETE OK
sttesta3 Sep 14, 2024
275db02
COMMIT PRE REFACTOR
sttesta3 Sep 14, 2024
4479650
query.columns to vec<usize>
sttesta3 Sep 14, 2024
1d5f935
OK: UPDATE clientes SET nombre = jose WHERE id = 9
sttesta3 Sep 14, 2024
f3728ec
fmtOK: UPDATE clientes SET nombre = jose WHERE id = 9
sttesta3 Sep 14, 2024
62b1b15
OK CLIPPY + FMT
sttesta3 Sep 15, 2024
a05a533
WIP: SORT BY
sttesta3 Sep 16, 2024
4b605fa
VUELVO A DESARROLLO
sttesta3 Sep 17, 2024
8703b52
gdb: SELECT * FROM ORDER BY
sttesta3 Sep 17, 2024
9fe9d5e
gdb: SORT BY. b search test OK
sttesta3 Sep 18, 2024
cb0cec7
gdb: ORDER BY. refactor line buffer to list
sttesta3 Sep 19, 2024
d1d541e
ORDER BY funciona, solo que compara por STRINGS
sttesta3 Sep 19, 2024
3a92606
OK order, WIP: Print output
sttesta3 Sep 21, 2024
47e7ffa
OK order by. Si campo vacio entonces es primero, quiza TODO
sttesta3 Sep 21, 2024
71269ab
Minor: Si no contiene columna de orden, entonces no imprimas nada
sttesta3 Sep 21, 2024
fcbcbc9
Minor bug: Imprimia coma al final de las lineas
sttesta3 Sep 21, 2024
f20e7df
FIN order by. funciona OK con buffers muy chiquitos y manejando vario…
sttesta3 Sep 21, 2024
de91654
README, clippy y format
sttesta3 Sep 21, 2024
c52f773
Merge pull request #3 from sttesta3/refactor
sttesta3 Sep 21, 2024
b651130
Minor: Explicacion pendientes en parseo
sttesta3 Sep 21, 2024
f30a8bb
COMMIT PARA REFACTOR
sttesta3 Sep 22, 2024
ec004e5
FIN CODE: Vector booleano
sttesta3 Sep 23, 2024
ca908ee
CODE OK: Funciones adaptadas
sttesta3 Sep 23, 2024
347452d
gdb OK: SELECT * FROM clientes WHERE id <= 8 AND id >= 4
sttesta3 Sep 23, 2024
1b005bb
OK: SELECT * FROM clientes WHERE id < 8 AND id > 4 OR nombre = Juan O…
sttesta3 Sep 23, 2024
fa2b421
OK: SELECT * FROM clientes WHERE AND AND AND AND
sttesta3 Sep 23, 2024
823beaf
FMT + Clippy 1 warning
sttesta3 Sep 23, 2024
f1b867d
Merge branch 'desarrollo_post_e1' into refactor
sttesta3 Sep 23, 2024
a93337d
Merge pull request #4 from sttesta3/refactor
sttesta3 Sep 23, 2024
f663419
WIP: doc
sttesta3 Sep 23, 2024
6a22baa
PEND DOC: Examples
sttesta3 Sep 24, 2024
50554c2
OK: SELECT ORDER BY s WHERE FMT CLIPPY + GitHub Actions
sttesta3 Sep 24, 2024
afafe59
OK: Print err y doc
sttesta3 Sep 25, 2024
7c9f667
Minor: Correcciones de prints y errores
sttesta3 Sep 25, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Ejercicio individual | (75.42) Taller de programación I

## Alumno: Testa Santiago Tomas ( 108301 )

### Detalles de entrega

Pendientes:

1. Testing (mas test unitarios e integración)

2. Documentación de funciones

3. Refactor de funciones para que tengan menos de 30 lineas. Por una cuestión de tiempos se deja para el final.

6. Terminar trabajo sobre el parseo ( TODOs & funcion para imprimir errores ). Se decide para poder avanzar con las funcionalidades implementar las mismas tal que, en caso de haber un error, simplemente no ejecutarán nada.

Funcionalidades probadas OK

1. SELECT

2. INSERT INTO

3. UPDATE

4. DELETE FROM

### Detalles de implementación

Para la logica del programa se decidio dividir en dos etapas: parseo y ejecucción. El punto del parseo es que se encuentre cualquier error previo a ejecucción del query, tal que no sea posible dañar la base de datos por error humano. De encontrarse un error se debe imprimir

Logica booleana: Se implemento por medio de un vector de vectores. Por cada OR se pushea un nuevo vector, donde en este vector se pushearán las expresiones simples y las negaciones ( los ANDs no son pusheados, ya que sería redundante ).

Esta implementación tiene como problema que un query con el condicional WHERE A AND AND AND {...} B resulta en WHERE A AND B. Como solución simple se planteó un chequeo en parseo que si se encuentra un condicional AND, se chequeará que el largo sea tal que el condicional sea válido, y que el proximo elemento no sea AND u OR.

Para la lógica booleana tambien se considero un arbol binario de expresiones booleanas (https://en.wikipedia.org/wiki/Binary_expression_tree). No se logró implementar debido a problemas con el manejo de memoria en Rust, aunque en mi opinión creo que es la mejor implementación posible.

Para en ORDER BY no cargar las tablas completas en memoria se eligió "Full external sort" (https://cs186berkeley.net/notes/note8/)
106 changes: 106 additions & 0 deletions src/condition.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
pub mod condition_type;
// pub mod complex_condition;
// use condition_type::BooleanOperator;
// use crate::libs::error;

use condition_type::ConditionOperator;

pub struct Condition {
pub condition: ConditionOperator,
pub column: Option<usize>,
pub value: Option<String>,
}

/// Constructor for not condition
pub fn build_not_condition() -> Condition {
Condition {
condition: ConditionOperator::Equal,
column: None,
value: None,
}
}

/// Constructor for general condition (simple expression, non boolean)
pub fn build_condition(column: usize, value: String, cond: ConditionOperator) -> Condition {
Condition {
condition: cond,
column: Some(column),
value: Some(value),
}
}

/// Returns string (or int if it's parseable as int) comparison
///
/// Pre: Strings and operator
/// Post: True if condition applies
pub fn operate_condition(v1: &String, v2: &String, operator: &ConditionOperator) -> bool {
if let Ok(x1) = v1.parse::<i32>() {
if let Ok(x2) = v2.parse::<i32>() {
match operator {
ConditionOperator::Minor => return x1 < x2,
ConditionOperator::MinorEqual => return x1 <= x2,
ConditionOperator::Equal => return x1 == x2,
ConditionOperator::Higher => return x1 > x2,
ConditionOperator::HigherEqual => return x1 >= x2,
}
};
};

match operator {
ConditionOperator::Minor => v1 < v2,
ConditionOperator::MinorEqual => v1 <= v2,
ConditionOperator::Equal => v1.eq(v2),
ConditionOperator::Higher => v1 > v2,
ConditionOperator::HigherEqual => v1 >= v2,
}
}

/// Returns the result of applying the condition to the lineW
///
/// Pre: Line to vec and condition (bool vector).
/// Post: Bool if condition applies or not
pub fn operate_full_condition(elements: &[String], condition: &[Vec<Condition>]) -> bool {
let mut or_valid = false;
let mut or_counter = 0;

let mut and_valid;
let mut and_counter;
let mut not_detected;

while or_counter < condition.len() && !or_valid {
and_valid = true;
and_counter = 0;
not_detected = false;
while and_counter < condition[or_counter].len() && and_valid {
match &condition[or_counter][and_counter].column {
None => not_detected = !not_detected,
Some(column) => match &condition[or_counter][and_counter].value {
None => return false,
Some(value) => {
if not_detected {
and_valid = !operate_condition(
&elements[*column],
value,
&condition[or_counter][and_counter].condition,
)
} else {
and_valid = operate_condition(
&elements[*column],
value,
&condition[or_counter][and_counter].condition,
);
}
}
},
}

and_counter += 1;
}

or_valid = and_valid;

or_counter += 1;
}

or_valid
}
133 changes: 133 additions & 0 deletions src/condition/complex_condition.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
use std::borrow::BorrowMut;

use crate::{libs::error::WHERE_MAL_FORMATEADO, query::Query};
use super::{condition_type::{self, ConditionOperator}, BooleanOperator, Condition};

pub struct ComplexCondition {
// Tree of complex conditions
pub operator: BooleanOperator,
pub left_cond: Option<Box<ComplexCondition>>, // Oldest condition ( first to be found )
pub left_simple: Option<Condition>,
pub right_cond: Option<Box<ComplexCondition>>, // Newest condition ( last to be found )
pub right_simple: Option<Condition>,
}

pub fn build_simple_condition(left: Option<Condition>) -> ComplexCondition {
ComplexCondition {
operator: BooleanOperator::I,
left_simple: left,

left_cond: None,
right_simple: None,
right_cond: None,
}
}

pub fn build_complex_condition(op: BooleanOperator, left: Option<Box<ComplexCondition>>, right: Option<Box<ComplexCondition>>) -> ComplexCondition {
ComplexCondition {
operator: op,
left_cond: left,
right_cond: right,

left_simple: None,
right_simple: None
}
}

pub fn tree_check(root: &ComplexCondition) -> bool {
// In Order valid check ( no None leafs )
match &root.operator {
BooleanOperator::OR => tree_check_or_and(&root),
BooleanOperator::AND => tree_check_or_and(&root),
BooleanOperator::NOT => tree_check_not_i(&root),
BooleanOperator::I => tree_check_not_i(&root)
}
}

fn tree_check_or_and(root: &ComplexCondition) -> bool {
match &root.left_cond {
Some(left) => {
match &root.right_cond {
Some(right) => return tree_check(&*left) && tree_check(&*right),
None => return false
}
},
None => return false
}
}

fn tree_check_not_i(root: &ComplexCondition) -> bool {
match &root.left_cond {
Some(left) => {
match root.right_cond {
Some(_) => return false,
None => return tree_check(&*left)
}
},
None => return false
}
}

pub fn add_node_to_tree(mut new_node: ComplexCondition, root: &mut ComplexCondition) -> Result<ComplexCondition,u32> {
// Pre: Previous root and new node
// Post: If success new root, else Error
if check_precedence(&new_node.operator, &root.operator) { // IM new root
new_node.left_cond = Some(Box::new(*root));
Ok(new_node)
} else if root.left_cond.is_none() { // IM RIGHT SON
Err(WHERE_MAL_FORMATEADO)
} else {
match root.right_cond.as_deref() {
Some(mut x) => add_node_to_tree(new_node, x.borrow_mut()),
None => {
root.right_cond = Some(Box::new(new_node));
return Ok(*root)
}
}
}
}

fn check_valid_args_for_basic_condition(args: &Vec<String>, start_position: usize) -> bool {
if start_position + 3 > args.len() {
false
} else {
let first = &args[start_position];
let second = &args[start_position + 1];
let third = &args[start_position + 2];

if first.eq("AND") || first.eq("OR") || first.eq("NOT") {
false
} else if second.eq("AND") || second.eq("OR") || second.eq("NOT") {
false
} else if ! ( second.eq(">") || second.eq(">=") || second.eq("=") || second.eq("<") || second.eq("<=") ) {
false
} else if third.eq("AND") || third.eq("OR") || third.eq("NOT") {
false
} else {
true
}
}
}

pub fn check_precedence(op1: &BooleanOperator, op2: &BooleanOperator) -> bool {
// Pre: Operators
// Post: True if it's higher on the tree, false if not
match op1 {
BooleanOperator::OR => true,
BooleanOperator::AND => {
if *op2 == BooleanOperator::OR {
false
} else {
true
}
},
BooleanOperator::NOT => {
if *op2 == BooleanOperator::OR || *op2 == BooleanOperator::AND {
false
} else {
true
}
},
BooleanOperator::I => false,
}
}
23 changes: 23 additions & 0 deletions src/condition/condition_type.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
pub enum ConditionOperator {
Minor,
MinorEqual,
Equal,
Higher,
HigherEqual,
}

pub enum BooleanOperator {
AND,
OR,
NOT, // NOT. Left child
I, // identity.
}

/*
impl PartialEq for BooleanOperator {
fn eq(&self, other: &Self) -> bool {
self == other
}
}
impl Eq for BooleanOperator {}
*/
4 changes: 4 additions & 0 deletions src/libs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Dumb file for organize everything into libs
pub mod error;
pub mod exec;
pub mod parsing;
Loading