a bit of refactoring
This commit is contained in:
parent
906df74847
commit
eebb270f47
86
ml_date.cpp
86
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<long int>(t);
|
||||
time_t t = std::time(nullptr);
|
||||
auto now = static_cast<long int>(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!
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
4
parser.h
4
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); };
|
||||
|
|
|
|||
6
row.h
6
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"); };
|
||||
|
||||
|
|
|
|||
19
settings.cpp
19
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<std::pair<std::string, std::string>> 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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
37
table.cpp
37
table.cpp
|
|
@ -1,7 +1,6 @@
|
|||
#include "table.h"
|
||||
#include "csvreader.h"
|
||||
#include "ml_string.h"
|
||||
#include "fast_double_parser.h"
|
||||
|
||||
#include <charconv>
|
||||
#include <fstream>
|
||||
|
|
@ -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<ColDefNode> &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<ColDefNode> &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{"+-"};
|
||||
|
||||
|
|
|
|||
3
table.h
3
table.h
|
|
@ -41,9 +41,6 @@ struct Table {
|
|||
std::vector<Row> m_rows;
|
||||
std::vector<Index> 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<ColDefNode> &colDefs, const std::vector<std::string> &csv_line);
|
||||
|
||||
void create_index(const Index& index);
|
||||
|
|
|
|||
24
usql.cpp
24
usql.cpp
|
|
@ -1,6 +1,5 @@
|
|||
#include "usql.h"
|
||||
#include "exception.h"
|
||||
#include "ml_date.h"
|
||||
#include "ml_string.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
|
@ -175,6 +174,7 @@ std::unique_ptr<ValueNode> 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<NullValueNode>();
|
||||
|
||||
|
|
@ -194,13 +194,11 @@ 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 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))
|
||||
return left;
|
||||
|
||||
//bool right = eval_relational_operator(static_cast<const RelationalOperatorNode &>(*node.right), pTable, row);
|
||||
bool right = eval_where(&(*node.right), pTable, row);
|
||||
return right;
|
||||
}
|
||||
|
|
@ -218,8 +216,8 @@ std::unique_ptr<ValueNode> USql::eval_arithmetic_operator(ColumnType outType, Ar
|
|||
return std::make_unique<NullValueNode>();
|
||||
|
||||
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<DoubleValueNode>(l + r);
|
||||
|
|
@ -230,12 +228,12 @@ std::unique_ptr<ValueNode> USql::eval_arithmetic_operator(ColumnType outType, Ar
|
|||
case ArithmeticalOperatorType::divide_operator:
|
||||
return std::make_unique<DoubleValueNode>(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<IntValueNode>(l + r);
|
||||
|
|
@ -246,22 +244,22 @@ std::unique_ptr<ValueNode> USql::eval_arithmetic_operator(ColumnType outType, Ar
|
|||
case ArithmeticalOperatorType::divide_operator:
|
||||
return std::make_unique<IntValueNode>(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<StringValueNode>(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 {
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ std::unique_ptr<Table> USql::create_stmt_result_table(long code, const std::stri
|
|||
std::vector<ColDefNode> 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<Table>("result", result_tbl_col_defs);
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,8 @@ std::pair<bool, std::vector<rowid_t>> USql::probe_index_scan(const Node *where,
|
|||
std::pair<bool, std::vector<rowid_t>> 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))
|
||||
|
|
|
|||
Loading…
Reference in New Issue