#include "table.h" #include "csvreader.h" namespace usql { Table::Table(const std::string name, const std::vector columns) { m_name = name; m_col_defs = columns; m_rows.clear(); } ColDefNode Table::get_column_def(const std::string &col_name) { auto name_cmp = [col_name](ColDefNode cd) { return cd.name == col_name; }; auto col_def = std::find_if(begin(m_col_defs), end(m_col_defs), name_cmp); if (col_def != std::end(m_col_defs)) { return *col_def; } else { throw Exception("column not exists (" + col_name + ")"); } } Row Table::create_empty_row() { return Row(columns_count()); } std::string Table::csv_string() { // header std::string out_string; for(int i = 0; i < m_col_defs.size(); i++) { if (i > 0) out_string += ","; out_string += m_col_defs[i].name; } // rows for (auto it = m_rows.begin(); it != m_rows.end(); ++it) { std::string csv_line{"\n"}; for(int i = 0; i < m_col_defs.size(); i++) { if (i > 0) csv_line += ","; auto col = it->ith_column(i); if (!col->isNull()) { csv_line += col->getStringValue(); // TODO handle enclosing commas etc } } out_string += csv_line; } return out_string; } int Table::load_csv_string(const std::string &content) { int row_cnt = 0; CsvReader csvparser{}; auto csv = csvparser.parseCSV(content); std::vector &colDefs = m_col_defs; for (auto it = csv.begin() + 1; it != csv.end(); ++it) { std::vector csv_line = *it; // prepare empty new_row Row new_row = create_empty_row(); // copy values for (size_t i = 0; i < columns_count(); i++) { ColDefNode col_def = get_column_def(colDefs[i].name); // TODO validate value if (col_def.type == ColumnType::integer_type) { new_row.setColumnValue(col_def.order, std::stol(csv_line[i])); } else if (col_def.type == ColumnType::float_type) { new_row.setColumnValue(col_def.order, std::stof(csv_line[i])); } else { new_row.setColumnValue(col_def.order, csv_line[i]); } } // append new_row add_row(new_row); row_cnt++; } return row_cnt; } void Table::print() { std::cout << "** " << m_name << " **" << std::endl; for (auto row : m_rows) { row.print(); } } Table::Table(const Table &other) { m_name = other.m_name; m_col_defs = other.m_col_defs; for(const Row& orig_row : other.m_rows) { add_copy_of_row(orig_row); } } void Table::add_row(const Row &row) { validate_row(row); m_rows.push_back(row); } void Table::add_copy_of_row(const Row &row) { Row new_row = create_empty_row(); for(int i = 0; i < m_col_defs.size(); i++) { ColValue *ct = row.ith_column(i); if (ct->isNull()) { new_row.setColumnNull(i); } else { if (m_col_defs[i].type == ColumnType::integer_type) { new_row.setColumnValue(i, row.ith_column(i)->getIntValue()); } else if (m_col_defs[i].type == ColumnType::float_type) { new_row.setColumnValue(i, row.ith_column(i)->getDoubleValue()); } else if (m_col_defs[i].type == ColumnType::varchar_type) { new_row.setColumnValue(i, row.ith_column(i)->getStringValue()); } } } validate_row(new_row); m_rows.push_back(new_row); } void Table::validate_column(const ColDefNode *col_def, ValueNode *col_val) { if (col_def->null == false && col_val->isNull()) { throw Exception("Column " + col_def->name + " cannot be null"); } if (col_def->type == ColumnType::varchar_type && !col_val->isNull() && col_val->getStringValue().size() > col_def->length) { throw Exception("Column value of " + col_def->name + " is too long (" + col_val->getStringValue() + ")"); } } void Table::validate_column(const ColDefNode *col_def, ColValue *col_val) { if (col_def->null == false && col_val->isNull()) { throw Exception("Column " + col_def->name + " cannot be null"); } if (col_def->type == ColumnType::varchar_type && !col_val->isNull() && col_val->getStringValue().size() > col_def->length) { throw Exception("Column value of " + col_def->name + " is too long (" + col_val->getStringValue() + ")"); } } void Table::validate_row(const Row &row) { for(int i = 0; i < m_col_defs.size(); i++) { ColDefNode col_def = m_col_defs[i]; ColValue *col_val = row.ith_column(i); validate_column(&col_def, col_val); } } } // namespace