From 056b45c83156be1a0a1511717868dcb0f533a2da Mon Sep 17 00:00:00 2001 From: VaclavT Date: Sun, 6 Mar 2022 23:24:22 +0100 Subject: [PATCH 1/2] silence warnings --- .gitignore | 1 + parser.cpp | 8 ++++---- parser.h | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index cd2524a..93b6723 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ localhost.session.sql CMakeFiles cmake-build-debug-coverage .idea +.cache diff --git a/parser.cpp b/parser.cpp index 32d55ef..b5682d7 100644 --- a/parser.cpp +++ b/parser.cpp @@ -7,12 +7,12 @@ namespace usql { std::string column_type_name(const ColumnType type) { if (type == ColumnType::integer_type) return "integer_type"; - if (type == ColumnType::float_type) return "float_type"; + if (type == ColumnType::float_type) return "float_type"; if (type == ColumnType::varchar_type) return "varchar_type"; - if (type == ColumnType::date_type) return "date_type"; - if (type == ColumnType::bool_type) return "bool_type"; + if (type == ColumnType::date_type) return "date_type"; + if (type == ColumnType::bool_type) return "bool_type"; - throw Exception("invalid column type: " + (int)type); + throw Exception("invalid column type: " + std::to_string((int)type)); }; diff --git a/parser.h b/parser.h index f100c32..a7e3b4d 100644 --- a/parser.h +++ b/parser.h @@ -162,7 +162,7 @@ struct FunctionNode : Node { if (type == Type::max) return "max"; if (type == Type::count) return "count"; - throw Exception("invalid function: " + (int)type); + throw Exception("invalid function: " + std::to_string((int)type)); }; From 038d891db59f31edf202a09d57cadbe85119742b Mon Sep 17 00:00:00 2001 From: VaclavT Date: Tue, 8 Mar 2022 17:35:08 +0100 Subject: [PATCH 2/2] basic version of coalesce function --- debug.h | 35 +++++++++++++++++++---------------- parser.h | 5 ++++- usql.cpp | 3 +++ usql.h | 1 + usql_dml.cpp | 7 +++++++ usql_function.cpp | 27 ++++++++++++++++++++++----- 6 files changed, 56 insertions(+), 22 deletions(-) diff --git a/debug.h b/debug.h index 6493e02..09e465a 100644 --- a/debug.h +++ b/debug.h @@ -10,33 +10,36 @@ std::vector k_debug_sql_commands { // "delete from history_earnings_dates where symbol='BABA' and datetime=to_date('2021-11-04', '%Y-%m-%d')", // "select * from history_earnings_dates" - "create table sf1 (symbol varchar(8) not null, 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)", - "set 'DATE_FORMAT' = '%Y-%m-%d'", - "create index sf1_symbol on sf1(symbol)", - "load into sf1 '/srv/SHARADAR_SF1.csv'", - "set 'USE_INDEXSCAN' = 'false'", - "select dimension, to_string(calendar_date, '%d.%m.%Y'), pp(eps, \"%.2f\"), pp(shareswadil), pp(revenue), pp(netinc), pp(cashneq), pp(assets), pp(debt), pp(ncfdebt), pp(roe*100), pp(intangibles), calendar_date from sf1 where symbol = 'MU' and dimension = 'ARQ' order by dimension, calendar_date desc limit 5", - "set 'USE_INDEXSCAN' = 'true'", - "select dimension, to_string(calendar_date, '%d.%m.%Y'), pp(eps, \"%.2f\"), pp(shareswadil), pp(revenue), pp(netinc), pp(cashneq), pp(assets), pp(debt), pp(ncfdebt), pp(roe*100), pp(intangibles), calendar_date from sf1 where symbol = 'MU' and dimension = 'ARQ' order by dimension, calendar_date desc limit 5", - "select max(calendar_date), calendar_date from sf1 where symbol = 'MU' and dimension = 'ARQ'", - "select max(calendar_date), min(calendar_date) from sf1 where symbol = 'MU' and dimension = 'ARQ'" + // "create table sf1 (symbol varchar(8) not null, 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)", + // "set 'DATE_FORMAT' = '%Y-%m-%d'", + // "create index sf1_symbol on sf1(symbol)", + // "load into sf1 '/srv/SHARADAR_SF1.csv'", + // "set 'USE_INDEXSCAN' = 'false'", + // "select dimension, to_string(calendar_date, '%d.%m.%Y'), pp(eps, \"%.2f\"), pp(shareswadil), pp(revenue), pp(netinc), pp(cashneq), pp(assets), pp(debt), pp(ncfdebt), pp(roe*100), pp(intangibles), calendar_date from sf1 where symbol = 'MU' and dimension = 'ARQ' order by dimension, calendar_date desc limit 5", + // "set 'USE_INDEXSCAN' = 'true'", + // "select dimension, to_string(calendar_date, '%d.%m.%Y'), pp(eps, \"%.2f\"), pp(shareswadil), pp(revenue), pp(netinc), pp(cashneq), pp(assets), pp(debt), pp(ncfdebt), pp(roe*100), pp(intangibles), calendar_date from sf1 where symbol = 'MU' and dimension = 'ARQ' order by dimension, calendar_date desc limit 5", + // "select max(calendar_date), calendar_date from sf1 where symbol = 'MU' and dimension = 'ARQ'", + // "select max(calendar_date), min(calendar_date) from sf1 where symbol = 'MU' and dimension = 'ARQ'" - // "create table a (i integer not null, s varchar(64))", - // "create index a_i on a(i)", + "create table a (i integer not null, s varchar(64))", + "create index a_i on a(i)", // "insert into a (i, s) values(1, 'one')", // "insert into a (i, s) values(2, 'two')", // "insert into a (i, s) values(2, 'second two')", // "insert into a (i, s) values(3, 'three')", // "insert into a (i, s) values(4, 'four')", - // "save a into '/tmp/a.csv'", - // "set 'USE_INDEXSCAN' = 'true'", + "insert into a (i) values(5)", + "save a into '/tmp/a.csv'", + "set 'USE_INDEXSCAN' = 'true'", // "select * from a where 1 = i", // "delete from a where i = 2 and s ='two'", // "select * from a where i = 2", // "update a set i = 5 where i = 2", // "select * from a where i = 5", - // "select max(i) from a where s = 'two'" + // "select max(i) from a where s = 'two'", // "select min(i), max(i), count(i) from a", - // "select i + 1000 from a" + // "select i + 1000 from a", + // "select i, s from a where i = 5", + "select i, s, coalesce(s, i) from a where i = 5" }; diff --git a/parser.h b/parser.h index a7e3b4d..b7efea5 100644 --- a/parser.h +++ b/parser.h @@ -132,6 +132,7 @@ struct FunctionNode : Node { pp, lower, upper, + coalesce, min, max, count @@ -144,6 +145,7 @@ struct FunctionNode : Node { if (str=="pp") return Type::pp; if (str=="lower") return Type::lower; if (str=="upper") return Type::upper; + if (str=="coalesce") return Type::coalesce; if (str=="min") return Type::min; if (str=="max") return Type::max; if (str=="count") return Type::count; @@ -158,6 +160,7 @@ struct FunctionNode : Node { if (type == Type::pp) return "pp"; if (type == Type::lower) return "lower"; if (type == Type::upper) return "upper"; + if (type == Type::coalesce) return "coalesce"; if (type == Type::min) return "min"; if (type == Type::max) return "max"; if (type == Type::count) return "count"; @@ -166,7 +169,7 @@ struct FunctionNode : Node { }; - Type function; + Type function; std::vector> params; FunctionNode(std::string func_name, std::vector> pars) : diff --git a/usql.cpp b/usql.cpp index 1c634a9..e827c4b 100644 --- a/usql.cpp +++ b/usql.cpp @@ -173,6 +173,9 @@ std::unique_ptr USql::eval_function_value_node(Table *table, Row &row evaluatedPars.push_back(eval_value_node(table, row, param.get(), nullptr, nullptr)); } + // coalesce function can have first parameter null, so must be calles before following "return null" + if (fnc->function == FunctionNode::Type::coalesce) return coalesce_function(evaluatedPars); + if (evaluatedPars.empty() || evaluatedPars[0]->isNull()) return std::make_unique(); diff --git a/usql.h b/usql.h index 17a9ee3..d8f9383 100644 --- a/usql.h +++ b/usql.h @@ -73,6 +73,7 @@ private: static std::unique_ptr lower_function(const std::vector> &evaluatedPars); static std::unique_ptr upper_function(const std::vector> &evaluatedPars); + static std::unique_ptr coalesce_function(const std::vector> &evaluatedPars); static std::unique_ptr to_date_function(const std::vector> &evaluatedPars); static std::unique_ptr to_string_function(const std::vector> &evaluatedPars); static std::unique_ptr date_add_function(const std::vector> &evaluatedPars); diff --git a/usql_dml.cpp b/usql_dml.cpp index cb79699..f259687 100644 --- a/usql_dml.cpp +++ b/usql_dml.cpp @@ -239,6 +239,13 @@ std::tuple USql::get_node_definition(Table *table, Node * node, // TODO get length, use get_db_column_definition ColDefNode col_def = ColDefNode{col_name, ColumnType::varchar_type, col_order, 256, true}; return std::make_tuple(FUNCTION_CALL, col_def); + } else if (func_node->function == FunctionNode::Type::coalesce) { + // TODO handle cases here + if (func_node->params.empty()) throw Exception("Coalesce without parameters"); + if (func_node->params[0]->node_type != NodeType::database_value) throw Exception("Coalesce first parameter must be database column"); + ColDefNode tbl_col_def = get_db_column_definition(table, func_node->params[0].get()); + ColDefNode col_def = ColDefNode{col_name, tbl_col_def.type, col_order, tbl_col_def.length, true}; + return std::make_tuple(FUNCTION_CALL, col_def); } else if (func_node->function == FunctionNode::Type::min || func_node->function == FunctionNode::Type::max) { auto col_type= ColumnType::float_type; size_t col_len = 1; diff --git a/usql_function.cpp b/usql_function.cpp index 1d7b3e6..11ec866 100644 --- a/usql_function.cpp +++ b/usql_function.cpp @@ -34,6 +34,13 @@ std::unique_ptr USql::date_add_function(const std::vector USql::lower_function(const std::vector> &evaluatedPars) { + std::string str = evaluatedPars[0]->getStringValue(); + std::transform(str.begin(), str.end(), str.begin(), [](unsigned char c) -> unsigned char { return tolower(c); }); + + return std::make_unique(str); +} + std::unique_ptr USql::upper_function(const std::vector> &evaluatedPars) { std::string str = evaluatedPars[0]->getStringValue(); std::transform(str.begin(), str.end(), str.begin(), [](unsigned char c) -> unsigned char { return toupper(c); }); @@ -41,11 +48,21 @@ std::unique_ptr USql::upper_function(const std::vector(str); } -std::unique_ptr USql::lower_function(const std::vector> &evaluatedPars) { - std::string str = evaluatedPars[0]->getStringValue(); - std::transform(str.begin(), str.end(), str.begin(), [](unsigned char c) -> unsigned char { return tolower(c); }); - - return std::make_unique(str); +std::unique_ptr USql::coalesce_function(const std::vector> &evaluatedPars) { + for(const auto & par : evaluatedPars) { + if (!par->isNull()) { + // TODO implement rest and take it out as a function + if (par->node_type == NodeType::int_value) + return std::make_unique(par->getIntegerValue()); + if (par->node_type == NodeType::float_value) + return std::make_unique(par->getDoubleValue()); + if (par->node_type == NodeType::string_value) + return std::make_unique(par->getStringValue()); + if (par->node_type == NodeType::bool_value) + return std::make_unique(par->getBooleanValue()); + } + } + return std::make_unique(); } std::unique_ptr USql::pp_function(const std::vector> &evaluatedPars) {