From eebb270f47d3e9b1e86860811be77003bd3144d3 Mon Sep 17 00:00:00 2001 From: VaclavT Date: Sat, 18 Dec 2021 14:52:33 +0100 Subject: [PATCH] a bit of refactoring --- ml_date.cpp | 86 ++++++++++++++++++++++++++++------------------------ ml_date.h | 4 +-- parser.h | 4 +-- row.h | 6 ++++ settings.cpp | 19 +++++++++--- settings.h | 4 +-- table.cpp | 37 ++++++---------------- table.h | 3 -- usql.cpp | 24 +++++++-------- usql_ddl.cpp | 2 +- usql_dml.cpp | 3 +- 11 files changed, 96 insertions(+), 96 deletions(-) diff --git a/ml_date.cpp b/ml_date.cpp index a787dc8..1c8694c 100644 --- a/ml_date.cpp +++ b/ml_date.cpp @@ -2,14 +2,23 @@ #include "ml_date.h" long now() { // get-universal-time - time_t t = std::time(0); - long int now = static_cast(t); + time_t t = std::time(nullptr); + auto now = static_cast(t); return now; } -std::string date_to_string(const long datetime, const std::string format) { +long get_gmt_localtime_offset() { + std::time_t current_time; + std::time(¤t_time); + struct std::tm *timeinfo = std::localtime(¤t_time); + long offset = timeinfo->tm_gmtoff; + return offset; +} + +std::string date_to_string(const long datetime, const std::string& format) { // std::locale::global(std::locale("en-US.UTF8")); + time_t timestamp = datetime; char mbstr[128]; @@ -18,62 +27,59 @@ std::string date_to_string(const long datetime, const std::string format) { return result; } - throw std::runtime_error("date_to_string invalid date string or format"); + throw std::runtime_error("date_to_string, invalid date string or format (" + std::to_string(datetime) + ", " + format + ")" ); } time_t time_to_epoch ( const struct tm *ltm, int utcdiff ) { - const int mon_days [] = {0, 31, 31+28, 31+28+31, - 31+28+31+30, 31+28+31+30+31, 31+28+31+30+31+30, - 31+28+31+30+31+30+31, 31+28+31+30+31+30+31+31, 31+28+31+30+31+30+31+31+30, - 31+28+31+30+31+30+31+31+30+31, 31+28+31+30+31+30+31+31+30+31+30, 31+28+31+30+31+30+31+31+30+31+30+31}; + const int mon_days [] = {0, 31, 31+28, 31+28+31, + 31+28+31+30, 31+28+31+30+31, 31+28+31+30+31+30, + 31+28+31+30+31+30+31, 31+28+31+30+31+30+31+31, 31+28+31+30+31+30+31+31+30, + 31+28+31+30+31+30+31+31+30+31, 31+28+31+30+31+30+31+31+30+31+30, 31+28+31+30+31+30+31+31+30+31+30+31}; - long tyears, tdays, leaps, utc_hrs; - int i; + long tyears, tdays, leaps, utc_hrs; - tyears = ltm->tm_year - 70 ; // tm->tm_year is from 1900. - leaps = (tyears + 2) / 4; - // no of next two lines until year 2100. - //i = (ltm->tm_year – 100) / 100; - //leaps -= ( (i/4)*3 + i%4 ); + tyears = ltm->tm_year - 70 ; // tm->tm_year is from 1900. + leaps = (tyears + 2) / 4; + // no of next two lines until year 2100. + //int i = (ltm->tm_year – 100) / 100; + //leaps -= ( (i/4)*3 + i%4 ); - tdays = mon_days[ltm->tm_mon]; + tdays = mon_days[ltm->tm_mon]; - tdays += ltm->tm_mday-1; // days of month passed. - tdays = tdays + (tyears * 365) + leaps; + tdays += ltm->tm_mday-1; // days of month passed. + tdays = tdays + (tyears * 365) + leaps; - utc_hrs = ltm->tm_hour + utcdiff/3600; // for your time zone. - return (tdays * 86400) + (utc_hrs * 3600) + (ltm->tm_min * 60) + ltm->tm_sec; + utc_hrs = ltm->tm_hour + utcdiff/3600; // for your time zone. + return (tdays * 86400) + (utc_hrs * 3600) + (ltm->tm_min * 60) + ltm->tm_sec; } long string_to_date(const std::string &datestr, const std::string &format) { // format for example "%d.%m.%Y"; - struct tm tm; + struct tm tm{}; memset(&tm, 0, sizeof(tm)); if (strptime(datestr.c_str(), format.c_str(), &tm)) { - time_t curTime; - struct tm * timeinfo; - - time(&curTime ); - timeinfo = localtime(&curTime); - - timeinfo->tm_year = tm.tm_year; - timeinfo->tm_mon = tm.tm_mon; - timeinfo->tm_mday = tm.tm_mday; - timeinfo->tm_hour = tm.tm_hour; - timeinfo->tm_min = tm.tm_min; - timeinfo->tm_sec = tm.tm_sec; - - // int offset = -1 * timeinfo->tm_gmtoff; // for local time - int offset = 0; - return time_to_epoch(timeinfo, offset); + time_t curTime; + struct tm * timeinfo; + + time(&curTime ); + timeinfo = std::gmtime(&curTime); + + timeinfo->tm_year = tm.tm_year; + timeinfo->tm_mon = tm.tm_mon; + timeinfo->tm_mday = tm.tm_mday; + timeinfo->tm_hour = tm.tm_hour; + timeinfo->tm_min = tm.tm_min; + timeinfo->tm_sec = tm.tm_sec; + + return time_to_epoch(timeinfo, 0); } - throw std::runtime_error("invalid date string or format (" + datestr + ", " + format + ")" ); + throw std::runtime_error("string_to_date, invalid date string or format (" + datestr + ", " + format + ")" ); } -long add_to_date(const long datetime, const long quantity, const std::string &part) { +long add_to_date(const long datetime, const int quantity, const std::string &part) { // part is one of 'year', 'month', 'day', 'hour', 'minute' or 'second' // very basic implementation, just for now - no timezones DST etc @@ -93,7 +99,7 @@ long add_to_date(const long datetime, const long quantity, const std::string &pa } else if (part == "second") { tm->tm_sec += quantity; } else { - // TODO exception here + throw std::runtime_error("add_to_date, part to add (" + part + ")" ); } return mktime(tm); // mktime is quite slow! diff --git a/ml_date.h b/ml_date.h index 5353d23..56fda1b 100644 --- a/ml_date.h +++ b/ml_date.h @@ -9,9 +9,9 @@ long now(); -std::string date_to_string(const long datetime, const std::string format); +std::string date_to_string(const long datetime, const std::string& format); long string_to_date(const std::string &datestr, const std::string &format); -long add_to_date(const long datetime, const long quantity, const std::string &part); +long add_to_date(const long datetime, const int quantity, const std::string &part); diff --git a/parser.h b/parser.h index 7775976..8a78fb9 100644 --- a/parser.h +++ b/parser.h @@ -176,7 +176,7 @@ namespace usql { long getIntegerValue() const override { return value; }; double getDoubleValue() const override { return (double) value; }; - std::string getStringValue() const override { return Settings::int_to_string(value); } + std::string getStringValue() const override { return Settings::long_to_string(value); } long getDateValue() const override { return value; }; bool getBooleanValue() const override { return value != 0; }; @@ -206,7 +206,7 @@ namespace usql { explicit StringValueNode(std::string value) : ValueNode(NodeType::string_value), value(std::move(value)) {} - long getIntegerValue() const override { return Settings::string_to_int(value); }; + long getIntegerValue() const override { return Settings::string_to_long(value); }; double getDoubleValue() const override { return Settings::string_to_double(value); }; std::string getStringValue() const override { return value; }; long getDateValue() const override { return Settings::string_to_date(value); }; diff --git a/row.h b/row.h index c875248..a11e9e4 100644 --- a/row.h +++ b/row.h @@ -15,6 +15,7 @@ struct ColValue { virtual long getIntegerValue() const = 0; virtual double getDoubleValue() const = 0; virtual std::string getStringValue() const = 0; + virtual std::string getCsvStringValue() const { return getStringValue(); }; virtual long getDateValue() const = 0; virtual bool getBoolValue() const = 0; @@ -87,6 +88,11 @@ struct ColStringValue : ColValue { long getIntegerValue() const override { return std::stoi(*m_string); }; double getDoubleValue() const override { return std::stod(*m_string); }; std::string getStringValue() const override { return *m_string; }; + std::string getCsvStringValue() const override { + // TODO handle correctly CSV string + // ?? return std::regex_replace(getStringValue(), std::regex( "\"" ), "\\\"" ); + return getStringValue(); + }; long getDateValue() const override { return std::stoi(*m_string); }; bool getBoolValue() const override { throw Exception("Not supported on ColStringValue"); }; diff --git a/settings.cpp b/settings.cpp index bcd82c2..ca36be8 100644 --- a/settings.cpp +++ b/settings.cpp @@ -1,4 +1,6 @@ +#include "fast_double_parser.h" + #include "settings.h" #include "exception.h" #include "ml_date.h" @@ -14,17 +16,26 @@ std::vector> Settings::m_settings = -long Settings::string_to_int(const std::string &intstr) { - return std::stoi(intstr); +long Settings::string_to_long(const std::string &intstr) { + try { + return std::stol(intstr); + } catch (std::invalid_argument &e) { + throw Exception("error parsing as integer: " + intstr); + } } -std::string Settings::int_to_string(long intval) { +std::string Settings::long_to_string(long intval) { return std::to_string(intval); } double Settings::string_to_double(const std::string &doublestr) { - return std::stod(doublestr); // TODO use fast parsing + double result; + const char * endptr = fast_double_parser::parse_number(doublestr.c_str(), &result); + if (endptr == nullptr) { + throw Exception("error parsing as double: " + doublestr); + } + return result; } std::string Settings::double_to_string(double d) { diff --git a/settings.h b/settings.h index ff35fee..014787c 100644 --- a/settings.h +++ b/settings.h @@ -12,8 +12,8 @@ public: static std::string get_setting(const std::string &name); static bool get_bool_setting(const std::string &name); - static long string_to_int(const std::string &intstr); - static std::string int_to_string(long intval); + static long string_to_long(const std::string &intstr); + static std::string long_to_string(long intval); static double string_to_double(const std::string &doublestr); static std::string double_to_string(double doubleval); diff --git a/table.cpp b/table.cpp index f8a3175..80df9a9 100644 --- a/table.cpp +++ b/table.cpp @@ -1,7 +1,6 @@ #include "table.h" #include "csvreader.h" #include "ml_string.h" -#include "fast_double_parser.h" #include #include @@ -50,15 +49,14 @@ Row& Table::create_empty_row() { } std::string Table::csv_string() { - const size_t row_size_est = m_col_defs.size() * 16; + const size_t k_row_size_est = m_col_defs.size() * 16; std::string out_string; - out_string.reserve(m_rows.size() * row_size_est); - // TODO improve it here https://www.cplusplus.com/reference/string/string/reserve/ + out_string.reserve(m_rows.size() * k_row_size_est); // header for(int i = 0; i < m_col_defs.size(); i++) { - if (i > 0) out_string += ","; + if (i > 0) out_string += ','; out_string += m_col_defs[i].name; } @@ -66,14 +64,14 @@ std::string Table::csv_string() { for (auto & row : m_rows) { if (row.is_visible()) { std::string csv_line{"\n"}; - csv_line.reserve(row_size_est); + csv_line.reserve(k_row_size_est); for (int i = 0; i < m_col_defs.size(); i++) { - if (i > 0) csv_line += ","; + if (i > 0) csv_line += ','; auto &col = row[i]; if (!col.isNull()) { - csv_line += col.getStringValue(); // TODO handle enclosing commas etc + csv_line += col.getCsvStringValue(); } } out_string += csv_line; @@ -132,9 +130,9 @@ void Table::create_row_from_vector(const std::vector &colDefs, const if (csv_line[i].empty()) { new_row.setColumnNull(col_def.order); } else if (col_def.type == ColumnType::integer_type) { - new_row.setIntColumnValue(col_def.order, string_to_long(csv_line[i])); + new_row.setIntColumnValue(col_def.order, Settings::string_to_long(csv_line[i])); } else if (col_def.type == ColumnType::float_type) { - new_row.setFloatColumnValue(col_def.order, string_to_double(csv_line[i])); + new_row.setFloatColumnValue(col_def.order, Settings::string_to_double(csv_line[i])); } else if (col_def.type == ColumnType::varchar_type) { new_row.setStringColumnValue(col_def.order, csv_line[i]); } else if (col_def.type == ColumnType::date_type) { @@ -149,24 +147,7 @@ void Table::create_row_from_vector(const std::vector &colDefs, const commit_row(new_row); } -double Table::string_to_double(const std::string &s) { - double result; - const char * endptr = fast_double_parser::parse_number(s.c_str(), &result); - if (endptr == nullptr) { - throw Exception("error parsing as double: " + s); - } - return result; -} - -long Table::string_to_long(const std::string &s) { - try { - return std::stol(s); - } catch (std::invalid_argument &e) { - throw Exception("error parsing as integer: " + s); - } -} - -void Table::print() { + void Table::print() { std::string out{"| "}; std::string out2{"+-"}; diff --git a/table.h b/table.h index a7128f9..e890955 100644 --- a/table.h +++ b/table.h @@ -41,9 +41,6 @@ struct Table { std::vector m_rows; std::vector m_indexes; - static long string_to_long(const std::string &s); - static double string_to_double(const std::string &s); - void create_row_from_vector(const std::vector &colDefs, const std::vector &csv_line); void create_index(const Index& index); diff --git a/usql.cpp b/usql.cpp index 3cd3e3a..392cef4 100644 --- a/usql.cpp +++ b/usql.cpp @@ -1,6 +1,5 @@ #include "usql.h" #include "exception.h" -#include "ml_date.h" #include "ml_string.h" #include @@ -175,6 +174,7 @@ std::unique_ptr USql::eval_function_value_node(Table *table, Row &row } // at this moment no functions without parameter(s) or first param can be null + // TODO exception here or better parsing if (evaluatedPars.empty() || evaluatedPars[0]->isNull()) return std::make_unique(); @@ -194,13 +194,11 @@ std::unique_ptr USql::eval_function_value_node(Table *table, Row &row bool USql::eval_logical_operator(LogicalOperatorNode &node, Table *pTable, Row &row) { - //bool left = eval_relational_operator(static_cast(*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)) return left; - //bool right = eval_relational_operator(static_cast(*node.right), pTable, row); bool right = eval_where(&(*node.right), pTable, row); return right; } @@ -218,8 +216,8 @@ std::unique_ptr USql::eval_arithmetic_operator(ColumnType outType, Ar return std::make_unique(); if (outType == ColumnType::float_type) { - double l = ((ValueNode *) left.get())->getDoubleValue(); - double r = ((ValueNode *) right.get())->getDoubleValue(); + double l = left->getDoubleValue(); + double r = right->getDoubleValue(); switch (node.op) { case ArithmeticalOperatorType::plus_operator: return std::make_unique(l + r); @@ -230,12 +228,12 @@ std::unique_ptr USql::eval_arithmetic_operator(ColumnType outType, Ar case ArithmeticalOperatorType::divide_operator: return std::make_unique(l / r); default: - throw Exception("implement me!!"); + throw Exception("eval_arithmetic_operator, float type implement me!!"); } } else if (outType == ColumnType::integer_type) { - long l = ((ValueNode *) left.get())->getIntegerValue(); - long r = ((ValueNode *) right.get())->getIntegerValue(); + long l = left->getIntegerValue(); + long r = right->getIntegerValue(); switch (node.op) { case ArithmeticalOperatorType::plus_operator: return std::make_unique(l + r); @@ -246,22 +244,22 @@ std::unique_ptr USql::eval_arithmetic_operator(ColumnType outType, Ar case ArithmeticalOperatorType::divide_operator: return std::make_unique(l / r); default: - throw Exception("implement me!!"); + throw Exception("eval_arithmetic_operator, integer type implement me!!"); } } else if (outType == ColumnType::varchar_type) { - std::string l = ((ValueNode *) left.get())->getStringValue(); - std::string r = ((ValueNode *) right.get())->getStringValue(); + std::string l = left->getStringValue(); + std::string r = right->getStringValue(); switch (node.op) { case ArithmeticalOperatorType::plus_operator: return std::make_unique(l + r); default: - throw Exception("implement me!!"); + throw Exception("eval_arithmetic_operator, varchar type implement me!!"); } } // TODO date node should support addition and subtraction - throw Exception("implement me!!"); + throw Exception("eval_arithmetic_operator, implement me!!"); } Table *USql::find_table(const std::string &name) const { diff --git a/usql_ddl.cpp b/usql_ddl.cpp index 6066623..c6b1e18 100644 --- a/usql_ddl.cpp +++ b/usql_ddl.cpp @@ -85,7 +85,7 @@ std::unique_ptr USql::create_stmt_result_table(long code, const std::stri std::vector result_tbl_col_defs{}; result_tbl_col_defs.emplace_back("code", ColumnType::integer_type, 0, 1, false); result_tbl_col_defs.emplace_back("desc", ColumnType::varchar_type, 1, 48, false); - result_tbl_col_defs.emplace_back("affected_rows", ColumnType::integer_type, 0, 1, true); + result_tbl_col_defs.emplace_back("aff_rows", ColumnType::integer_type, 0, 1, true); auto table_def = std::make_unique
("result", result_tbl_col_defs); diff --git a/usql_dml.cpp b/usql_dml.cpp index 9102f49..ec2b192 100644 --- a/usql_dml.cpp +++ b/usql_dml.cpp @@ -22,7 +22,8 @@ std::pair> USql::probe_index_scan(const Node *where, std::pair> USql::look_for_usable_index(const Node *where, Table *table) const { if (where->node_type == NodeType::relational_operator) { auto * ron = (RelationalOperatorNode *)where; - // TODO impllemen > & < https://en.cppreference.com/w/cpp/container/map/upper_bound + // TODO implement >, >=, <=, < + // https://en.cppreference.com/w/cpp/container/map/upper_bound if (ron->op == RelationalOperatorType::equal) { if (ron->left->node_type == NodeType::database_value && ((ron->right->node_type == NodeType::int_value) || (ron->right->node_type == NodeType::string_value))