mutable
A Database System for Research and Fast Prototyping
Loading...
Searching...
No Matches
Interpreter.hpp
Go to the documentation of this file.
1#pragma once
2
5#include <cerrno>
6#include <ctime>
10#include <mutable/IR/Tuple.hpp>
12#include <unordered_map>
13
14
15namespace m {
16
18template<std::size_t N>
19struct Block
20{
21 static constexpr std::size_t CAPACITY = N;
22
23 private:
24 template<bool C>
26 {
27 static constexpr bool IsConst = C;
28
29 using block_t = std::conditional_t<IsConst, const Block, Block>;
30 using reference = std::conditional_t<IsConst, const Tuple&, Tuple&>;
31 using pointer = std::conditional_t<IsConst, const Tuple*, Tuple*>;
32
33 private:
35 uint64_t mask_;
36
37 public:
38 the_iterator(block_t &vec, uint64_t mask) : block_(vec), mask_(mask) { }
39
41 M_insist(&this->block_ == &other.block_);
42 return this->mask_ == other.mask_;
43 }
44 bool operator!=(the_iterator other) { return not operator==(other); }
45
46 the_iterator & operator++() { mask_ = mask_ & (mask_ - 1UL); /* set lowest 1-bit to 0 */ return *this; }
47 the_iterator operator++(int) { the_iterator clone(*this); operator++(); return clone; }
48
49 std::size_t index() const { return __builtin_ctzl(mask_); }
50
51 reference operator*() const { return block_[index()]; }
52 pointer operator->() const { return &block_[index()]; }
53 };
54
55 public:
58
59 private:
60 std::array<Tuple, N> data_;
61 uint64_t mask_ = 0x0;
62 static_assert(N <= 64, "maximum block size exceeded");
64
65 public:
66 Block() = default;
67 Block(const Block&) = delete;
68 Block(Block&&) = delete;
69
72 : schema_(std::move(schema))
73 {
74 for (auto &t : data_)
75 t = Tuple(schema_);
76 }
77
79 Tuple * data() { return data_.data(); }
81 const Tuple * data() const { return data_.data(); }
82
83 const Schema & schema() const { return schema_; }
84
86 static constexpr std::size_t capacity() { return CAPACITY; }
88 std::size_t size() const { return __builtin_popcountl(mask_); }
89
90 iterator begin() { return iterator(*this, mask_); }
91 iterator end() { return iterator(*this, 0UL); }
92 const_iterator begin() const { return const_iterator(*this, mask_); }
93 const_iterator end() const { return const_iterator(*this, 0UL); }
94 const_iterator cbegin() const { return const_iterator(*this, mask_); }
95 const_iterator cend() const { return const_iterator(*this, 0UL); }
96
98 iterator at(std::size_t index) {
99 M_insist(index < capacity());
100 return iterator(*this, mask_ & (-1UL << index));
101 }
103 const_iterator at(std::size_t index) const { return const_cast<Block>(this)->at(index); }
104
106 bool alive(std::size_t index) const {
107 M_insist(index < capacity());
108 return mask_ & (1UL << index);
109 }
110
112 bool empty() const { return size() == 0; }
113
115 uint64_t mask() const { return mask_; }
117 void mask(uint64_t new_mask) { mask_ = new_mask; }
118
119 private:
121 static constexpr uint64_t AllOnes() { return -1UL >> (8 * sizeof(mask_) - capacity()); }
122
123 public:
125 Tuple & operator[](std::size_t index) {
126 M_insist(index < capacity(), "index out of bounds");
127 M_insist(alive(index), "cannot access a dead tuple directly");
128 return data_[index];
129 }
131 const Tuple & operator[](std::size_t index) const { return const_cast<Block*>(this)->operator[](index); }
132
134 void fill() { mask_ = AllOnes(); M_insist(size() == capacity()); }
135
137 void erase(std::size_t index) {
138 M_insist(index < capacity(), "index out of bounds");
139 setbit(&mask_, false, index);
140 }
142 void erase(iterator it) { erase(it.index()); }
144 void erase(const_iterator it) { erase(it.index()); }
145
147 void clear() {
148 mask_ = 0;
149 for (auto &t : data_)
150 t.clear();
151 }
152
155 friend std::ostream & operator<<(std::ostream &out, const Block<N> &block) {
156 out << "Block<" << block.capacity() << "> with " << block.size() << " elements:\n";
157 for (std::size_t i = 0; i != block.capacity(); ++i) {
158 out << " " << i << ": ";
159 if (block.alive(i))
160 out << block[i];
161 else
162 out << "[dead]";
163 out << '\n';
164 }
165 return out;
166 }
167
168 void dump(std::ostream &out) const
169 {
170 out << *this;
171 out.flush();
172 }
173 void dump() const { dump(std::cerr); }
175};
176
177struct Interpreter;
178
181{
182 friend struct Interpreter;
183
184 private:
186
187 public:
189
191 : block_(schema)
192 {
193 block_.mask(1UL); // create one empty tuple in the block
194 }
195
197 {
198 block_.mask(1UL);
199 block_[0] = std::move(t);
200 }
201
202 void push(const Operator &pipeline_start) { (*this)(pipeline_start); }
203
204 void clear() { block_.clear(); }
205
206 const Schema & schema() const { return block_.schema(); }
207
208 using ConstOperatorVisitor::operator();
209#define DECLARE(CLASS) void operator()(Const<CLASS> &op) override;
211#undef DECLARE
212};
213
216{
217 public:
218 Interpreter() = default;
219
220 void register_operators(PhysicalOptimizer &phys_opt) const override { register_interpreter_operators(phys_opt); }
221
222 void execute(const MatchBase &plan) const override {
223 (*const_cast<Interpreter*>(this))(plan.get_matched_root()); // use former visitor pattern on logical operators
224 }
225
226 using ConstOperatorVisitor::operator();
227#define DECLARE(CLASS) void operator()(Const<CLASS> &op) override;
229#undef DECLARE
230
231 static Value eval(const ast::Constant &c)
232 {
233 errno = 0;
234 switch (c.tok.type) {
235 default: M_unreachable("illegal token");
236
237 /* Null */
238 case TK_Null:
239 M_unreachable("NULL cannot be evaluated to a Value");
240
241 /* Integer */
242 case TK_OCT_INT:
243 return int64_t(strtoll(*c.tok.text, nullptr, 8));
244
245 case TK_DEC_INT:
246 return int64_t(strtoll(*c.tok.text, nullptr, 10));
247
248 case TK_HEX_INT:
249 return int64_t(strtoll(*c.tok.text, nullptr, 16));
250
251 /* Float */
252 case TK_DEC_FLOAT:
253 return strtod(*c.tok.text, nullptr);
254
255 case TK_HEX_FLOAT:
256 M_unreachable("not implemented");
257
258 /* String */
259 case TK_STRING_LITERAL: {
260 std::string str(*c.tok.text);
261 auto substr = interpret(str);
262 return Catalog::Get().pool(substr.c_str()); // return internalized string by reference
263 }
264
265 /* Date */
266 case TK_DATE: {
267 int year, month, day;
268 if (3 != sscanf(*c.tok.text, "d'%d-%d-%d'", &year, &month, &day))
269 M_unreachable("invalid date");
270 return int32_t(unsigned(year) << 9 | month << 5 | day);
271 }
272
273 /* Datetime */
274 case TK_DATE_TIME: {
275 /* Extract date time from string. */
276 std::string str_datetime(*c.tok.text);
277 std::istringstream ss(str_datetime.substr(2, str_datetime.length() - 3));
278
279 /* Parse date time. */
280 std::tm tm;
281 ss >> get_tm(tm);
282 M_insist(not ss.fail(), "failed to parse date time");
283
284#if defined(__APPLE__)
285 /* Adapt tm_year such that it is non-negative (i.e. >= 1900) since timegm() cannot handle these cases. */
286 constexpr long SECONDS_PER_400_YEAR_CYCLE = 12622780800L;
287 int cycles = tm.tm_year < 0 ? -tm.tm_year / 400 + 1 : 0;
288 tm.tm_year += cycles * 400;
289 M_insist(tm.tm_year >= 0);
290#endif
291
292 /* Convert date time from std::tm to time_t (seconds since epoch). */
293 const time_t time = timegm(&tm);
294 M_insist(time != -1, "datetime out of bounds");
295
296#if defined(__APPLE__)
297 return int64_t(time - cycles * SECONDS_PER_400_YEAR_CYCLE);
298#else
299 return int64_t(time);
300#endif
301 }
302
303 /* Boolean */
304 case TK_True:
305 return true;
306
307 case TK_False:
308 return false;
309 }
310 M_insist(errno == 0, "constant could not be parsed");
311 }
312
323 static StackMachine compile_load(const Schema &tuple_schema, void *address, const storage::DataLayout &layout,
324 const Schema &layout_schema, std::size_t row_id = 0, std::size_t tuple_id = 0);
325
336 static StackMachine compile_store(const Schema &tuple_schema, void *address, const storage::DataLayout &layout,
337 const Schema &layout_schema, std::size_t row_id = 0, std::size_t tuple_id = 0);
338};
339
340}
#define M_OPERATOR_LIST(X)
Definition: Operator.hpp:560
#define DECLARE(CLASS)
Check whether.
Definition: concepts.hpp:39
#define M_unreachable(MSG)
Definition: macro.hpp:146
#define M_insist(...)
Definition: macro.hpp:129
‍mutable namespace
Definition: Backend.hpp:10
std::string interpret(const std::string &str, char esc='\\', char quote='"')
Definition: fn.hpp:319
void M_EXPORT setbit(T *bytes, bool value, uint32_t n)
Definition: fn.hpp:442
STL namespace.
Defines the interface of all execution Backends.
Definition: Backend.hpp:17
static constexpr bool IsConst
Definition: Interpreter.hpp:27
std::size_t index() const
Definition: Interpreter.hpp:49
pointer operator->() const
Definition: Interpreter.hpp:52
bool operator!=(the_iterator other)
Definition: Interpreter.hpp:44
std::conditional_t< IsConst, const Tuple &, Tuple & > reference
Definition: Interpreter.hpp:30
bool operator==(the_iterator other)
Definition: Interpreter.hpp:40
reference operator*() const
Definition: Interpreter.hpp:51
the_iterator & operator++()
Definition: Interpreter.hpp:46
the_iterator operator++(int)
Definition: Interpreter.hpp:47
std::conditional_t< IsConst, const Block, Block > block_t
Definition: Interpreter.hpp:29
the_iterator(block_t &vec, uint64_t mask)
Definition: Interpreter.hpp:38
A block of size N contains N tuples.
Definition: Interpreter.hpp:20
Block(Schema schema)
Create a new Block with tuples of Schema schema.
Definition: Interpreter.hpp:71
const_iterator end() const
Definition: Interpreter.hpp:93
bool empty() const
Returns true iff the block has no alive tuples, i.e. size() == 0.
const Tuple & operator[](std::size_t index) const
Returns the tuple at index index.
void erase(std::size_t index)
Erase the tuple at the given index from this Block.
Schema schema_
Definition: Interpreter.hpp:63
void clear()
Renders all tuples dead and removes their attributes.
const_iterator at(std::size_t index) const
Returns an iterator to the tuple at index index.
uint64_t mask() const
Returns the bit mask that identifies which tuples of this Block are alive.
Tuple & operator[](std::size_t index)
Returns the tuple at index index.
std::array< Tuple, N > data_
an array of the tuples of this Block; some slots may be unused
Definition: Interpreter.hpp:60
the_iterator< false > iterator
Definition: Interpreter.hpp:56
void erase(const_iterator it)
Erase the tuple identified by it from this Block.
Block(const Block &)=delete
void erase(iterator it)
Erase the tuple identified by it from this Block.
const_iterator cbegin() const
Definition: Interpreter.hpp:94
iterator begin()
Definition: Interpreter.hpp:90
bool alive(std::size_t index) const
Check whether the tuple at the given index is alive.
void dump(std::ostream &out) const
static constexpr std::size_t capacity()
Return the capacity of this Block.
Definition: Interpreter.hpp:86
the_iterator< true > const_iterator
Definition: Interpreter.hpp:57
const_iterator begin() const
Definition: Interpreter.hpp:92
const_iterator cend() const
Definition: Interpreter.hpp:95
iterator end()
Definition: Interpreter.hpp:91
const Tuple * data() const
Return a pointer to the underlying array of tuples.
Definition: Interpreter.hpp:81
Tuple * data()
Return a pointer to the underlying array of tuples.
Definition: Interpreter.hpp:79
std::size_t size() const
Return the number of alive tuples in this Block.
Definition: Interpreter.hpp:88
void fill()
Make all tuples in this Block alive.
static constexpr uint64_t AllOnes()
Returns a bit vector with left-most capacity() many bits set to 1 and the others set to 0.
uint64_t mask_
a mast identifying which slots of data_ are in use
Definition: Interpreter.hpp:61
Block(Block &&)=delete
static constexpr std::size_t CAPACITY
the capacity of a block
Definition: Interpreter.hpp:21
Block()=default
void mask(uint64_t new_mask)
Returns the bit mask that identifies which tuples of this Block are alive.
const Schema & schema() const
Definition: Interpreter.hpp:83
iterator at(std::size_t index)
Returns an iterator to the tuple at index index.
Definition: Interpreter.hpp:98
M_LCOV_EXCL_START friend std::ostream & operator<<(std::ostream &out, const Block< N > &block)
Print a textual representation of this Block to out.
void dump() const
ThreadSafePooledString pool(const char *str) const
Creates an internalized copy of the string str by adding it to the internal StringPool.
Definition: Catalog.hpp:274
static Catalog & Get()
Return a reference to the single Catalog instance.
Evaluates SQL operator trees on the database.
M_OPERATOR_LIST(DECLARE) static Value eval(const ast
static StackMachine compile_store(const Schema &tuple_schema, void *address, const storage::DataLayout &layout, const Schema &layout_schema, std::size_t row_id=0, std::size_t tuple_id=0)
Compile a StackMachine to store a tuple of Schema tuple_schema using a given memory address and a giv...
void register_operators(PhysicalOptimizer &phys_opt) const override
Registers all physical operators of this Backend in phys_opt.
Interpreter()=default
static StackMachine compile_load(const Schema &tuple_schema, void *address, const storage::DataLayout &layout, const Schema &layout_schema, std::size_t row_id=0, std::size_t tuple_id=0)
Compile a StackMachine to load a tuple of Schema tuple_schema using a given memory address and a give...
void execute(const MatchBase &plan) const override
Executes the already computed physical covering represented by plan using this Backend.
virtual const Operator & get_matched_root() const =0
Returns the matched logical root operator for physical operators.
An Operator represents an operation in a query plan.
Definition: Operator.hpp:45
The physical optimizer interface.
Implements push-based evaluation of a pipeline in the plan.
Block< 64 > block_
Pipeline(const Schema &schema)
const Schema & schema() const
Pipeline(Tuple &&t)
void push(const Operator &pipeline_start)
A Schema represents a sequence of identifiers, optionally with a prefix, and their associated types.
Definition: Schema.hpp:39
A stack machine that evaluates an expression.
This class holds a SQL attribute value.
Definition: Tuple.hpp:19
A constant: a string literal or a numeric constant.
Definition: AST.hpp:213
Token tok
the token of the expression; serves as an anchor to locate the expression in the source
Definition: AST.hpp:43
TokenType type
Definition: Token.hpp:17
ThreadSafePooledOptionalString text
declared as optional for dummy tokens
Definition: Token.hpp:16
Models how data is laid out in a linear address space.
Definition: DataLayout.hpp:29