code changes in load
This commit is contained in:
parent
cd92e27270
commit
e53d062ff5
|
|
@ -2,3 +2,5 @@ build
|
||||||
cmake-build-debug
|
cmake-build-debug
|
||||||
.DS_Store
|
.DS_Store
|
||||||
tmp/.idea
|
tmp/.idea
|
||||||
|
Makefile
|
||||||
|
localhost.session.sql
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
|
|
||||||
### TODO
|
### TODO
|
||||||
- command line interface
|
|
||||||
- date functions - now, add_date...
|
- date functions - now, add_date...
|
||||||
- add pipe | token
|
|
||||||
- string functions rtrim, ltrim, rpad, lpad
|
- string functions rtrim, ltrim, rpad, lpad
|
||||||
|
- add pipe | concatenation
|
||||||
- support for order by, offset, limit (allow column name in order by, validate)
|
- support for order by, offset, limit (allow column name in order by, validate)
|
||||||
|
- command line interface
|
||||||
- support for uniqueue indexes (primary key)
|
- support for uniqueue indexes (primary key)
|
||||||
- support for btree indexes
|
- support for btree indexes
|
||||||
- add count min and max functions, eg aggregate functions
|
- add count min and max functions, eg aggregate functions
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,9 @@
|
||||||
#include "csvreader.h"
|
#include "csvreader.h"
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
|
||||||
namespace usql {
|
namespace usql {
|
||||||
|
|
||||||
CsvReader::CsvReader(bool skip_hdr, char field_sep, char quote_ch, char line_sep, char line_sep2) {
|
CsvReader::CsvReader(bool skip_hdr, char field_sep, char quote_ch, char line_sep, char line_sep2) {
|
||||||
|
|
@ -14,8 +17,67 @@ namespace usql {
|
||||||
header_skiped = !skip_hdr;
|
header_skiped = !skip_hdr;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CsvReader::parseCSV2(const std::string &csvSource, std::vector<ColDefNode> &cols_def,
|
|
||||||
void (Table::*function)(const std::vector<ColDefNode>&, const std::vector<std::string>&), Table& a) {
|
int CsvReader::parseCSV(const std::string &filename, std::vector<ColDefNode> &cols_def, Table& table) {
|
||||||
|
|
||||||
|
std::vector<ColDefNode> cdefs;
|
||||||
|
cdefs.reserve(cols_def.size());
|
||||||
|
for(auto & cd : cols_def) {
|
||||||
|
cdefs.emplace_back(table.get_column_def(cd.name));
|
||||||
|
}
|
||||||
|
|
||||||
|
int row_cnt = 0;
|
||||||
|
bool inQuote(false);
|
||||||
|
std::string field;
|
||||||
|
std::string csvSource;
|
||||||
|
|
||||||
|
std::vector<std::string> line;
|
||||||
|
line.reserve(32);
|
||||||
|
|
||||||
|
std::fstream newfile;
|
||||||
|
newfile.open(filename, std::ios::in);
|
||||||
|
/// if (newfile.is_open()){ //checking whether the file is open
|
||||||
|
|
||||||
|
while(getline(newfile, csvSource)){
|
||||||
|
if (skip_header && !header_skiped) {
|
||||||
|
header_skiped = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
std::string::const_iterator aChar = csvSource.begin();
|
||||||
|
while (aChar != csvSource.end()) {
|
||||||
|
if (*aChar == quote_character) {
|
||||||
|
inQuote = !inQuote;
|
||||||
|
} else if (*aChar == field_separator) {
|
||||||
|
if (inQuote == true) {
|
||||||
|
field += *aChar;
|
||||||
|
} else {
|
||||||
|
line.push_back(field);
|
||||||
|
field.clear();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
field.push_back(*aChar);
|
||||||
|
}
|
||||||
|
|
||||||
|
aChar++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!field.empty())
|
||||||
|
line.push_back(field);
|
||||||
|
|
||||||
|
table.create_row_from_vector(cols_def, line);
|
||||||
|
row_cnt++;
|
||||||
|
|
||||||
|
field.clear();
|
||||||
|
line.clear();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
newfile.close();
|
||||||
|
|
||||||
|
return row_cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CsvReader::parseCSV2(const std::string &csvSource, std::vector<ColDefNode> &cols_def, Table& table) {
|
||||||
int row_cnt = 0;
|
int row_cnt = 0;
|
||||||
bool inQuote(false);
|
bool inQuote(false);
|
||||||
bool newLine(false);
|
bool newLine(false);
|
||||||
|
|
@ -44,7 +106,7 @@ namespace usql {
|
||||||
if (newLine == false) {
|
if (newLine == false) {
|
||||||
line.push_back(field);
|
line.push_back(field);
|
||||||
if (header_skiped) {
|
if (header_skiped) {
|
||||||
(a.*function)(cols_def, line);
|
table.create_row_from_vector(cols_def, line);
|
||||||
row_cnt++;
|
row_cnt++;
|
||||||
}
|
}
|
||||||
header_skiped = true;
|
header_skiped = true;
|
||||||
|
|
@ -64,7 +126,7 @@ namespace usql {
|
||||||
if (!field.empty()) line.push_back(field);
|
if (!field.empty()) line.push_back(field);
|
||||||
|
|
||||||
if (header_skiped) {
|
if (header_skiped) {
|
||||||
(a.*function)(cols_def, line);
|
table.create_row_from_vector(cols_def, line);
|
||||||
row_cnt++;
|
row_cnt++;
|
||||||
header_skiped = true;
|
header_skiped = true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,9 @@ namespace usql {
|
||||||
public:
|
public:
|
||||||
CsvReader(bool skip_hdr = true, char field_sep = ',', char quote_ch = '"', char line_sep = '\r', char line_sep2 = '\n');
|
CsvReader(bool skip_hdr = true, char field_sep = ',', char quote_ch = '"', char line_sep = '\r', char line_sep2 = '\n');
|
||||||
|
|
||||||
int parseCSV2(const std::string &csvSource, std::vector<ColDefNode> &cols_def,
|
int parseCSV2(const std::string &csvSource, std::vector<ColDefNode> &cols_def, Table& table);
|
||||||
void (Table::*function)(const std::vector<ColDefNode>&, const std::vector<std::string>&), Table& a);
|
|
||||||
|
int parseCSV(const std::string &filename, std::vector<ColDefNode> &cols_def, Table& table);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
66
main.cpp
66
main.cpp
|
|
@ -129,37 +129,39 @@ int main(int argc, char *argv[]) {
|
||||||
// "create table ticker ( tablee varchar(5) not null, permaticker integer, ticker varchar(10) not null, name varchar(256) not null, exchange varchar(32), isdelisted boolean, category varchar(32), cusips varchar(256), siccode integer, sicsector varchar(256), sicindustry varchar(256), famasector varchar(256), famaindustry varchar(256), sector varchar(128), industry varchar(128), scalemarketcap varchar(64), scalerevenue varchar(64), relatedtickers varchar(128), currency varchar(3), location varchar(64), lastupdated date, firstadded date, firstpricedate date, lastpricedate date, firstquarter date, lastquarter date, secfilings varchar(256), companysite varchar(256))",
|
// "create table ticker ( tablee varchar(5) not null, permaticker integer, ticker varchar(10) not null, name varchar(256) not null, exchange varchar(32), isdelisted boolean, category varchar(32), cusips varchar(256), siccode integer, sicsector varchar(256), sicindustry varchar(256), famasector varchar(256), famaindustry varchar(256), sector varchar(128), industry varchar(128), scalemarketcap varchar(64), scalerevenue varchar(64), relatedtickers varchar(128), currency varchar(3), location varchar(64), lastupdated date, firstadded date, firstpricedate date, lastpricedate date, firstquarter date, lastquarter date, secfilings varchar(256), companysite varchar(256))",
|
||||||
// "load ticker from '/Users/vaclavt/Library/Mobile Documents/com~apple~CloudDocs/Development/usql/tickers.csv')",
|
// "load ticker from '/Users/vaclavt/Library/Mobile Documents/com~apple~CloudDocs/Development/usql/tickers.csv')",
|
||||||
// "select * from ticker where ticker = 'WFC' and tablee = 'SF1'",
|
// "select * from ticker where ticker = 'WFC' and tablee = 'SF1'",
|
||||||
"set 'DATE_FORMAT' = '%Y-%m-%d'",
|
// "set 'DATE_FORMAT' = '%Y-%m-%d'",
|
||||||
"show 'DATE_FORMAT'",
|
// "show 'DATE_FORMAT'",
|
||||||
"create table sf1 ( ticker varchar(8), dimension varchar(3), calendar_date date, date_key date, report_period date, last_updated date, accoci float, assets float, assetsavg float, assetsc float, assetsnc float, assetturnover float, bvps float, capex float, cashneq float, cashnequsd float, cor float, consolinc float, currentratio float, de float, debt float, debtc float, debtnc float, debtusd float, deferredrev float, depamor float, deposits float, divyield float, dps float, ebit float, ebitda float, ebitdamargin float, ebitdausd float, ebitusd float, ebt float, eps float, epsdil float, epsusd float, equity float, equityavg float, equityusd float, ev float, evebit float, evebitda float, fcf float, fcfps float, fxusd float, gp float, grossmargin float, intangibles float, intexp float, invcap float, invcapavg float, inventory float, investments float, investmentsc float, investmentsnc float, liabilities float, liabilitiesc float, liabilitiesnc float, marketcap float, ncf float, ncfbus float, ncfcommon float, ncfdebt float, ncfdiv float, ncff float, ncfi float, ncfinv float, ncfo float, ncfx float, netinc float, netinccmn float, netinccmnusd float, netincdis float, netincnci float, netmargin float, opex float, opinc float, payables float, payoutratio float, pb float, pe float, pe1 float, ppnenet float, prefdivis float, price float, ps float, ps1 float, receivables float, retearn float, revenue float, revenueusd float, rnd float, roa float, roe float, roic float, ros float, sbcomp float, sgna float, sharefactor float, sharesbas float, shareswa float, shareswadil float, sps float, tangibles float, taxassets float, taxexp float, taxliabilities float, tbvps float, workingcapital float)",
|
// "create table sf1 ( ticker varchar(8), dimension varchar(3), calendar_date date, date_key date, report_period date, last_updated date, accoci float, assets float, assetsavg float, assetsc float, assetsnc float, assetturnover float, bvps float, capex float, cashneq float, cashnequsd float, cor float, consolinc float, currentratio float, de float, debt float, debtc float, debtnc float, debtusd float, deferredrev float, depamor float, deposits float, divyield float, dps float, ebit float, ebitda float, ebitdamargin float, ebitdausd float, ebitusd float, ebt float, eps float, epsdil float, epsusd float, equity float, equityavg float, equityusd float, ev float, evebit float, evebitda float, fcf float, fcfps float, fxusd float, gp float, grossmargin float, intangibles float, intexp float, invcap float, invcapavg float, inventory float, investments float, investmentsc float, investmentsnc float, liabilities float, liabilitiesc float, liabilitiesnc float, marketcap float, ncf float, ncfbus float, ncfcommon float, ncfdebt float, ncfdiv float, ncff float, ncfi float, ncfinv float, ncfo float, ncfx float, netinc float, netinccmn float, netinccmnusd float, netincdis float, netincnci float, netmargin float, opex float, opinc float, payables float, payoutratio float, pb float, pe float, pe1 float, ppnenet float, prefdivis float, price float, ps float, ps1 float, receivables float, retearn float, revenue float, revenueusd float, rnd float, roa float, roe float, roic float, ros float, sbcomp float, sgna float, sharefactor float, sharesbas float, shareswa float, shareswadil float, sps float, tangibles float, taxassets float, taxexp float, taxliabilities float, tbvps float, workingcapital float)",
|
||||||
"load sf1 from '/tmp/sf1.csv')",
|
// "load sf1 from '/tmp/sf1.csv')",
|
||||||
"select * from sf1 where ticker = 'WFC'"
|
// "select * from sf1 where ticker = 'WFC'",
|
||||||
// "select * from sf1 limit 10"
|
// "select ticker, dimension, calendar_date, eps, dps from sf1 where (ticker = 'AIG' or ticker = 'AI') and dimension = 'MRY' order by 3 desc",
|
||||||
// "create table a (i integer not null, s varchar(64), f float null, d date null, b boolean)",
|
// "select ticker, dimension, calendar_date, eps, dps from sf1 where (ticker = 'AIG' or ticker = 'AI') and (dimension = 'MRY' or dimension = 'MRQ') order by 3 desc",
|
||||||
// "insert into a (i, s, b) values(1, upper('one'), 'Y')",
|
// "select ticker, dimension, calendar_date, eps, dps from sf1 where (ticker = 'AIG' or ticker = 'WFC') and dimension = 'MRY' order by 3 desc",
|
||||||
// "select i, s, b from a where i >=1 order by 1 desc offset 0 limit 1",
|
"create table a (i integer not null, s varchar(64), f float null, d date null, b boolean)",
|
||||||
|
"insert into a (i, s, b) values(1, upper('one'), 'Y')",
|
||||||
|
"select i+2, s, b from a where i >=1 order by 1 desc offset 0 limit 1",
|
||||||
// "update table a set s = 'null string aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'",
|
// "update table a set s = 'null string aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'",
|
||||||
// "update table a set i = null",
|
"update table a set i = null",
|
||||||
// "insert into a (i, s) values(2, 'two')",
|
"insert into a (i, s) values(2, 'two')",
|
||||||
// "insert into a (i, s) values(3, 'two')",
|
"insert into a (i, s) values(3, 'two')",
|
||||||
// "insert into a (i, s) values(4, lower('FOUR'))",
|
"insert into a (i, s) values(4, lower('FOUR'))",
|
||||||
// "insert into a (i, s) values(5, 'five')",
|
"insert into a (i, s) values(5, 'five')",
|
||||||
// "insert into a (i, s) values(to_date('20.12.1973', '%d.%m.%Y'), 'six')",
|
"insert into a (i, s) values(to_date('20.12.1973', '%d.%m.%Y'), 'six')",
|
||||||
// tohle zpusobi kresh "insert into a (i, d) values(6', '2006-10-04')",
|
// tohle zpusobi kresh "insert into a (i, d) values(6', '2006-10-04')",
|
||||||
// "insert into a (i, d) values(6, '2006-10-04')",
|
"insert into a (i, d) values(6, '2006-10-04')",
|
||||||
// "save table a into '/tmp/a.csv'",
|
"save table a into '/tmp/a.csv'",
|
||||||
// "select i, s from a where i > 2 order by 1 desc offset 1 limit 1",
|
"select i, s from a where i > 2 order by 1 desc offset 1 limit 1",
|
||||||
// "select distinct s, d from a",
|
"select distinct s, d from a",
|
||||||
// "select i, s from a where i = 1",
|
"select i, s from a where i = 1",
|
||||||
// "select i, s from a where s = 'two'",
|
"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 <= 3 and s = 'one'",
|
||||||
// "select i, s from a where i > 0",
|
"select i, s from a where i > 0",
|
||||||
// "delete from a where i = 4",
|
"delete from a where i = 4",
|
||||||
// "select i, s from a where i > 0",
|
"select i, s from a where i > 0",
|
||||||
// "update a set f = 9.99 where i = 3",
|
"update a set f = 9.99 where i = 3",
|
||||||
// "select i, s, f from a where i = 3",
|
"select i, s, f from a where i = 3",
|
||||||
// "update a set s = 'three', f = f + 0.01 where i = 3",
|
"update a set s = 'three', f = f + 0.01 where i = 3",
|
||||||
// "select i, s, f from a where i = 3",
|
"select i, s, f from a where i = 3",
|
||||||
// "create table data (ticker varchar(8), price float null)",
|
// "create table data (ticker varchar(8), price float null)",
|
||||||
// "load data from '/Users/vaclavt/Library/Mobile Documents/com~apple~CloudDocs/Development/usql/data.csv')",
|
// "load data from '/Users/vaclavt/Library/Mobile Documents/com~apple~CloudDocs/Development/usql/data.csv')",
|
||||||
// "select ticker, price from data",
|
// "select ticker, price from data",
|
||||||
|
|
@ -175,7 +177,6 @@ int main(int argc, char *argv[]) {
|
||||||
// "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"
|
// "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{};
|
usql::USql uSql{};
|
||||||
|
|
||||||
for (const auto &command : sql_commands) {
|
for (const auto &command : sql_commands) {
|
||||||
|
|
@ -184,14 +185,15 @@ int main(int argc, char *argv[]) {
|
||||||
time_point<high_resolution_clock> end_time = high_resolution_clock::now();
|
time_point<high_resolution_clock> end_time = high_resolution_clock::now();
|
||||||
|
|
||||||
std::cout << command << std::endl;
|
std::cout << command << std::endl;
|
||||||
std::cout << "run time: " << duration_cast<milliseconds>(end_time - start_time).count() << " ms " << std::endl <<std::endl;
|
std::cout << "run time: " << duration_cast<milliseconds>(end_time - start_time).count() << " ms "
|
||||||
|
<< std::endl << std::endl;
|
||||||
|
|
||||||
result->print();
|
result->print();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << std::endl << std::endl;
|
std::cout << std::endl << std::endl;
|
||||||
|
|
||||||
repl();
|
// repl();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
103
parser.cpp
103
parser.cpp
|
|
@ -318,12 +318,10 @@ namespace usql {
|
||||||
ArithmeticalOperatorType op = parse_arithmetical_operator();
|
ArithmeticalOperatorType op = parse_arithmetical_operator();
|
||||||
std::unique_ptr<Node> right = Parser::parse_operand_node();
|
std::unique_ptr<Node> right = Parser::parse_operand_node();
|
||||||
|
|
||||||
values.push_back(std::make_unique<ArithmeticalOperatorNode>(op, std::move(left),
|
values.push_back(std::make_unique<ArithmeticalOperatorNode>(op, std::move(left), std::move(right)));
|
||||||
std::move(right)));
|
|
||||||
} else {
|
} else {
|
||||||
std::unique_ptr<Node> right = std::make_unique<IntValueNode>(0);
|
std::unique_ptr<Node> right = std::make_unique<IntValueNode>(0);
|
||||||
values.push_back(
|
values.push_back(std::make_unique<ArithmeticalOperatorNode>(ArithmeticalOperatorType::copy_value,
|
||||||
std::make_unique<ArithmeticalOperatorNode>(ArithmeticalOperatorType::copy_value,
|
|
||||||
std::move(left), std::move(right)));
|
std::move(left), std::move(right)));
|
||||||
}
|
}
|
||||||
m_lexer.skipTokenOptional(TokenType::comma);
|
m_lexer.skipTokenOptional(TokenType::comma);
|
||||||
|
|
@ -335,26 +333,6 @@ namespace usql {
|
||||||
return std::make_unique<UpdateTableNode>(table_name, cols_names, std::move(values), std::move(where_node));
|
return std::make_unique<UpdateTableNode>(table_name, cols_names, std::move(values), std::move(where_node));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Node> Parser::parse_where_clause() {
|
|
||||||
if (m_lexer.tokenType() != TokenType::keyword_where) {
|
|
||||||
return std::make_unique<TrueNode>();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<Node> node;
|
|
||||||
m_lexer.skipToken(TokenType::keyword_where);
|
|
||||||
do {
|
|
||||||
node = parse_relational_expression();
|
|
||||||
|
|
||||||
if (Lexer::isLogicalOperator(m_lexer.tokenType())) {
|
|
||||||
auto operation = parse_logical_operator();
|
|
||||||
std::unique_ptr<Node> node2 = parse_relational_expression();
|
|
||||||
node = std::make_unique<LogicalOperatorNode>(operation, std::move(node), std::move(node2));
|
|
||||||
}
|
|
||||||
} while (m_lexer.tokenType() != TokenType::eof && m_lexer.tokenType() != TokenType::keyword_order);
|
|
||||||
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
std::vector<ColOrderNode> Parser::parse_order_by_clause() {
|
std::vector<ColOrderNode> Parser::parse_order_by_clause() {
|
||||||
std::vector<ColOrderNode> order_cols;
|
std::vector<ColOrderNode> order_cols;
|
||||||
|
|
@ -419,17 +397,64 @@ namespace usql {
|
||||||
return OffsetLimitNode{offset, limit};
|
return OffsetLimitNode{offset, limit};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Node> Parser::parse_relational_expression() {
|
|
||||||
auto left = parse_operand_node();
|
std::unique_ptr<Node> Parser::parse_where_clause() {
|
||||||
|
if (m_lexer.tokenType() != TokenType::keyword_where) {
|
||||||
|
return std::make_unique<TrueNode>();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_lexer.skipToken(TokenType::keyword_where);
|
||||||
|
|
||||||
|
std::unique_ptr<Node> left = parse_expression();
|
||||||
|
do {
|
||||||
|
left = parse_expression(std::move(left));
|
||||||
|
|
||||||
|
} while (m_lexer.tokenType() != TokenType::eof && m_lexer.tokenType() != TokenType::keyword_order && m_lexer.tokenType() != TokenType::keyword_offset && m_lexer.tokenType() != TokenType::keyword_limit);
|
||||||
|
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Node> Parser::parse_expression() {
|
||||||
|
std::unique_ptr<Node> left = parse_operand_node();
|
||||||
|
|
||||||
|
return parse_expression(std::move(left));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Node> Parser::parse_expression(std::unique_ptr<Node> left) {
|
||||||
|
if (Lexer::isRelationalOperator(m_lexer.tokenType())) {
|
||||||
auto operation = parse_relational_operator();
|
auto operation = parse_relational_operator();
|
||||||
auto right = parse_operand_node();
|
auto right = parse_operand_node();
|
||||||
|
|
||||||
return std::make_unique<RelationalOperatorNode>(operation, std::move(left), std::move(right));
|
return std::make_unique<RelationalOperatorNode>(operation, std::move(left), std::move(right));
|
||||||
|
} else if (Lexer::isLogicalOperator(m_lexer.tokenType())) {
|
||||||
|
auto operation = parse_logical_operator();
|
||||||
|
auto right = parse_expression();
|
||||||
|
return std::make_unique<LogicalOperatorNode>(operation, std::move(left), std::move(right));
|
||||||
|
} else if (Lexer::isArithmeticalOperator(m_lexer.tokenType())) {
|
||||||
|
auto operation = parse_arithmetical_operator();
|
||||||
|
auto right = parse_operand_node();
|
||||||
|
|
||||||
|
return std::make_unique<ArithmeticalOperatorNode>(operation, std::move(left), std::move(right));
|
||||||
|
} else if (m_lexer.tokenType() == TokenType::int_number || m_lexer.tokenType() == TokenType::double_number ||m_lexer.tokenType() == TokenType::string_literal ||m_lexer.tokenType() == TokenType::identifier || m_lexer.tokenType() == TokenType::keyword_null || m_lexer.tokenType() == TokenType::open_paren) {
|
||||||
|
return parse_operand_node();
|
||||||
|
}
|
||||||
|
|
||||||
|
return left;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Node> Parser::parse_operand_node() {
|
std::unique_ptr<Node> Parser::parse_operand_node() {
|
||||||
// while not end or order or limit
|
|
||||||
auto token_type = m_lexer.tokenType();
|
auto token_type = m_lexer.tokenType();
|
||||||
|
|
||||||
|
if (token_type == TokenType::open_paren) {
|
||||||
|
m_lexer.skipToken(TokenType::open_paren);
|
||||||
|
auto left = parse_expression();
|
||||||
|
do {
|
||||||
|
left = parse_expression(std::move(left));
|
||||||
|
} while (m_lexer.tokenType() != TokenType::close_paren && m_lexer.tokenType() != TokenType::eof);
|
||||||
|
|
||||||
|
m_lexer.skipToken(TokenType::close_paren);
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
std::string tokenString = m_lexer.consumeCurrentToken().token_string;
|
std::string tokenString = m_lexer.consumeCurrentToken().token_string;
|
||||||
switch (token_type) {
|
switch (token_type) {
|
||||||
case TokenType::int_number:
|
case TokenType::int_number:
|
||||||
|
|
@ -443,7 +468,7 @@ namespace usql {
|
||||||
case TokenType::keyword_null:
|
case TokenType::keyword_null:
|
||||||
return std::make_unique<NullValueNode>();
|
return std::make_unique<NullValueNode>();
|
||||||
default:
|
default:
|
||||||
throw Exception("Unknown operand node");
|
throw Exception("Unknown operand node " + tokenString);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -463,7 +488,7 @@ namespace usql {
|
||||||
case TokenType::lesser_equal:
|
case TokenType::lesser_equal:
|
||||||
return RelationalOperatorType::lesser_equal;
|
return RelationalOperatorType::lesser_equal;
|
||||||
default:
|
default:
|
||||||
throw Exception("Unknown relational operator");
|
throw Exception("Unknown relational operator " + op.token_string);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -495,4 +520,22 @@ namespace usql {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Node> Parser::parse_relational_expression() {
|
||||||
|
auto left = parse_operand_node();
|
||||||
|
|
||||||
|
if (!Lexer::isRelationalOperator(m_lexer.tokenType()))
|
||||||
|
{
|
||||||
|
if (left->node_type != NodeType::relational_operator)
|
||||||
|
throw Exception("syntax error in relational operation");
|
||||||
|
|
||||||
|
return left;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto operation = parse_relational_operator();
|
||||||
|
auto right = parse_operand_node();
|
||||||
|
|
||||||
|
return std::make_unique<RelationalOperatorNode>(operation, std::move(left), std::move(right));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
|
|
||||||
6
parser.h
6
parser.h
|
|
@ -362,15 +362,19 @@ namespace usql {
|
||||||
std::unique_ptr<Node> parse_delete_from_table();
|
std::unique_ptr<Node> parse_delete_from_table();
|
||||||
std::unique_ptr<Node> parse_update_table();
|
std::unique_ptr<Node> parse_update_table();
|
||||||
|
|
||||||
std::unique_ptr<Node> parse_where_clause();
|
|
||||||
std::vector<ColOrderNode> parse_order_by_clause();
|
std::vector<ColOrderNode> parse_order_by_clause();
|
||||||
OffsetLimitNode parse_offset_limit_clause();
|
OffsetLimitNode parse_offset_limit_clause();
|
||||||
|
|
||||||
|
std::unique_ptr<Node> parse_where_clause();
|
||||||
|
std::unique_ptr<Node> parse_expression();
|
||||||
|
std::unique_ptr<Node> parse_expression(std::unique_ptr<Node> left);
|
||||||
|
|
||||||
std::unique_ptr<Node> parse_operand_node();
|
std::unique_ptr<Node> parse_operand_node();
|
||||||
std::unique_ptr<Node> parse_value();
|
std::unique_ptr<Node> parse_value();
|
||||||
RelationalOperatorType parse_relational_operator();
|
RelationalOperatorType parse_relational_operator();
|
||||||
LogicalOperatorType parse_logical_operator();
|
LogicalOperatorType parse_logical_operator();
|
||||||
ArithmeticalOperatorType parse_arithmetical_operator();
|
ArithmeticalOperatorType parse_arithmetical_operator();
|
||||||
|
|
||||||
std::unique_ptr<Node> parse_relational_expression();
|
std::unique_ptr<Node> parse_relational_expression();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
47
table.cpp
47
table.cpp
|
|
@ -3,6 +3,8 @@
|
||||||
#include "csvreader.h"
|
#include "csvreader.h"
|
||||||
#include "ml_string.h"
|
#include "ml_string.h"
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
namespace usql {
|
namespace usql {
|
||||||
|
|
||||||
|
|
@ -70,21 +72,49 @@ std::string Table::csv_string() {
|
||||||
}
|
}
|
||||||
|
|
||||||
int Table::load_csv_string(const std::string &content) {
|
int Table::load_csv_string(const std::string &content) {
|
||||||
int row_cnt = 0;
|
std::vector<ColDefNode> &colDefs = m_col_defs;
|
||||||
|
|
||||||
CsvReader csvparser{};
|
CsvReader csvparser{};
|
||||||
auto csv = csvparser.parseCSV(content);
|
int row_cnt = csvparser.parseCSV2(content, colDefs, *this);
|
||||||
|
|
||||||
|
return row_cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Table::load_csv_file(const std::string &filename) {
|
||||||
std::vector<ColDefNode> &colDefs = m_col_defs;
|
std::vector<ColDefNode> &colDefs = m_col_defs;
|
||||||
for (auto it = csv.begin() + 1; it != csv.end(); ++it) {
|
|
||||||
std::vector<std::string> &csv_line = *it;
|
|
||||||
|
|
||||||
|
// allocate enough space
|
||||||
|
int line_size = 128;
|
||||||
|
|
||||||
|
std::ifstream in(filename, std::ifstream::ate | std::ifstream::binary);
|
||||||
|
auto file_size = in.tellg();
|
||||||
|
|
||||||
|
std::ifstream infile(filename);
|
||||||
|
if (infile.good()) {
|
||||||
|
std::string sLine;
|
||||||
|
std::getline(infile, sLine);
|
||||||
|
line_size = sLine.size();
|
||||||
|
}
|
||||||
|
infile.close();
|
||||||
|
|
||||||
|
if (file_size > 0) {
|
||||||
|
m_rows.reserve(m_rows.size() + int(file_size / line_size * 1.1));
|
||||||
|
}
|
||||||
|
|
||||||
|
// load rows
|
||||||
|
CsvReader csvparser{};
|
||||||
|
int row_cnt = csvparser.parseCSV(filename, colDefs, *this);
|
||||||
|
|
||||||
|
return row_cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Table::create_row_from_vector(const std::vector<ColDefNode> &colDefs, const std::vector<std::string> &csv_line) {
|
||||||
// prepare empty new_row
|
// prepare empty new_row
|
||||||
Row& new_row = create_empty_row();
|
Row& new_row = create_empty_row();
|
||||||
|
|
||||||
// copy values
|
// copy values
|
||||||
for (size_t i = 0; i < columns_count(); i++) {
|
for (size_t i = 0; i < std::min<int>(columns_count(), csv_line.size()); i++) {
|
||||||
ColDefNode col_def = get_column_def(colDefs[i].name);
|
const ColDefNode & col_def = colDefs[i];
|
||||||
|
|
||||||
if (csv_line[i].empty()) {
|
if (csv_line[i].empty()) {
|
||||||
new_row.setColumnNull(col_def.order);
|
new_row.setColumnNull(col_def.order);
|
||||||
|
|
@ -104,11 +134,6 @@ int Table::load_csv_string(const std::string &content) {
|
||||||
|
|
||||||
// append new_row
|
// append new_row
|
||||||
commit_row(new_row);
|
commit_row(new_row);
|
||||||
|
|
||||||
row_cnt++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return row_cnt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
double Table::string_to_double(const std::string &s) {
|
double Table::string_to_double(const std::string &s) {
|
||||||
|
|
|
||||||
5
table.h
5
table.h
|
|
@ -15,7 +15,7 @@ namespace usql {
|
||||||
ColDefNode get_column_def(const std::string &col_name);
|
ColDefNode get_column_def(const std::string &col_name);
|
||||||
ColDefNode get_column_def(int col_index);
|
ColDefNode get_column_def(int col_index);
|
||||||
|
|
||||||
int columns_count() const { return m_col_defs.size(); };
|
int columns_count() const { return m_col_defs.size(); }; // TODO size_t type?
|
||||||
int rows_count() const { return m_rows.size(); };
|
int rows_count() const { return m_rows.size(); };
|
||||||
|
|
||||||
Row& create_empty_row();
|
Row& create_empty_row();
|
||||||
|
|
@ -28,6 +28,7 @@ namespace usql {
|
||||||
|
|
||||||
std::string csv_string();
|
std::string csv_string();
|
||||||
int load_csv_string(const std::string &content);
|
int load_csv_string(const std::string &content);
|
||||||
|
int load_csv_file(const std::string &filename);
|
||||||
|
|
||||||
void print();
|
void print();
|
||||||
|
|
||||||
|
|
@ -37,6 +38,8 @@ namespace usql {
|
||||||
|
|
||||||
static long string_to_long(const std::string &s) ;
|
static long string_to_long(const std::string &s) ;
|
||||||
static double string_to_double(const std::string &s) ;
|
static double string_to_double(const std::string &s) ;
|
||||||
|
|
||||||
|
void create_row_from_vector(const std::vector<ColDefNode> &colDefs, const std::vector<std::string> &csv_line);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
20
usql.cpp
20
usql.cpp
|
|
@ -87,12 +87,14 @@ std::unique_ptr<Table> USql::execute_load(LoadIntoTableNode &node) {
|
||||||
Table *table_def = find_table(node.table_name);
|
Table *table_def = find_table(node.table_name);
|
||||||
|
|
||||||
// read data
|
// read data
|
||||||
std::ifstream ifs(node.filename);
|
// std::ifstream ifs(node.filename);
|
||||||
std::string content((std::istreambuf_iterator<char>(ifs)),
|
// std::string content((std::istreambuf_iterator<char>(ifs)),
|
||||||
(std::istreambuf_iterator<char>()));
|
// (std::istreambuf_iterator<char>()));
|
||||||
|
|
||||||
// load rows
|
// load rows
|
||||||
auto rows_cnt = table_def->load_csv_string(content);
|
// auto rows_cnt = table_def->load_csv_string(content);
|
||||||
|
|
||||||
|
|
||||||
|
auto rows_cnt = table_def->load_csv_file(node.filename);
|
||||||
|
|
||||||
return create_stmt_result_table(0, "load succeeded", rows_cnt);
|
return create_stmt_result_table(0, "load succeeded", rows_cnt);
|
||||||
}
|
}
|
||||||
|
|
@ -483,12 +485,14 @@ std::unique_ptr<ValueNode> USql::eval_function_value_node(Table *table, Row &row
|
||||||
|
|
||||||
|
|
||||||
bool USql::eval_logical_operator(LogicalOperatorNode &node, Table *pTable, Row &row) {
|
bool USql::eval_logical_operator(LogicalOperatorNode &node, Table *pTable, Row &row) {
|
||||||
bool left = eval_relational_operator(static_cast<const RelationalOperatorNode &>(*node.left), pTable, row);
|
//bool left = eval_relational_operator(static_cast<const RelationalOperatorNode &>(*node.left), pTable, row);
|
||||||
|
bool left = eval_where(&(*node.left), pTable, row);
|
||||||
|
|
||||||
if ((node.op == LogicalOperatorType::and_operator && !left) || (node.op == LogicalOperatorType::or_operator && left))
|
if ((node.op == LogicalOperatorType::and_operator && !left) || (node.op == LogicalOperatorType::or_operator && left))
|
||||||
return left;
|
return left;
|
||||||
|
|
||||||
bool right = eval_relational_operator(static_cast<const RelationalOperatorNode &>(*node.right), pTable, row);
|
//bool right = eval_relational_operator(static_cast<const RelationalOperatorNode &>(*node.right), pTable, row);
|
||||||
|
bool right = eval_where(&(*node.right), pTable, row);
|
||||||
return right;
|
return right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -559,7 +563,7 @@ std::unique_ptr<Table> USql::create_stmt_result_table(long code, const std::stri
|
||||||
|
|
||||||
Row& new_row = table_def->create_empty_row();
|
Row& new_row = table_def->create_empty_row();
|
||||||
new_row.setIntColumnValue(0, code);
|
new_row.setIntColumnValue(0, code);
|
||||||
new_row.setStringColumnValue(1, text);
|
new_row.setStringColumnValue(1, text.size() <= 48 ? text : text.substr(0,48));
|
||||||
new_row.setIntColumnValue(2, affected_rows);
|
new_row.setIntColumnValue(2, affected_rows);
|
||||||
table_def->commit_row(new_row);
|
table_def->commit_row(new_row);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue