3#include "../query/core.hpp"
22 LazyCell(std::string_view raw_data,
size_t start_pos,
size_t end_pos)
23 : raw_data_(raw_data), start_pos_(start_pos), end_pos_(end_pos) {}
28 return value ==
"NULL";
33 return std::string(raw_data_.substr(start_pos_, end_pos_ - start_pos_));
47 return temp_cell.template as<T>(allow_numeric_bools);
51 std::string_view raw_data_;
60 LazyRow() : raw_data_(
""), column_names_({}), cells_parsed_(
false), owns_data_(
false) {}
64 : raw_data_(raw_data), column_names_(
std::move(
column_names)), cells_parsed_(false),
69 : raw_data_(), owned_data_(
std::move(owned_data)), column_names_(
std::move(
column_names)),
70 cells_parsed_(false), owns_data_(true) {
71 raw_data_ = owned_data_;
76 : raw_data_(other.raw_data_), owned_data_(other.owned_data_),
77 column_names_(other.column_names_), cell_positions_(other.cell_positions_),
78 cells_parsed_(other.cells_parsed_), owns_data_(other.owns_data_) {
81 raw_data_ = owned_data_;
88 raw_data_ = other.raw_data_;
89 owned_data_ = other.owned_data_;
90 column_names_ = other.column_names_;
91 cell_positions_ = other.cell_positions_;
92 cells_parsed_ = other.cells_parsed_;
93 owns_data_ = other.owns_data_;
97 raw_data_ = owned_data_;
105 : raw_data_(other.raw_data_), owned_data_(std::move(other.owned_data_)),
106 column_names_(std::move(other.column_names_)),
107 cell_positions_(std::move(other.cell_positions_)), cells_parsed_(other.cells_parsed_),
108 owns_data_(other.owns_data_) {
111 raw_data_ = owned_data_;
113 other.owns_data_ =
false;
118 if (
this != &other) {
119 raw_data_ = other.raw_data_;
120 owned_data_ = std::move(other.owned_data_);
121 column_names_ = std::move(other.column_names_);
122 cell_positions_ = std::move(other.cell_positions_);
123 cells_parsed_ = other.cells_parsed_;
124 owns_data_ = other.owns_data_;
128 raw_data_ = owned_data_;
131 other.owns_data_ =
false;
138 ensure_cells_parsed();
140 if (
index >= cell_positions_.size()) {
141 return std::unexpected(
ResultError{
"Cell index out of range"});
144 const auto& [start, end] = cell_positions_[
index];
145 return LazyCell(raw_data_, start, end);
150 if (column_names_.empty()) {
151 return std::unexpected(
ResultError{
"Column names not available"});
154 for (
size_t i = 0; i < column_names_.size(); ++i) {
155 if (column_names_[i] == name) {
160 return std::unexpected(
ResultError{
"Column name not found: " + name});
164 template <
typename T>
166 return get<T>(
index,
false);
170 template <
typename T>
174 return std::unexpected(cell.error());
176 return cell->template as<T>(allow_numeric_bools);
180 template <
typename T>
182 return get<T>(name,
false);
186 template <
typename T>
190 return std::unexpected(cell.error());
192 return cell->template as<T>(allow_numeric_bools);
197 ensure_cells_parsed();
198 return cell_positions_.size();
202 const std::vector<std::string>&
column_names()
const {
return column_names_; }
205 mutable std::string_view raw_data_;
206 std::string owned_data_;
207 std::vector<std::string> column_names_;
208 mutable std::vector<std::pair<size_t, size_t>> cell_positions_;
209 mutable bool cells_parsed_;
212 void ensure_cells_parsed()
const {
213 if (cells_parsed_)
return;
219 while (pos < raw_data_.size()) {
220 if (raw_data_[pos] ==
'|') {
221 cell_positions_.emplace_back(start, pos);
228 if (start < raw_data_.size()) {
229 cell_positions_.emplace_back(start, raw_data_.size());
232 cells_parsed_ =
true;
240 LazyResultSet(std::string raw_data) : raw_data_(
std::move(raw_data)), rows_parsed_(false) {}
244 ensure_rows_parsed();
245 return row_positions_.size();
253 ensure_rows_parsed();
255 if (
index >= row_positions_.size()) {
256 return std::unexpected(
ResultError{
"Row index out of range"});
259 const auto& [start,
end] = row_positions_[
index];
260 std::string_view row_data(raw_data_.data() + start,
end - start);
261 return LazyRow(row_data, column_names_);
277 ensure_rows_parsed();
278 return column_names_;
285 : result_set_(result_set), index_(
index) {}
288 auto result = result_set_.
at(index_);
315 std::vector<Row> rows;
316 rows.reserve(
size());
318 for (
size_t i = 0; i <
size(); ++i) {
319 auto lazy_row_result =
at(i);
320 if (!lazy_row_result) {
321 return std::unexpected(lazy_row_result.error());
324 auto lazy_row = *lazy_row_result;
325 std::vector<Cell> cells;
326 cells.reserve(lazy_row.size());
328 for (
size_t j = 0; j < lazy_row.size(); ++j) {
329 auto lazy_cell = lazy_row.get_cell(j);
331 cells.emplace_back(lazy_cell->get_raw_value());
333 return std::unexpected(
ResultError{
"Failed to get cell at index " + std::to_string(j)});
337 rows.emplace_back(std::move(cells), column_names_);
340 return ResultSet(std::move(rows), column_names_);
344 std::string raw_data_;
345 mutable std::vector<std::pair<size_t, size_t>> row_positions_;
346 mutable std::vector<std::string> column_names_;
347 mutable bool rows_parsed_;
349 void ensure_rows_parsed()
const {
350 if (rows_parsed_)
return;
354 size_t line_start = 0;
355 bool first_line =
true;
357 while (pos <= raw_data_.size()) {
358 if (pos == raw_data_.size() || raw_data_[pos] ==
'\n') {
359 if (pos > line_start) {
360 std::string_view line(raw_data_.data() + line_start, pos - line_start);
364 parse_column_names(line);
366 }
else if (!line.empty()) {
368 row_positions_.emplace_back(line_start, pos);
371 line_start = pos + 1;
379 void parse_column_names(std::string_view header_line)
const {
383 while (pos < header_line.size()) {
384 if (header_line[pos] ==
'|') {
386 column_names_.emplace_back(header_line.substr(start, pos - start));
394 if (start < header_line.size()) {
395 column_names_.emplace_back(header_line.substr(start));
405template <query::SqlExpr Query>
Represents a single cell value from a database result.
Lazy cell that defers parsing until accessed.
std::string get_raw_value() const
Get the raw string value (parsed on demand)
bool is_null() const
Check if the cell contains a NULL value.
ResultProcessingResult< T > as(bool allow_numeric_bools) const
Parse the cell's value as the specified type with boolean conversion options.
LazyCell(std::string_view raw_data, size_t start_pos, size_t end_pos)
Constructs a lazy cell with raw data and parsing context.
ResultProcessingResult< T > as() const
Parse the cell's value as the specified type.
iterator(const LazyResultSet &result_set, size_t index)
bool operator!=(const iterator &other) const
LazyRow operator*() const
Lazy result set that defers row parsing until accessed.
ResultProcessingResult< LazyRow > at(size_t index) const
Get a row by index (parsed on demand)
LazyResultSet(std::string raw_data)
Constructs a lazy result set with raw data.
const std::vector< std::string > & column_names() const
Get the column names.
bool empty() const
Check if the result set is empty.
LazyRow operator[](size_t index) const
Access a row by index using the subscript operator.
size_t size() const
Get the number of rows (requires parsing row boundaries)
ResultProcessingResult< ResultSet > to_result_set() const
Transform to regular ResultSet if needed.
Lazy row that defers cell parsing until accessed.
ResultProcessingResult< T > get(size_t index) const
Get a typed value by index.
ResultProcessingResult< LazyCell > get_cell(const std::string &name) const
Get a cell by column name.
LazyRow(std::string_view raw_data, std::vector< std::string > column_names={})
Constructs a lazy row with raw data and column information.
LazyRow(std::string owned_data, std::vector< std::string > column_names)
Constructs a lazy row that owns its data (for streaming)
size_t size() const
Get the number of cells in this row.
ResultProcessingResult< T > get(const std::string &name) const
Get a typed value by column name.
ResultProcessingResult< LazyCell > get_cell(size_t index) const
Get a cell by index (parsed on demand)
LazyRow(LazyRow &&other) noexcept
Move constructor.
const std::vector< std::string > & column_names() const
Get the column names.
LazyRow()
Default constructor.
ResultProcessingResult< T > get(const std::string &name, bool allow_numeric_bools) const
Get a typed value by column name with boolean conversion options.
LazyRow & operator=(const LazyRow &other)
Copy assignment operator.
LazyRow & operator=(LazyRow &&other) noexcept
Move assignment operator.
ResultProcessingResult< T > get(size_t index, bool allow_numeric_bools) const
Get a typed value by index with boolean conversion options.
LazyRow(const LazyRow &other)
Copy constructor.
Represents the result set from a database query.
Represents an index on a table.
LazyResultSet parse_lazy(const Query &, std::string raw_results)
Parse raw results from a database into a lazy ResultSet.
std::expected< T, ResultError > ResultProcessingResult
Type alias for result of processing operations.
Error type for result processing operations.