myTinySQL v0.2.0-2-g5000098
A tiny SQL interpreter over fixed-width text files
Loading...
Searching...
No Matches
Catalog.cpp
Go to the documentation of this file.
1
3
4#include "Catalog.hpp"
5
6#include <algorithm>
7#include <format>
8#include <fstream>
9
10#include "Util.hpp"
11
12namespace tinysql {
13
14namespace {
15
19struct Field {
20 std::size_t from;
21 std::size_t to;
22};
23constexpr Field kTable{15, 34};
24constexpr Field kName{35, 54};
25constexpr Field kType{55, 59};
26constexpr Field kFrom{60, 64};
27constexpr Field kTo{65, 69};
28constexpr Field kRecordLength{75, 79};
29
34std::string_view cut(std::string_view line, Field field)
35{
36 if (field.from >= line.size()) {
37 return {};
38 }
39 return trim(line.substr(field.from, field.to - field.from + 1));
40}
41
48std::size_t number(std::string_view line, Field field, std::size_t lineNumber)
49{
50 auto value = parseInteger(cut(line, field));
51 if (!value || *value < 0) {
52 throw SqlError(std::format("{} line {}: expected a number in characters {}-{}",
53 kCatalogTable, lineNumber, field.from, field.to));
54 }
55 return static_cast<std::size_t>(*value);
56}
57
58} // namespace
59
60std::optional<std::size_t> TableSchema::indexOf(std::string_view columnName) const
61{
62 auto it = std::ranges::find_if(columns, [&](const Column& c) { return equalsIgnoreCase(c.name, columnName); });
63 if (it == columns.end()) {
64 return std::nullopt;
65 }
66 return static_cast<std::size_t>(it - columns.begin());
67}
68
70{
71 return !columns.empty() && equalsIgnoreCase(columns.front().name, "ID");
72}
73
74Catalog Catalog::load(const std::filesystem::path& dataDir)
75{
76 Catalog catalog;
77 catalog.dataDir_ = dataDir;
78
79 const auto path = dataDir / kCatalogTable;
80 std::ifstream in(path);
81 if (!in) {
82 throw SqlError(std::format("cannot open the catalogue {}", path.string()));
83 }
84
85 std::string line;
86 std::size_t lineNumber = 0;
87 while (std::getline(in, line)) {
88 ++lineNumber;
89 if (trim(line).empty()) {
90 continue;
91 }
92 std::string tableName(cut(line, kTable));
93 Column column{
94 .name = std::string(cut(line, kName)),
95 .type = std::string(cut(line, kType)),
96 .from = number(line, kFrom, lineNumber),
97 .to = number(line, kTo, lineNumber),
98 };
99 if (tableName.empty() || column.name.empty() || column.to < column.from) {
100 throw SqlError(std::format("{} line {}: invalid column definition", kCatalogTable, lineNumber));
101 }
102 const std::size_t recordLength = std::max(number(line, kRecordLength, lineNumber), column.to + 1);
103
104 auto table = std::ranges::find_if(catalog.tables_,
105 [&](const TableSchema& t) { return equalsIgnoreCase(t.name, tableName); });
106 if (table == catalog.tables_.end()) {
107 catalog.tables_.push_back(TableSchema{.name = tableName, .columns = {}, .recordLength = 0});
108 table = std::prev(catalog.tables_.end());
109 }
110 table->columns.push_back(std::move(column));
111 table->recordLength = std::max(table->recordLength, recordLength);
112 }
113 return catalog;
114}
115
116const TableSchema& Catalog::table(std::string_view name) const
117{
118 auto it = std::ranges::find_if(tables_, [&](const TableSchema& t) { return equalsIgnoreCase(t.name, name); });
119 if (it == tables_.end()) {
120 throw SqlError(std::format("unknown table '{}'", name));
121 }
122 return *it;
123}
124
125std::filesystem::path Catalog::dataFile(const TableSchema& table) const
126{
128 return dataDir_ / kCatalogTable;
129 }
130 return dataDir_ / (table.name + "_DATA");
131}
132
133} // namespace tinysql
The table definitions read from SYSTEM_TABLE: tables, their columns and positions.
constexpr std::string_view kCatalogTable
Name of the catalogue table: it describes every table, itself included, and is its own data file.
Definition Catalog.hpp:16
The SqlError exception and small string helpers used everywhere.
std::optional< long long > parseInteger(std::string_view text)
Parses a whole string as a base-10 integer.
Definition Util.cpp:82
bool equalsIgnoreCase(std::string_view a, std::string_view b)
Compares two strings, ignoring the case of ASCII letters.
Definition Util.cpp:49
std::string_view trim(std::string_view text)
Removes leading and trailing spaces, tabs and line ends.
Definition Util.cpp:34
All table definitions, read from the SYSTEM_TABLE file (one 80-character line per column).
Definition Catalog.hpp:47
std::filesystem::path dataFile(const TableSchema &table) const
The file holding a table's rows.
Definition Catalog.cpp:125
std::filesystem::path dataDir_
Where the files are.
Definition Catalog.hpp:71
const TableSchema & table(std::string_view name) const
Finds a table by name.
Definition Catalog.cpp:116
std::vector< TableSchema > tables_
Every table, in file order.
Definition Catalog.hpp:72
static Catalog load(const std::filesystem::path &dataDir)
Reads SYSTEM_TABLE from a data directory.
Definition Catalog.cpp:74
A problem with one statement: bad syntax, unknown table, value too long...
Definition Util.hpp:16
constexpr Field kName
Column name.
Definition Catalog.cpp:24
constexpr Field kType
Column type (N1 or S1).
Definition Catalog.cpp:25
constexpr Field kTo
Last character of the column.
Definition Catalog.cpp:27
constexpr Field kTable
Table name.
Definition Catalog.cpp:23
std::size_t number(std::string_view line, Field field, std::size_t lineNumber)
Reads one numeric field of a SYSTEM_TABLE line.
Definition Catalog.cpp:48
constexpr Field kFrom
First character of the column in a data row.
Definition Catalog.cpp:26
constexpr Field kRecordLength
Length of a full data row.
Definition Catalog.cpp:28
std::string_view cut(std::string_view line, Field field)
Cuts one field out of a SYSTEM_TABLE line.
Definition Catalog.cpp:34
One column of a table: the characters it occupies in every fixed-width row.
Definition Catalog.hpp:19
std::string name
Column name, e.g. NOME.
Definition Catalog.hpp:20
The definition of one table: its name, its columns, and the length of a row.
Definition Catalog.hpp:31
std::string name
Table name, e.g. EMPLOY.
Definition Catalog.hpp:32
std::size_t recordLength
Length of a full row, in characters.
Definition Catalog.hpp:34
std::optional< std::size_t > indexOf(std::string_view columnName) const
Finds a column by name.
Definition Catalog.cpp:60
bool hasAutoId() const
Tells whether rows are numbered automatically.
Definition Catalog.cpp:69
std::vector< Column > columns
Columns in file order.
Definition Catalog.hpp:33
The position of one field in a SYSTEM_TABLE line.
Definition Catalog.cpp:19
std::size_t to
Last character, inclusive.
Definition Catalog.cpp:21
std::size_t from
First character, counted from 0.
Definition Catalog.cpp:20