186 lines
5.7 KiB
C++
186 lines
5.7 KiB
C++
#include "parser.h"
|
|
#include "usql.h"
|
|
|
|
#include "linenoise.h"
|
|
|
|
// https://dev.to/joaoh82/what-would-sqlite-look-like-if-written-in-rust-part-1-2np4
|
|
|
|
using namespace std::chrono;
|
|
|
|
const std::vector<std::string> commands {
|
|
"select", "create", "load", "table"
|
|
};
|
|
|
|
std::string get_history_file_dir() {
|
|
std::string file{"/.usql_history.txt"};
|
|
const char *t = std::getenv("HOME");
|
|
|
|
if (t == nullptr) return "/tmp/" + file;
|
|
else return std::string{t} + "/" + file;
|
|
}
|
|
|
|
|
|
size_t last_token_index( std::string str ) {
|
|
// remove trailing white space
|
|
while( !str.empty() && std::isspace( str.back() ) ) str.pop_back() ;
|
|
|
|
// locate the last white space
|
|
return str.find_last_of( "() \t\n" ) ;
|
|
}
|
|
|
|
|
|
void completion(const char *buf, linenoiseCompletions *lc) {
|
|
if (buf != nullptr) {
|
|
std::string str{buf};
|
|
|
|
const auto pos = last_token_index(str);
|
|
if (pos == std::string::npos)
|
|
return; // cannot find what to complete
|
|
|
|
std::string token = str.substr(pos+1);
|
|
std::string begining = str.substr(0, pos+1);
|
|
|
|
for (auto t = commands.begin(); t != commands.end(); ++t) {
|
|
if(t->find(token) == 0) {
|
|
std::string completion_string = begining + *t;
|
|
linenoiseAddCompletion(lc, completion_string.c_str());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
char *hints(const char *buf, int *color, int *bold) {
|
|
// if (!strcasecmp(buf,"hello")) {
|
|
// *color = 35;
|
|
// *bold = 0;
|
|
// return " World";
|
|
// }
|
|
return nullptr;
|
|
}
|
|
|
|
|
|
void setup_linenoise() {
|
|
std::string history_file = get_history_file_dir();
|
|
|
|
linenoiseHistorySetMaxLen(500);
|
|
linenoiseSetCompletionCallback(completion);
|
|
linenoiseSetHintsCallback(hints);
|
|
linenoiseSetMultiLine(1);
|
|
linenoiseHistoryLoad(history_file.c_str());
|
|
}
|
|
|
|
void linenoise_line_read(char *line) {
|
|
linenoiseHistoryAdd(line);
|
|
}
|
|
|
|
void close_linenoise() {
|
|
std::string history_file = get_history_file_dir();
|
|
|
|
linenoiseHistorySave(history_file.c_str());
|
|
}
|
|
|
|
void repl() {
|
|
std::string code;
|
|
std::string input;
|
|
|
|
setup_linenoise();
|
|
|
|
usql::USql uSql{};
|
|
|
|
|
|
while (true) {
|
|
char *line = linenoise(">>> ");
|
|
if (line == nullptr) break;
|
|
|
|
linenoise_line_read(line);
|
|
|
|
input = std::string(line);
|
|
|
|
if (input == "!quit" || input == "!q")
|
|
break;
|
|
else if (input == "!export" || input == "!x") {
|
|
std::cout << "File to export to: ";
|
|
std::getline(std::cin, input);
|
|
|
|
//write_file_contents(input, code);
|
|
} else if (input != "") {
|
|
try {
|
|
time_point<high_resolution_clock> start_time = high_resolution_clock::now();
|
|
auto result = uSql.execute(input);
|
|
time_point<high_resolution_clock> end_time = high_resolution_clock::now();
|
|
|
|
std::cout << input << std::endl;
|
|
std::cout << "run time: " << duration_cast<milliseconds>(end_time - start_time).count() << " ms " << std::endl <<std::endl;
|
|
|
|
result->print();
|
|
|
|
code += input + "\n";
|
|
} catch (std::exception &e) {
|
|
std::cerr << e.what() << std::endl;
|
|
}
|
|
}
|
|
}
|
|
|
|
close_linenoise();
|
|
}
|
|
|
|
int main(int argc, char *argv[]) {
|
|
std::vector<std::string> sql_commands{
|
|
"create table a (i integer not null, s varchar(64), f float null)",
|
|
"insert into a (i, s) values(1, upper('one'))",
|
|
// "update table a set s = 'null string aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'",
|
|
// "update table a set i = null",
|
|
"insert into a (i, s) values(2, 'two')",
|
|
"insert into a (i, s) values(3, 'two')",
|
|
"insert into a (i, s) values(4, lower('FOUR'))",
|
|
"insert into a (i, s) values(5, 'five')",
|
|
"insert into a (i, s) values(to_date('20.12.1973', '%d.%m.%Y'), 'six')",
|
|
"save table a into '/tmp/a.csv'",
|
|
"select i, s from a where i > 2 order by 1 desc offset 1 limit 1",
|
|
"select distinct s from a",
|
|
// "select i, s from a where i = 1",
|
|
// "select i, s from a where s = 'two'",
|
|
// "select i, s from a where i <= 3 and s = 'one'",
|
|
// "select i, s from a where i > 0",
|
|
"delete from a where i = 4",
|
|
// "select i, s from a where i > 0",
|
|
// "update a set f = 9.99 where i = 3",
|
|
// "select i, s, f from a where i = 3",
|
|
// "update a set s = 'three', f = f + 0.01 where i = 3",
|
|
// "select i, s, f from a where i = 3",
|
|
// "create table data (ticker varchar(8), price float null)",
|
|
// "load data from '/Users/vaclavt/Library/Mobile Documents/com~apple~CloudDocs/Development/usql/data.csv')",
|
|
// "select ticker, price from data",
|
|
// "select i, s, f from a where i < 300",
|
|
// "create table x as select i, s, f from a where i < 300",
|
|
// "select i, s, f from x where i < 300",
|
|
// "drop table x",
|
|
// "select i, s, f from a where i > 300",
|
|
// "select i, to_string(i, '%d.%m.%Y'), s, f from a where i > 300",
|
|
"create table prices (datetime integer, symbol varchar(8), prev_close float, open float, price float, change float, change_prct varchar(16))",
|
|
"load prices from '/Users/vaclavt/Library/Mobile Documents/com~apple~CloudDocs/Development/usql/prices.csv'",
|
|
// "insert into prices (datetime, symbol, prev_close, open, price, change, change_prct) values (1626979443, 'MPC', 54.08, 53.82, 53.63, -0.832101, '-0.83 %')",
|
|
"select to_string(datetime, '%d.%m.%Y %H:%M:%S'), symbol, prev_close, open, price, change, change_prct, datetime from prices where symbol = 'SYF' order by 8 desc limit 10"
|
|
};
|
|
|
|
|
|
usql::USql uSql{};
|
|
|
|
for (auto command : sql_commands) {
|
|
time_point<high_resolution_clock> start_time = high_resolution_clock::now();
|
|
auto result = uSql.execute(command);
|
|
time_point<high_resolution_clock> end_time = high_resolution_clock::now();
|
|
|
|
std::cout << command << std::endl;
|
|
std::cout << "run time: " << duration_cast<milliseconds>(end_time - start_time).count() << " ms " << std::endl <<std::endl;
|
|
|
|
result->print();
|
|
}
|
|
|
|
std::cout << std::endl << std::endl;
|
|
|
|
repl();
|
|
|
|
return 0;
|
|
}
|