-
Notifications
You must be signed in to change notification settings - Fork 0
/
statement.cpp
81 lines (68 loc) · 2.33 KB
/
statement.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include "statement.h"
#include <stdexcept>
/**
* Esegue direttamente il parsing della stringa di input.
* TODO: la generazione delle eccezioni deve avvenire secondo la regola RAII...
*/
Statement::Statement(const std::string& input)
: lexer{input}
{
if(lexer.get().type != Token_type::SELECT) {
throw std::logic_error("Statement::construct(): SELECT expected!");
}
expression(); //* Attenzione: si mangia un token in più. Il token successivo è gia in pancia al Lexer!
if(lexer.current().type != Token_type::end) {
throw std::logic_error{"Statement::construct(): end of input expected!"};
}
}
/**
* *Attenzione: si mangia un token in più!
* TODO: si dovrebbe restituire, in caso di SELECT_SINGLE, il token che ha mangiato in più...
* TODO: si potrebbe rimettere nello stream l'intero token che si è mangiato in più...
*/
void Statement::expression() {
start_id = id();
if(lexer.get().type == Token_type::RANGE_OPERATOR) {
statement_type = Type::SELECT_RANGE;
end_id = id();
lexer.get(); //! devo comunque mangiare un token in più come già avviene nel caso in cui la condizione dell'if() sia falsa
}
else {
statement_type = Type::SELECT_SINGLE;
}
}
/**
* Si aspetta semplicemente un intero positivo.
*/
int Statement::id() {
if(lexer.get().type == Token_type::POSITIVE_INTEGER) {
return std::stoi(lexer.current().value);
}
else {
throw std::logic_error{"Statement::id(): expected POSITIVE INTEGER!"};
}
}
/**
* Esegue la query in base a come il parser ha modificato la rappresentazione di Statement.
* Se non viene trovato alcun risultato, viene restituito un std::vector vuoto.
*/
std::vector<Record> Statement::execute(Database& database) {
if(statement_type == Type::SELECT_SINGLE) {
Cursor res = database.search(start_id);
return (res) ? std::vector{*res.record} : std::vector<Record>(0);
}
else { //Type::SELECT_RANGE
auto range = database.search(start_id, end_id);
if(!range.first) { //se non trovato
return std::vector<Record>(0);
}
std::vector<Record> results(range.first.diff(range.second) + 1);
int i{0}; //TODO: puoi farlo meglio
while(range.first != range.second) {
results[i++] = *range.first.record;
++range.first;
}
results[i] = *range.first.record; //quindi inseriamo anche l'ultimo record
return results;
}
}