morph 0.1.0
Asynchronous bridge between GUI thread and business models
Loading...
Searching...
No Matches
query.hpp File Reference

TableQuery, Page and table::apply: a table's sort, filter and page as a request body, and the server's reference implementation. More...

#include <algorithm>
#include <array>
#include <chrono>
#include <concepts>
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <expected>
#include <functional>
#include <limits>
#include <map>
#include <memory>
#include <morph/detail/reflected_member.hpp>
#include <morph/table/data_source.hpp>
#include <morph/table/engine.hpp>
#include <morph/table/filter.hpp>
#include <morph/table/sort.hpp>
#include <morph/util/datetime.hpp>
#include <morph/util/quantity.hpp>
#include <optional>
#include <set>
#include <span>
#include <string>
#include <string_view>
#include <type_traits>
#include <utility>
#include <vector>

Go to the source code of this file.

Classes

struct  morph::table::PageRequest
 Which rows of the view a request wants. More...
struct  morph::table::TableQuery
 A table's sort, filters and page, as a list action's body carries them. More...
struct  morph::table::Page< Row >
 One page of a list action's reply. More...
struct  morph::table::QueryLimits
 The bounds a server applies to every TableQuery, an untrusted body. More...
struct  morph::table::ApplyOptions
 How apply runs. More...
struct  morph::table::PageRows
 The rows of one page, as source row indices. More...
struct  morph::table::detail::IsOptional< T >
 true for std::optional<T>. More...
struct  morph::table::detail::IsOptional< std::optional< T > >
 true for std::optional<T>. More...
class  morph::table::RowsSnapshot< Row >
 A snapshot over a shared, immutable vector of typed rows. More...
class  morph::table::RowsSource< Row >
 A DataSource over typed rows: one column per key glaze writes, its kind inferred from the value's type. More...
struct  morph::table::PageFetch
 A request a PageWindow asks the client to send, tagged with the query it belongs to. More...
class  morph::table::PageWindow< Row >
 The pages a server-mode table holds: those around the visible rows, up to a bound, plus the request state and the last error. More...

Concepts

concept  morph::table::detail::MemberWrapper
 A type glaze writes as one of its own members, as morph's Ranged, Choice, Multiline and Tagged are: its glz::meta value is a member pointer.

Typedefs

template<typename V>
using morph::table::detail::WrappedMember = std::remove_cvref_t<decltype(std::declval<V const&>().*(glz::meta<V>::value))>
 The member a MemberWrapper is written as.
template<typename Row>
using morph::table::detail::CellReader = Cell (*)(Row const&)
 Reads one column's cell from a row.
template<typename Row>
using morph::table::RowKey = std::function<RowId(Row const&)>
 A key projection: the RowId of a typed row.

Functions

TableError morph::table::detail::limitError (std::string column, std::string message)
 A LimitExceeded error.
bool morph::table::detail::entryTooLong (FilterEntry const &entry, std::size_t max)
 Whether any operand of an entry is longer than max bytes.
bool morph::table::detail::anyTooLong (std::span< FilterEntry const > entries, std::size_t max)
 Whether any of entries has an operand longer than max bytes.
std::optional< TableError > morph::table::detail::checkColumn (std::string const &columnId, std::span< ColumnInfo const > columns, std::function< bool(std::string_view)> const &mayRead)
 Checks that a column exists and the principal may read it.
std::optional< TableError > morph::table::detail::checkFilters (FilterSpec const &filters, std::span< ColumnInfo const > columns, QueryLimits const &limits, std::function< bool(std::string_view)> const &mayRead)
 Checks a filter's columns, entry counts and value lengths.
std::expected< TableQuery, TableError > morph::table::validate (TableQuery query, std::span< ColumnInfo const > columns, QueryLimits const &limits={}, std::function< bool(std::string_view)> const &mayRead={})
 Checks query against the table's columns and limits.
std::string morph::table::escapeLikePattern (std::string_view text, char escape='\\')
 Escapes %, _ and the escape character for a SQL LIKE pattern, so a database-backed server keeps them ordinary characters as the filter semantics require.
std::expected< PageRows, TableError > morph::table::apply (DataSource const &source, TableQuery const &query, ApplyOptions const &options={})
 Runs query over source in the calling thread: the reference implementation of server mode.
