34             "only booleans and bitmaps may not be byte aligned");
 
   36             "only booleans and bitmaps may not be byte aligned");
 
   38    auto leaf = 
new Leaf(type, idx);
 
   40        .
ptr = std::unique_ptr<DataLayout::Node>(as<Node>(leaf)),
 
   41        .offset_in_bits = offset_in_bits,
 
   49    M_insist(
num_tuples != 0, 
"the new INode must be large enough for at least one tuple");
 
   52             "the number of tuples in the parent must be a whole multiple of the number of tuples of the newly created " 
   54    M_insist(offset_in_bits % 8 == 0, 
"the offset of the newly created INode must be byte aligned");
 
   59        .
ptr = std::unique_ptr<DataLayout::Node>(as<Node>(inode)),
 
   60        .offset_in_bits = offset_in_bits,
 
   71    std::vector<leaf_info_t> leaves;
 
   72    leaves.reserve(this->num_children());
 
   74    for (
auto &
child : *
this) {
 
   75        if (
auto child_leaf = cast<const Leaf>(
child.ptr.get())) {
 
   78                .offset_in_bits = 
child.offset_in_bits,
 
   79                .stride_in_bits = 
child.stride_in_bits,
 
   82            auto child_inode = as<const INode>(
child.ptr.get());
 
   87            child_inode->for_sibling_leaves(level_info_stack, inode_offset_in_bits + 
child.offset_in_bits, callback);
 
   88            level_info_stack.pop_back();
 
   92    if (not leaves.empty())
 
   93        callback(leaves, level_info_stack, inode_offset_in_bits);
 
  100std::ostream & 
indent(std::ostream &out, 
unsigned indentation)
 
  102    out << 
'\n' << std::string(4 * indentation, 
' ');
 
  113    for (std::size_t i = 0; i != num_children(); ++i, ++it) {
 
  116        indent(out, indentation) << 
"[" << std::setw(decimal_places) << i << 
"]: ";
 
  119        if (
auto child_leaf = cast<const Leaf>(
child.ptr.get())) {
 
  120            out << 
"Leaf " << child_leaf->index() << 
" of type " << *child_leaf->type() << 
" with bit offset " 
  121                << 
child.offset_in_bits << 
" and bit stride " << 
child.stride_in_bits;
 
  123            auto child_inode = as<const INode>(
child.ptr.get());
 
  124            out << 
"INode of " << child_inode->num_tuples() << 
" tuple(s) with bit offset " << 
child.offset_in_bits
 
  125                << 
" and bit stride " << 
child.stride_in_bits;
 
  126            child_inode->print(out, indentation + 1);
 
  146    M_insist(
num_tuples != 0, 
"the new INode must be large enough for at least one tuple");
 
  152        .
ptr = std::unique_ptr<DataLayout::Node>(as<Node>(inode)),
 
  174    const bool needs_null_bitmap = [&]() {
 
  186        if (
auto child_inode = cast<const DataLayout::INode>(inode[0].ptr.get());
 
  189            return rec(*child_inode, rec); 
 
  192        std::size_t num_simd_lanes = 1;
 
  193        for (
auto &
child : inode) {
 
  194            if (cast<const DataLayout::INode>(
child.ptr.get()))
 
  197            auto &child_leaf = as<const DataLayout::Leaf>(*
child.ptr);
 
  198            const uint8_t bit_stride = 
child.stride_in_bits % 8;
 
  200                if (not needs_null_bitmap)
 
  210                    if (
child.offset_in_bits % 8 != 0)
 
  214                num_simd_lanes = std::max<std::size_t>(num_simd_lanes, 16); 
 
  219                M_insist(*tuple_it->type == *child_leaf.type());
 
  222                    if (
child.stride_in_bits != 1)
 
  225                    if (tuple_it->type->is_boolean() 
and child.stride_in_bits != 8)
 
  227                    if (tuple_it->type->is_character_sequence())
 
  231                const uint64_t size_in_bytes = (tuple_it->type->size() + 7) / 8;
 
  232                num_simd_lanes = std::max<std::size_t>(num_simd_lanes, 16 / size_in_bytes); 
 
  236        if (inode.num_tuples() % num_simd_lanes != 0)
 
  241    return test_simd_support(
static_cast<const DataLayout::INode&
>(layout), test_simd_support);
 
  248             "layout must support SIMD to retrieve its number of SIMD lanes");
 
  250    std::size_t num_simd_lanes = 1;
 
  255        const uint64_t size_in_bytes = (tuple_entry.type->size() + 7) / 8;
 
  256        num_simd_lanes = std::max<std::size_t>(num_simd_lanes, 16 / size_in_bytes); 
 
  259    return num_simd_lanes;
 
std::ostream & indent(std::ostream &out, unsigned indentation)
Start a new line with proper indentation.
 
const Schema const Schema & tuple_schema
 
std::size_t get_num_simd_lanes(const DataLayout &layout, const Schema &layout_schema, const Schema &tuple_schema)
Returns the number of SIMD lanes used for accessing tuples of schema tuple_schema in SIMDfied manner ...
 
const Schema & layout_schema
 
static constexpr float DECIMAL_TO_BINARY_DIGITS
How many binary digits fit into a single decimal digit.
 
A Schema represents a sequence of identifiers, optionally with a prefix, and their associated types.
 
std::size_t num_entries() const
Returns the number of entries in this Schema.
 
iterator find(const Identifier &id)
Returns an iterator to the entry with the given Identifier id, or end() if no such entry exists.
 
This class represents types in the SQL type system.
 
a child Node and its relative offset and stride within the containing INode
 
std::unique_ptr< Node > ptr
 
An internal node of the recursive data layout model.
 
std::vector< child_t > children_
the child Nodes of this INode
 
void print(std::ostream &out, unsigned indentation=0) const
 
size_type num_tuples() const override
returns the number of tuples represented by an instance of this node
 
Leaf & add_leaf(const m::Type *type, size_type idx, uint64_t offset_in_bits, uint64_t stride_in_bits)
Creates a Leaf and adds it as a child to this INode.
 
void for_sibling_leaves(level_info_stack_t &level_info_stack, uint64_t inode_offset_in_bits, const callback_leaves_t &callback) const
 
void accept(ConstDataLayoutVisitor &v) const override
 
INode & add_inode(size_type num_tuples, uint64_t offset_in_bits, uint64_t stride_in_bits)
Creates an INode and adds it as a child to this INode.
 
size_type num_children() const
returns the number of child Nodes of this INode
 
The Leaf represents exactly one attribue.
 
void accept(ConstDataLayoutVisitor &v) const override
 
virtual size_type num_tuples() const =0
returns the number of tuples represented by an instance of this node
 
combines information of a single leaf for for_sibling_leaves()
 
combines information of a single internal level inside the DataLayout, used by for_sibling_leaves()
 
uint64_t stride_in_bits
the stride of instances of this level
 
Models how data is laid out in a linear address space.
 
INode inode_
use an INode to store a single child, allowing us to exploit INode abstractions within DataLayout
 
uint64_t stride_in_bits() const
return the stride (in bits) of the single child of the DataLayout
 
const Node & child() const
returns a reference to the single child of this DataLayout
 
INode & add_inode(size_type num_tuples, uint64_t stride_in_bits)
Creates an INode and adds it as a child to this DataLayout's internal INode.
 
size_type num_tuples() const
returns the number of tuples laid out by this DataLayout; must not be called when not is_finite()
 
std::vector< level_info_t > level_info_stack_t
 
Leaf & add_leaf(const m::Type *type, size_type idx, uint64_t stride_in_bits)
Creates a Leaf and adds it as a child to this DataLayout's internal INode.
 
std::function< void(const std::vector< leaf_info_t > &leaves, const level_info_stack_t &levels, uint64_t inode_offset_in_bits)> callback_leaves_t
 
void for_sibling_leaves(callback_leaves_t callback) const
 
void accept(ConstDataLayoutVisitor &v) const