Joedb 10.0.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 const std::string &command,
36 std::istream &parameters,
37 std::istream &in,
38 std::ostream &out
39 )
40 {
41 if (command == "table") ///////////////////////////////////////////////////
42 {
43 const Table_Id table_id = parse_table(parameters, readable);
44
45 size_t max_column_width = 25;
46 {
47 size_t w;
48 if (parameters >> w)
49 max_column_width = w;
50 }
51
52 Record_Id start = Record_Id{0};
53 size_t length = 0;
54
55 parameters >> start >> length;
56
57 if (table_id != Table_Id(0))
58 {
59 const auto &fields = readable.get_fields(table_id);
60 std::map<Field_Id, size_t> column_width;
61
62 for (const auto &[fid, fname]: fields)
63 column_width[fid] = fname.size();
64
65 //
66 // Store values in strings to determine column widths
67 //
68 std::map<Field_Id, std::vector<std::string>> columns;
69 std::vector<Record_Id> id_column;
70
71 size_t rows = 0;
72 const Record_Id size = readable.get_size(table_id);
73 for (Record_Id record_id{0}; record_id < size; ++record_id)
74 {
75 if
76 (
77 readable.is_used(table_id, record_id) &&
78 (length == 0 || (record_id >= start && record_id < start + length))
79 )
80 {
81 rows++;
82 id_column.emplace_back(record_id);
83
84 for (const auto &[fid, fname]: fields)
85 {
86 std::ostringstream ss;
87 write_value(ss, table_id, record_id, fid);
88 ss.flush();
89 const std::string &s = ss.str();
90 const size_t width = utf8_display_size(s);
91 if (column_width[fid] < width)
92 column_width[fid] = width;
93 columns[fid].emplace_back(s);
94 }
95 }
96 }
97
98 //
99 // Determine table width
100 //
101 size_t id_width = 0;
102 {
103 std::ostringstream ss;
104 ss << size - 1;
105 ss.flush();
106 id_width = ss.str().size();
107 }
108 size_t table_width = id_width;
109 for (const auto &[fid, fname]: fields)
110 {
111 if (max_column_width && column_width[fid] > max_column_width)
112 column_width[fid] = max_column_width;
113 table_width += column_width[fid] + 1;
114 }
115
116 //
117 // Table header
118 //
119 out << std::string(table_width, '-') << '\n';
120 out << std::string(id_width, ' ');
121 for (const auto &[fid, fname]: fields)
122 {
123 const Type::Type_Id type_id = readable.get_field_type
124 (
125 table_id,
126 fid
127 ).get_type_id();
128 out << ' ';
130 (
131 out,
132 fname,
133 column_width[fid],
134 type_id == Type::Type_Id::string
135 );
136 }
137 out << '\n';
138 out << std::string(table_width, '-') << '\n';
139
140 //
141 // Table data
142 //
143 for (size_t i = 0; i < rows; i++)
144 {
145 out << std::setw(int(id_width)) << id_column[i];
146
147 for (const auto &[fid, fname]: fields)
148 {
149 const Type::Type_Id type_id = readable.get_field_type
150 (
151 table_id,
152 fid
153 ).get_type_id();
154
155 out << ' ';
157 (
158 out,
159 columns[fid][i],
160 column_width[fid],
161 type_id == Type::Type_Id::string
162 );
163 }
164 out << '\n';
165 }
166 }
167 }
168 else if (command == "record") /////////////////////////////////////////////
169 {
170 const Table_Id table_id = parse_table(parameters, readable);
171 Record_Id record_id;
172 if (!(parameters >> record_id))
173 record_id = Record_Id::null;
174
175 const auto &freedom = readable.get_freedom(table_id);
176
177 if (!readable.is_used(table_id, record_id))
178 {
179 if (record_id.is_not_null())
180 out << record_id << " is not used.\n";
181 out << "first_used: " << freedom.get_first_used() << '\n';
182 out << "last_used: " << freedom.get_last_used() << '\n';
183 out << "used_count: " << freedom.get_used_count() << '\n';
184 out << "size: " << freedom.get_size() << '\n';
185 out << "dense: " << freedom.is_dense() << '\n';
186 }
187 else
188 {
189 out << "id = " << record_id;
190 out << "; next = " << freedom.get_next(record_id);
191 out << "; previous = " << freedom.get_previous(record_id) << '\n';
192
193 const auto &fields = readable.get_fields(table_id);
194 size_t max_field_size = 0;
195 for (const auto &[fid, fname]: fields)
196 if (fname.size() > max_field_size)
197 max_field_size = fname.size();
198
199 for (const auto &[fid, fname]: fields)
200 {
201 out << std::setw(int(max_field_size)) << fname << ": ";
202 write_value(out, table_id, record_id, fid);
203 out << '\n';
204 }
205 }
206 }
207 else if (command == "schema") /////////////////////////////////////////////
208 {
209 Interpreter_Dump_Writable dump_writable(out);
210 dump(readable, dump_writable, true);
211 }
212 else if (command == "dump") ///////////////////////////////////////////////
213 {
214 Interpreter_Dump_Writable dump_writable(out);
215 dump(readable, dump_writable);
216 }
217 else if (command == "sql") ////////////////////////////////////////////////
218 {
219 SQL_Dump_Writable dump_writable(out);
220 dump(readable, dump_writable);
221 }
222 else if (command == "json") ///////////////////////////////////////////////
223 {
224 bool use_base64 = false;
225 parameters >> use_base64;
226 write_json(out, readable, use_base64);
227 }
228 else if (command == "help") ///////////////////////////////////////////////
229 {
230 out << R"RRR(Displaying data
231~~~~~~~~~~~~~~~
232 table <table_name> [<max_column_width>] [start] [length]
233 record <table_name> [<record_id>]
234 schema
235 dump
236 sql
237 json [<base64>]
238
239)RRR";
240
241 return Status::ok;
242 }
243 else
244 return Status::not_found;
245
246 return Status::done;
247 }
248}
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
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)
Definition Blob.h:7