template<typename T>
constexpr ColumnKind morph::table::detail::kindOf ()
 The column kind a member type gives.
template<typename T>
Cell morph::table::detail::integerCell (T value)
 An integer member as a cell.
template<typename T>
Cell morph::table::detail::writtenCell (T const &value)
 A member as the text glaze writes for it: an enum by its glaze name, a JSON string decoded, null as an empty cell.
template<typename T>
Cell morph::table::detail::toCell (T const &value)
 A member value as a cell.
template<typename Row>
std::vector< CellReader< Row > > morph::table::detail::cellReaders ()
 One cell reader per key glaze writes, in key order.
template<typename Row>
std::vector< ColumnInfo > morph::table::detail::reflectedColumns ()
 One column per key glaze writes, its kind from the value's type.
template<typename Row>
std::expected< Page< Row >, TableError > morph::table::apply (std::vector< Row > const &rows, RowKey< Row > key, TableQuery const &query, ApplyOptions const &options={}, std::map< std::string, ColumnKind, std::less<> > const &kinds={}, std::map< std::string, std::string, std::less<> > const &comparators={})
 Runs query over typed rows and returns the page of rows: what a server's list action returns.

Detailed Description

TableQuery, Page and table::apply: a table's sort, filter and page as a request body, and the server's reference implementation.

In server mode a list action's body embeds a TableQuery and its reply is a Page<Row>. A server implements the action with table::apply over its own rows, or with a database query that honours the same semantics (spec 7 §5–6). validate applies the limits every server applies to an untrusted query. On the client, PageWindow holds the pages fetched around the visible rows.

See docs/spec/table/engine.md.

Definition in file query.hpp.

Typedef Documentation

◆ WrappedMember

template<typename V>
using morph::table::detail::WrappedMember = std::remove_cvref_t<decltype(std::declval<V const&>().*(glz::meta<V>::value))>

The member a MemberWrapper is written as.

Template Parameters
VThe wrapper type.

Definition at line 369 of file query.hpp.

◆ CellReader

template<typename Row>
using morph::table::detail::CellReader = Cell (*)(Row const&)

Reads one column's cell from a row.

Template Parameters
RowThe row type.

Definition at line 466 of file query.hpp.

◆ RowKey

template<typename Row>
using morph::table::RowKey = std::function<RowId(Row const&)>

A key projection: the RowId of a typed row.

Template Parameters
RowThe row type.

Definition at line 503 of file query.hpp.

Function Documentation

◆ limitError()

TableError morph::table::detail::limitError ( std::string column,
std::string message )
inlinenodiscard

A LimitExceeded error.

Parameters
columnThe column concerned, or empty.
messageThe description.
Returns
The error.

Definition at line 121 of file query.hpp.

◆ entryTooLong()

bool morph::table::detail::entryTooLong ( FilterEntry const & entry,
std::size_t max )
inlinenodiscard

Whether any operand of an entry is longer than max bytes.

Parameters
entryThe entry.
maxThe bound.
Returns
true when one is.

Definition at line 130 of file query.hpp.

◆ anyTooLong()

bool morph::table::detail::anyTooLong ( std::span< FilterEntry const > entries,
std::size_t max )
inlinenodiscard

Whether any of entries has an operand longer than max bytes.

Parameters
entriesThe entries.
maxThe bound.
Returns
true when one has.

Definition at line 141 of file query.hpp.

◆ checkColumn()

std::optional< TableError > morph::table::detail::checkColumn ( std::string const & columnId,
std::span< ColumnInfo const > columns,
std::function< bool(std::string_view)> const & mayRead )
inlinenodiscard

Checks that a column exists and the principal may read it.

Parameters
columnIdThe column's id.
columnsThe row schema's columns.
mayReadWhether the principal may read a column; empty allows every column.
Returns
The error, or nothing.

Definition at line 150 of file query.hpp.

◆ checkFilters()

std::optional< TableError > morph::table::detail::checkFilters ( FilterSpec const & filters,
std::span< ColumnInfo const > columns,
QueryLimits const & limits,
std::function< bool(std::string_view)> const & mayRead )
inlinenodiscard

Checks a filter's columns, entry counts and value lengths.

Parameters
filtersThe filter.
columnsThe row schema's columns.
limitsThe bounds.
mayReadWhether the principal may read a column.
Returns
The first violation, or nothing.

Definition at line 170 of file query.hpp.

