Joedb 10.2.1
The Journal-Only Embedded Database
Loading...
Searching...
No Matches
Readable_Command_Processor.cpp
Go to the documentation of this file.
2#include "joedb/ui/type_io.h"
5#include "joedb/ui/json.h"
6#include "joedb/ui/dump.h"
7#include "joedb/Readable.h"
8
9#include <vector>
10#include <sstream>
11#include <iomanip>
12
13namespace joedb
14{
15 ////////////////////////////////////////////////////////////////////////////
17 ////////////////////////////////////////////////////////////////////////////
18 (
19 std::istream &in,
20 const Readable &readable
21 )
22 {
23 std::string table_name;
24 in >> table_name;
25 const Table_Id table_id = readable.find_table(table_name);
26 if (table_id == Table_Id(0))
27 throw Exception("No such table: " + table_name);
28 return table_id;
29 }
30
31 ////////////////////////////////////////////////////////////////////////////
33 ////////////////////////////////////////////////////////////////////////////
34 (
35 std::ostream &out,
36 Table_Id table_id,
37 size_t max_column_width,
38 Record_Id start,
39 size_t length
40 )
41 {
42 if (table_id != Table_Id(0))
43 {
44 const auto &fields = readable.get_fields(table_id);
45 std::map<Field_Id, size_t> column_width;
46
47 for (const auto &[fid, fname]: fields)
48 column_width[fid] = fname.size();
49
50 //
51 // Store values in strings to determine column widths
52 //
53 std::map<Field_Id, std::vector<std::string>> columns;
54 std::vector<Record_Id> id_column;
55
56 size_t rows = 0;
57 const Record_Id size = readable.get_size(table_id);
58 for (Record_Id record_id{0}; record_id < size; ++record_id)
59 {
60 if
61 (
62 readable.is_used(table_id, record_id) &&
63 (length == 0 || (record_id >= start && record_id < start + length))
64 )
65 {
66 rows++;
67 id_column.emplace_back(record_id);
68
69 for (const auto &[fid, fname]: fields)
70 {
71 std::ostringstream ss;
72 write_value(ss, table_id, record_id, fid);
73 ss.flush();
74 const std::string &s = ss.str();
75 const size_t width = utf8_display_size(s);
76 if (column_width[fid] < width)
77 column_width[fid] = width;
78 columns[fid].emplace_back(s);
79 }
80 }
81 }
82
83 //
84 // Determine table width
85 //
86 size_t id_width = 0;
87 {
88 std::ostringstream ss;
89 ss << size - 1;
90 ss.flush();
91 id_width = ss.str().size();
92 }
93 size_t table_width = id_width;
94 for (const auto &[fid, fname]: fields)
95 {
96 if (max_column_width && column_width[fid] > max_column_width)
97 column_width[fid] = max_column_width;
98 table_width += column_width[fid] + 1;
99 }
100
101 //
102 // Table header
103 //
104 out << std::string(table_width, '-') << '\n';
105 out << std::string(id_width, ' ');
106 for (const auto &[fid, fname]: fields)
107 {
108 const Type::Type_Id type_id = readable.get_field_type
109 (
110 table_id,
111 fid
112 ).get_type_id();
113 out << ' ';
115 (
116 out,
117 fname,
118 column_width[fid],
119 type_id == Type::Type_Id::string
120 );
121 }
122 out << '\n';
123 out << std::string(table_width, '-') << '\n';
124
125 //
126 // Table data
127 //
128 for (size_t i = 0; i < rows; i++)
129 {
130 out << std::setw(int(id_width)) << id_column[i];
131
132 for (const auto &[fid, fname]: fields)
133 {
134 const Type::Type_Id type_id = readable.get_field_type
135 (
136 table_id,
137 fid
138 ).get_type_id();
139
140 out << ' ';
142 (
143 out,
144 columns[fid][i],
145 column_width[fid],
146 type_id == Type::Type_Id::string
147 );
148 }
149 out << '\n';
150 }
151 }
152 }
153
154 ////////////////////////////////////////////////////////////////////////////
156 ////////////////////////////////////////////////////////////////////////////
157 (
158 const std::string &command,
159 std::istream &parameters,
160 std::istream &in,
161 std::ostream &out
162 )
163 {
164 if (command == "table") ///////////////////////////////////////////////////
165 {
166 const Table_Id table_id = parse_table(parameters, readable);
167
168 size_t max_column_width = 25;
169 {
170 size_t w;
171 if (parameters >> w)
172 max_column_width = w;
173 }
174
175 Record_Id start = Record_Id{0};
176 size_t length = 0;
177
178 parameters >> start >> length;
179
180 print_table(out, table_id, max_column_width, start, length);
181 }
182 else if (command == "record") /////////////////////////////////////////////
183 {
184 const Table_Id table_id = parse_table(parameters, readable);
185 Record_Id record_id;
186 if (!(parameters >> record_id))
187 record_id = Record_Id::null;
188
189 const auto &freedom = readable.get_freedom(table_id);
190
191 if (!readable.is_used(table_id, record_id))
192 {
193 if (record_id.is_not_null())
194 out << record_id << " is not used.\n";
195 out << "first_used: " << freedom.get_first_used() << '\n';
196 out << "last_used: " << freedom.get_last_used() << '\n';
197 out << "used_count: " << freedom.get_used_count() << '\n';
198 out << "size: " << freedom.get_size() << '\n';
199 out << "dense: " << freedom.is_dense() << '\n';
200 }
201 else
202 {
203 out << "id = " << record_id;
204 out << "; next = " << freedom.get_next(record_id);
205 out << "; previous = " << freedom.get_previous(record_id) << '\n';
206
207 const auto &fields = readable.get_fields(table_id);
208 size_t max_field_size = 0;
209 for (const auto &[fid, fname]: fields)
210 if (fname.size() > max_field_size)
211 max_field_size = fname.size();
212
213 for (const auto &[fid, fname]: fields)
214 {
215 out << std::setw(int(max_field_size)) << fname << ": ";
216 write_value(out, table_id, record_id, fid);
217 out << '\n';
218 }
219 }
220 }
221 else if (command == "schema") /////////////////////////////////////////////
222 {
223 Interpreter_Dump_Writable dump_writable(out);
224 dump(readable, dump_writable, true);
225 }
226 else if (command == "dump") ///////////////////////////////////////////////
227 {
228 Interpreter_Dump_Writable dump_writable(out);
229 dump(readable, dump_writable);
230 }
231 else if (command == "sql") ////////////////////////////////////////////////
232 {
233 SQL_Dump_Writable dump_writable(out);
234 dump(readable, dump_writable);
235 }
236 else if (command == "json") ///////////////////////////////////////////////
237 {
238 bool use_base64 = false;
239 parameters >> use_base64;
240 write_json(out, readable, use_base64);
241 }
242 else if (command == "help") ///////////////////////////////////////////////
243 {
244 out << R"RRR(Displaying data
245~~~~~~~~~~~~~~~
246 table <table_name> [<max_column_width>] [start] [length]
247 record <table_name> [<record_id>]
248 schema
249 dump
250 sql
251 json [<base64>]
252
253)RRR";
254
255 return Status::ok;
256 }
257 else
258 return Status::not_found;
259
260 return Status::done;
261 }
262}
static Table_Id parse_table(std::istream &in, const Readable &readable)
Status process_command(const std::string &command, std::istream &parameters, std::istream &in, std::ostream &out) override
void print_table(std::ostream &out, Table_Id table_id, size_t max_column_width=0, Record_Id start=Record_Id::null, size_t length=0)
constexpr bool is_not_null() const
Definition index_types.h:42
static const Record_Id null
Definition index_types.h:44
void write_justified(std::ostream &out, const std::string &s, size_t width, bool flush_left)
Definition type_io.cpp:161
size_t utf8_display_size(const std::string &s)
Definition type_io.cpp:104
int write_json(std::ostream &out, const Readable &db, bool base64)
Definition json.cpp:16
void dump(const Readable &db, Writable &writable, bool schema_only)
Definition dump.cpp:12
void write_value(std::ostream &out, const Readable &readable, Table_Id table_id, Record_Id record_id, Field_Id field_id)