◆ validate()

std::expected< TableQuery, TableError > morph::table::validate ( TableQuery query,
std::span< ColumnInfo const > columns,
QueryLimits const & limits = {},
std::function< bool(std::string_view)> const & mayRead = {} )
inlinenodiscard

Checks query against the table's columns and limits.

Every column named must be one of columns, a closed set, and one the principal may read: a filter on a hidden column is an oracle for its value, so hiding a column is not a security control. page.limit is clamped; every other bound is a refusal.

Parameters
queryThe query, as received.
columnsThe row schema's columns.
limitsThe bounds.
mayReadWhether the principal may read a column; empty allows every column.
Returns
The query with its limit clamped, or the first violation.

Definition at line 220 of file query.hpp.

◆ escapeLikePattern()

std::string morph::table::escapeLikePattern ( std::string_view text,
char escape = '\\' )
inlinenodiscard

Escapes %, _ and the escape character for a SQL LIKE pattern, so a database-backed server keeps them ordinary characters as the filter semantics require.

Parameters
textA filter value.
escapeThe ESCAPE character the query declares.
Returns
The escaped text; wrap it in % for contains and so on.

Definition at line 250 of file query.hpp.

◆ apply() [1/2]

std::expected< PageRows, TableError > morph::table::apply ( DataSource const & source,
TableQuery const & query,
ApplyOptions const & options = {} )
inlinenodiscard

Runs query over source in the calling thread: the reference implementation of server mode.

Parameters
sourceThe server's rows.
queryThe request body's table query.
optionsLimits, services and column access.
Returns
The page, or the typed error the client shows.

Definition at line 289 of file query.hpp.

◆ kindOf()

template<typename T>
ColumnKind morph::table::detail::kindOf ( )
nodiscardconstexpr

The column kind a member type gives.

Template Parameters
TThe member type.
Returns
The kind.

Definition at line 375 of file query.hpp.

◆ integerCell()

template<typename T>
Cell morph::table::detail::integerCell ( T value)
nodiscard

An integer member as a cell.

Template Parameters
TThe integer type.
Parameters
valueThe member.
Returns
The cell: an int64, or text that an integer column reads as invalid when no int64 holds the value (rather than a wrapped negative number).

Definition at line 405 of file query.hpp.

◆ writtenCell()

template<typename T>
Cell morph::table::detail::writtenCell ( T const & value)
nodiscard

A member as the text glaze writes for it: an enum by its glaze name, a JSON string decoded, null as an empty cell.

Template Parameters
TThe member type.
Parameters
valueThe member.
Returns
The cell.

Definition at line 420 of file query.hpp.

◆ toCell()

template<typename T>
Cell morph::table::detail::toCell ( T const & value)
nodiscard

A member value as a cell.

Template Parameters
TThe member type.
Parameters
valueThe member.
Returns
The cell.

Definition at line 439 of file query.hpp.

◆ cellReaders()

template<typename Row>
std::vector< CellReader< Row > > morph::table::detail::cellReaders ( )
nodiscard

One cell reader per key glaze writes, in key order.

Template Parameters
RowThe row type.
Returns
The readers.

Definition at line 472 of file query.hpp.

◆ reflectedColumns()

template<typename Row>
std::vector< ColumnInfo > morph::table::detail::reflectedColumns ( )
nodiscard

One column per key glaze writes, its kind from the value's type.

Template Parameters
RowThe row type.
Returns
The columns.

Definition at line 484 of file query.hpp.

◆ apply() [2/2]

template<typename Row>
std::expected< Page< Row >, TableError > morph::table::apply ( std::vector< Row > const & rows,
RowKey< Row > key,
TableQuery const & query,
ApplyOptions const & options = {},
std::map< std::string, ColumnKind, std::less<> > const & kinds = {},
std::map< std::string, std::string, std::less<> > const & comparators = {} )
nodiscard

Runs query over typed rows and returns the page of rows: what a server's list action returns.

Template Parameters
RowA glaze-reflectable aggregate.
Parameters
rowsThe server's rows; read during the call only.
keyThe key projection.
queryThe request body's table query.
optionsLimits, services and column access.
kindsColumn kinds that replace the inferred ones.
comparatorsComparator names by column id; a column named here is Custom.
Returns
The page, or the typed error the client shows.

Definition at line 644 of file query.hpp.