include/simdb/
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
245 / 262
93.5%
Branches:
279 / 663
42.1%
Functions:
54 / 55
98.2%

schema/SchemaDef.hpp
Line Branch Exec Source
1 // <SchemaDef.hpp> -*- C++ -*-
2
3 #pragma once
4
5 #include "simdb/Assert.hpp"
6 #include "simdb/Exceptions.hpp"
7
8 #include <algorithm>
9 #include <deque>
10 #include <iostream>
11 #include <limits>
12 #include <memory>
13 #include <unordered_map>
14 #include <unordered_set>
15 #include <vector>
16
17 #include <boost/algorithm/string.hpp>
18
19 namespace simdb {
20
21 class DatabaseManager;
22
23 /// Data types supported by SimDB schemas
24 enum class SqlDataType { int32_t, uint32_t, int64_t, uint64_t, double_t, string_t, blob_t };
25
26 /// Stream operator used when creating various SQL commands.
27 470 inline std::ostream& operator<<(std::ostream& os, const SqlDataType dtype)
28 {
29 using dt = SqlDataType;
30
31
4/5
✓ Branch 2 → 3 taken 127 times.
✓ Branch 2 → 5 taken 297 times.
✓ Branch 2 → 7 taken 22 times.
✓ Branch 2 → 9 taken 24 times.
✗ Branch 2 → 11 not taken.
470 switch (dtype)
32 {
33 127 case dt::int32_t:
34 case dt::uint32_t:
35 case dt::int64_t: {
36 127 os << "INT";
37 127 break;
38 }
39
40 297 case dt::string_t:
41 case dt::uint64_t: {
42 297 os << "TEXT";
43 297 break;
44 }
45
46 22 case dt::double_t: {
47 22 os << "REAL";
48 22 break;
49 }
50
51 24 case dt::blob_t: {
52 24 os << "BLOB";
53 24 break;
54 }
55 }
56
57 470 return os;
58 }
59
60 /*!
61 * \class Column
62 *
63 * \brief This class is used for creating SimDB tables.
64 */
65 class Column
66 {
67 public:
68 /// Construct with the column name and data type.
69 649 Column(const std::string& column_name, const SqlDataType dt) :
70 649 name_(column_name),
71 649 dt_(dt)
72 {
73 649 }
74
75 /// Equivalence is defined as having the same name and data type.
76 20 bool operator==(const Column& rhs) const
77 {
78
3/6
✓ Branch 3 → 4 taken 20 times.
✗ Branch 3 → 8 not taken.
✓ Branch 4 → 5 taken 20 times.
✗ Branch 4 → 8 not taken.
✓ Branch 6 → 7 taken 20 times.
✗ Branch 6 → 8 not taken.
20 return name_ == rhs.name_ && dt_ == rhs.dt_ && default_val_string_ == rhs.default_val_string_;
79 }
80
81 /// Equivalence is defined as having the same name and data type.
82 20 bool operator!=(const Column& rhs) const { return !(*this == rhs); }
83
84 /// Get the name of this column.
85 20590 const std::string& getName() const { return name_; }
86
87 /// Get the data type of this column.
88 2280 SqlDataType getDataType() const { return dt_; }
89
90 /// Optionally specify a default value for this Column.
91 /// Defaults for SqlBlob data types are not allowed and will
92 /// throw if you attempt to set a SqlBlob default value.
93 75 template <typename T> void setDefaultValue(const T val)
94 {
95
16/72
void simdb::Column::setDefaultValue<simdb::SqlBlob>(simdb::SqlBlob):
✓ Branch 2 → 3 taken 1 time.
✗ Branch 2 → 21 not taken.
✓ Branch 5 → 6 taken 1 time.
✓ Branch 6 → 7 taken 1 time.
✓ Branch 8 → 9 taken 1 time.
✓ Branch 12 → 13 taken 1 time.
✓ Branch 13 → 14 taken 1 time.
✓ Branch 14 → 15 taken 1 time.
✓ Branch 15 → 16 taken 1 time.
✓ Branch 16 → 17 taken 1 time.
✓ Branch 17 → 18 taken 1 time.
✓ Branch 19 → 20 taken 1 time.
void simdb::Column::setDefaultValue<char const*>(char const*):
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 21 taken 25 times.
✗ Branch 5 → 6 not taken.
✗ Branch 6 → 7 not taken.
✗ Branch 8 → 9 not taken.
✗ Branch 12 → 13 not taken.
✗ Branch 13 → 14 not taken.
✗ Branch 14 → 15 not taken.
✗ Branch 15 → 16 not taken.
✗ Branch 16 → 17 not taken.
✗ Branch 17 → 18 not taken.
✗ Branch 19 → 20 not taken.
void simdb::Column::setDefaultValue<double>(double):
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 21 taken 14 times.
✗ Branch 5 → 6 not taken.
✗ Branch 6 → 7 not taken.
✗ Branch 8 → 9 not taken.
✗ Branch 12 → 13 not taken.
✗ Branch 13 → 14 not taken.
✗ Branch 14 → 15 not taken.
✗ Branch 15 → 16 not taken.
✗ Branch 16 → 17 not taken.
✗ Branch 17 → 18 not taken.
✗ Branch 19 → 20 not taken.
void simdb::Column::setDefaultValue<int>(int):
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 21 taken 31 times.
✗ Branch 5 → 6 not taken.
✗ Branch 6 → 7 not taken.
✗ Branch 8 → 9 not taken.
✗ Branch 12 → 13 not taken.
✗ Branch 13 → 14 not taken.
✗ Branch 14 → 15 not taken.
✗ Branch 15 → 16 not taken.
✗ Branch 16 → 17 not taken.
✗ Branch 17 → 18 not taken.
✗ Branch 19 → 20 not taken.
void simdb::Column::setDefaultValue<unsigned int>(unsigned int):
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 21 taken 2 times.
✗ Branch 5 → 6 not taken.
✗ Branch 6 → 7 not taken.
✗ Branch 8 → 9 not taken.
✗ Branch 12 → 13 not taken.
✗ Branch 13 → 14 not taken.
✗ Branch 14 → 15 not taken.
✗ Branch 15 → 16 not taken.
✗ Branch 16 → 17 not taken.
✗ Branch 17 → 18 not taken.
✗ Branch 19 → 20 not taken.
void simdb::Column::setDefaultValue<long>(long):
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 21 taken 2 times.
✗ Branch 5 → 6 not taken.
✗ Branch 6 → 7 not taken.
✗ Branch 8 → 9 not taken.
✗ Branch 12 → 13 not taken.
✗ Branch 13 → 14 not taken.
✗ Branch 14 → 15 not taken.
✗ Branch 15 → 16 not taken.
✗ Branch 16 → 17 not taken.
✗ Branch 17 → 18 not taken.
✗ Branch 19 → 20 not taken.
77 simdb_assert(dt_ != SqlDataType::blob_t, "Cannot set default value for a database "
96 "column with blob data type");
97
98 if constexpr (std::is_integral_v<T> && sizeof(T) == 64)
99 {
100 simdb_assert(dt_ != SqlDataType::int32_t, "Cannot assign 64-bit default value to 32-bit column");
101 }
102
103 if constexpr (std::is_integral_v<T>)
104 {
105
14/36
void simdb::Column::setDefaultValue<int>(int):
✗ Branch 21 → 22 not taken.
✓ Branch 21 → 40 taken 31 times.
✗ Branch 24 → 25 not taken.
✗ Branch 25 → 26 not taken.
✗ Branch 27 → 28 not taken.
✗ Branch 31 → 32 not taken.
✗ Branch 32 → 33 not taken.
✗ Branch 33 → 34 not taken.
✗ Branch 34 → 35 not taken.
✗ Branch 35 → 36 not taken.
✗ Branch 36 → 37 not taken.
✗ Branch 38 → 39 not taken.
void simdb::Column::setDefaultValue<unsigned int>(unsigned int):
✓ Branch 21 → 22 taken 1 time.
✓ Branch 21 → 40 taken 1 time.
✓ Branch 24 → 25 taken 1 time.
✓ Branch 25 → 26 taken 1 time.
✓ Branch 27 → 28 taken 1 time.
✓ Branch 31 → 32 taken 1 time.
✓ Branch 32 → 33 taken 1 time.
✓ Branch 33 → 34 taken 1 time.
✓ Branch 34 → 35 taken 1 time.
✓ Branch 35 → 36 taken 1 time.
✓ Branch 36 → 37 taken 1 time.
✓ Branch 38 → 39 taken 1 time.
void simdb::Column::setDefaultValue<long>(long):
✗ Branch 21 → 22 not taken.
✓ Branch 21 → 40 taken 2 times.
✗ Branch 24 → 25 not taken.
✗ Branch 25 → 26 not taken.
✗ Branch 27 → 28 not taken.
✗ Branch 31 → 32 not taken.
✗ Branch 32 → 33 not taken.
✗ Branch 33 → 34 not taken.
✗ Branch 34 → 35 not taken.
✗ Branch 35 → 36 not taken.
✗ Branch 36 → 37 not taken.
✗ Branch 38 → 39 not taken.
37 simdb_assert(dt_ != SqlDataType::string_t, "Cannot assign integral default value to string column");
106 }
107
108 if constexpr (std::is_same_v<T, const char*>)
109 {
110
3/16
✓ Branch 21 → 22 taken 25 times.
✗ Branch 21 → 23 not taken.
✗ Branch 22 → 23 not taken.
✓ Branch 22 → 24 taken 25 times.
✗ Branch 25 → 26 not taken.
✓ Branch 25 → 44 taken 25 times.
✗ Branch 28 → 29 not taken.
✗ Branch 29 → 30 not taken.
✗ Branch 31 → 32 not taken.
✗ Branch 35 → 36 not taken.
✗ Branch 36 → 37 not taken.
✗ Branch 37 → 38 not taken.
✗ Branch 38 → 39 not taken.
✗ Branch 39 → 40 not taken.
✗ Branch 40 → 41 not taken.
✗ Branch 42 → 43 not taken.
25 simdb_assert(dt_ != SqlDataType::int32_t&& dt_ != SqlDataType::int64_t,
111 "Cannot assign string default value to an integer column");
112 }
113
114
5/6
void simdb::Column::setDefaultValue<simdb::SqlBlob>(simdb::SqlBlob):
✗ Branch 21 → 22 not taken.
void simdb::Column::setDefaultValue<char const*>(char const*):
✓ Branch 44 → 45 taken 25 times.
void simdb::Column::setDefaultValue<double>(double):
✓ Branch 21 → 22 taken 14 times.
void simdb::Column::setDefaultValue<int>(int):
✓ Branch 40 → 41 taken 31 times.
void simdb::Column::setDefaultValue<unsigned int>(unsigned int):
✓ Branch 40 → 41 taken 1 time.
void simdb::Column::setDefaultValue<long>(long):
✓ Branch 40 → 41 taken 2 times.
73 std::ostringstream ss;
115
5/6
void simdb::Column::setDefaultValue<simdb::SqlBlob>(simdb::SqlBlob):
✗ Branch 22 → 23 not taken.
void simdb::Column::setDefaultValue<char const*>(char const*):
✓ Branch 45 → 46 taken 25 times.
void simdb::Column::setDefaultValue<double>(double):
✓ Branch 22 → 23 taken 14 times.
void simdb::Column::setDefaultValue<int>(int):
✓ Branch 41 → 42 taken 31 times.
void simdb::Column::setDefaultValue<unsigned int>(unsigned int):
✓ Branch 41 → 42 taken 1 time.
void simdb::Column::setDefaultValue<long>(long):
✓ Branch 41 → 42 taken 2 times.
73 writeDefaultValue_(ss, val);
116
10/12
void simdb::Column::setDefaultValue<simdb::SqlBlob>(simdb::SqlBlob):
✗ Branch 23 → 24 not taken.
✗ Branch 24 → 25 not taken.
void simdb::Column::setDefaultValue<char const*>(char const*):
✓ Branch 46 → 47 taken 25 times.
✓ Branch 47 → 48 taken 25 times.
void simdb::Column::setDefaultValue<double>(double):
✓ Branch 23 → 24 taken 14 times.
✓ Branch 24 → 25 taken 14 times.
void simdb::Column::setDefaultValue<int>(int):
✓ Branch 42 → 43 taken 31 times.
✓ Branch 43 → 44 taken 31 times.
void simdb::Column::setDefaultValue<unsigned int>(unsigned int):
✓ Branch 42 → 43 taken 1 time.
✓ Branch 43 → 44 taken 1 time.
void simdb::Column::setDefaultValue<long>(long):
✓ Branch 42 → 43 taken 2 times.
✓ Branch 43 → 44 taken 2 times.
73 setDefaultValueStr_(ss.str());
117
118
5/84
void simdb::Column::setDefaultValue<simdb::SqlBlob>(simdb::SqlBlob):
✗ Branch 27 → 28 not taken.
✗ Branch 27 → 48 not taken.
✗ Branch 30 → 31 not taken.
✗ Branch 31 → 32 not taken.
✗ Branch 33 → 34 not taken.
✗ Branch 37 → 38 not taken.
✗ Branch 38 → 39 not taken.
✗ Branch 39 → 40 not taken.
✗ Branch 40 → 41 not taken.
✗ Branch 41 → 42 not taken.
✗ Branch 42 → 43 not taken.
✗ Branch 43 → 44 not taken.
✗ Branch 44 → 45 not taken.
✗ Branch 46 → 47 not taken.
void simdb::Column::setDefaultValue<char const*>(char const*):
✗ Branch 50 → 51 not taken.
✓ Branch 50 → 71 taken 25 times.
✗ Branch 53 → 54 not taken.
✗ Branch 54 → 55 not taken.
✗ Branch 56 → 57 not taken.
✗ Branch 60 → 61 not taken.
✗ Branch 61 → 62 not taken.
✗ Branch 62 → 63 not taken.
✗ Branch 63 → 64 not taken.
✗ Branch 64 → 65 not taken.
✗ Branch 65 → 66 not taken.
✗ Branch 66 → 67 not taken.
✗ Branch 67 → 68 not taken.
✗ Branch 69 → 70 not taken.
void simdb::Column::setDefaultValue<double>(double):
✗ Branch 27 → 28 not taken.
✓ Branch 27 → 48 taken 14 times.
✗ Branch 30 → 31 not taken.
✗ Branch 31 → 32 not taken.
✗ Branch 33 → 34 not taken.
✗ Branch 37 → 38 not taken.
✗ Branch 38 → 39 not taken.
✗ Branch 39 → 40 not taken.
✗ Branch 40 → 41 not taken.
✗ Branch 41 → 42 not taken.
✗ Branch 42 → 43 not taken.
✗ Branch 43 → 44 not taken.
✗ Branch 44 → 45 not taken.
✗ Branch 46 → 47 not taken.
void simdb::Column::setDefaultValue<int>(int):
✗ Branch 46 → 47 not taken.
✓ Branch 46 → 67 taken 31 times.
✗ Branch 49 → 50 not taken.
✗ Branch 50 → 51 not taken.
✗ Branch 52 → 53 not taken.
✗ Branch 56 → 57 not taken.
✗ Branch 57 → 58 not taken.
✗ Branch 58 → 59 not taken.
✗ Branch 59 → 60 not taken.
✗ Branch 60 → 61 not taken.
✗ Branch 61 → 62 not taken.
✗ Branch 62 → 63 not taken.
✗ Branch 63 → 64 not taken.
✗ Branch 65 → 66 not taken.
void simdb::Column::setDefaultValue<unsigned int>(unsigned int):
✗ Branch 46 → 47 not taken.
✓ Branch 46 → 67 taken 1 time.
✗ Branch 49 → 50 not taken.
✗ Branch 50 → 51 not taken.
✗ Branch 52 → 53 not taken.
✗ Branch 56 → 57 not taken.
✗ Branch 57 → 58 not taken.
✗ Branch 58 → 59 not taken.
✗ Branch 59 → 60 not taken.
✗ Branch 60 → 61 not taken.
✗ Branch 61 → 62 not taken.
✗ Branch 62 → 63 not taken.
✗ Branch 63 → 64 not taken.
✗ Branch 65 → 66 not taken.
void simdb::Column::setDefaultValue<long>(long):
✗ Branch 46 → 47 not taken.
✓ Branch 46 → 67 taken 2 times.
✗ Branch 49 → 50 not taken.
✗ Branch 50 → 51 not taken.
✗ Branch 52 → 53 not taken.
✗ Branch 56 → 57 not taken.
✗ Branch 57 → 58 not taken.
✗ Branch 58 → 59 not taken.
✗ Branch 59 → 60 not taken.
✗ Branch 60 → 61 not taken.
✗ Branch 61 → 62 not taken.
✗ Branch 62 → 63 not taken.
✗ Branch 63 → 64 not taken.
✗ Branch 65 → 66 not taken.
73 simdb_assert(!default_val_string_.empty(), "Unable to convert default value " << val << " into a std::string");
119 73 }
120
121 /// Called in order to set default values for TEXT columns.
122 2 void setDefaultValue(const std::string& val)
123 {
124
1/12
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 21 taken 2 times.
✗ Branch 5 → 6 not taken.
✗ Branch 6 → 7 not taken.
✗ Branch 8 → 9 not taken.
✗ Branch 12 → 13 not taken.
✗ Branch 13 → 14 not taken.
✗ Branch 14 → 15 not taken.
✗ Branch 15 → 16 not taken.
✗ Branch 16 → 17 not taken.
✗ Branch 17 → 18 not taken.
✗ Branch 19 → 20 not taken.
2 simdb_assert(dt_ == SqlDataType::string_t, "Unable to set default value string (data type mismatch)");
125
1/12
✗ Branch 21 → 22 not taken.
✓ Branch 21 → 40 taken 2 times.
✗ Branch 24 → 25 not taken.
✗ Branch 25 → 26 not taken.
✗ Branch 27 → 28 not taken.
✗ Branch 31 → 32 not taken.
✗ Branch 32 → 33 not taken.
✗ Branch 33 → 34 not taken.
✗ Branch 34 → 35 not taken.
✗ Branch 35 → 36 not taken.
✗ Branch 36 → 37 not taken.
✗ Branch 38 → 39 not taken.
2 simdb_assert(!unique_col_, "Cannot set default column value on a unique column");
126
127 2 setDefaultValueStr_(val);
128 2 }
129
130 /// Check if this column has a default value set or not.
131 507 bool hasDefaultValue() const { return !default_val_string_.empty(); }
132
133 /// Get this Column's default value. These are returned as
134 /// strings since the schema creation command is one string,
135 /// e.g. "CREATE TABLE ..."
136 1169 const std::string& getDefaultValueAsString() const { return default_val_string_; }
137
138 /// Ensure the given column is unique:
139 /// CREATE TABLE my_table (
140 /// Id INTEGER PRIMARY KEY,
141 /// Timestamp INTEGER UNIQUE <---
142 /// );
143 37 void ensureUnique()
144 {
145
1/12
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 22 taken 37 times.
✗ Branch 6 → 7 not taken.
✗ Branch 7 → 8 not taken.
✗ Branch 9 → 10 not taken.
✗ Branch 13 → 14 not taken.
✗ Branch 14 → 15 not taken.
✗ Branch 15 → 16 not taken.
✗ Branch 16 → 17 not taken.
✗ Branch 17 → 18 not taken.
✗ Branch 18 → 19 not taken.
✗ Branch 20 → 21 not taken.
37 simdb_assert(!hasDefaultValue(), "Column has default value; cannot make unique");
146 37 unique_col_ = true;
147 37 }
148
149 /// Check if this column should be created with the UNIQUE tag.
150 470 bool isUnique() const { return unique_col_; }
151
152 private:
153 /// Default values are stringified. For doubles, we need maximum precision.
154 14 void writeDefaultValue_(std::ostringstream& oss, const double val) const
155 {
156 14 oss << std::numeric_limits<long double>::digits10 + 1 << val;
157 14 }
158
159 /// Default values are stringified. For non-doubles, e.g. INT and TEXT
160 /// types, we use default precision.
161 template <typename T>
162 typename std::enable_if<std::is_integral_v<T> || std::is_same_v<T, std::string> || std::is_same_v<T, const char*>,
163 void>::type
164 59 writeDefaultValue_(std::ostringstream& oss, const T& val) const
165 {
166 59 oss << val;
167 59 }
168
169 /// Throw for columns that do not support default values.
170 template <typename T>
171 typename std::enable_if<
172 !std::is_integral_v<T> && !std::is_same_v<T, std::string> && !std::is_same_v<T, const char*>, void>::type
173 ✗ writeDefaultValue_(std::ostringstream&, const T&) const
174 {
175
0/1
✗ Branch 4 → 5 not taken.
✗ throw DBException("Only INT/REAL/TEXT columns support default values");
176 }
177
178 /// Set the default-value-as-string.
179 90 void setDefaultValueStr_(const std::string& val) { default_val_string_ = val; }
180
181 /// DatabaseManager needs setDefaultValueStr_
182 friend class DatabaseManager;
183
184 /// Column name
185 std::string name_;
186
187 /// Column data type
188 SqlDataType dt_;
189
190 /// Optional default value (stringified)
191 std::string default_val_string_;
192
193 /// Should this column be defined as e.g. "Timestamp INTEGER UNIQUE"?
194 bool unique_col_ = false;
195 };
196
197 /*!
198 * \class Table
199 *
200 * \brief Table class used for creating SimDB schemas
201 */
202 class Table
203 {
204 public:
205 /// Construct with a name.
206 236 Table(const std::string& table_name) :
207
1/1
✓ Branch 8 → 9 taken 236 times.
472 name_(table_name)
208 {
209 236 }
210
211 /// Get the name of this table.
212 49907 const std::string& getName() const { return name_; }
213
214 /// Add a column to this table's schema with a name and data type.
215 650 Table& addColumn(const std::string& name, const SqlDataType dt)
216 {
217
13/13
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 23 taken 649 times.
✓ Branch 6 → 7 taken 1 time.
✓ Branch 7 → 8 taken 1 time.
✓ Branch 9 → 10 taken 1 time.
✓ Branch 13 → 14 taken 1 time.
✓ Branch 14 → 15 taken 1 time.
✓ Branch 15 → 16 taken 1 time.
✓ Branch 16 → 17 taken 1 time.
✓ Branch 17 → 18 taken 1 time.
✓ Branch 18 → 19 taken 1 time.
✓ Branch 19 → 20 taken 1 time.
✓ Branch 21 → 22 taken 1 time.
652 simdb_assert(!hasColumn(name), "Table already has a column named " << name);
218
1/12
✗ Branch 24 → 25 not taken.
✓ Branch 24 → 43 taken 649 times.
✗ Branch 27 → 28 not taken.
✗ Branch 28 → 29 not taken.
✗ Branch 30 → 31 not taken.
✗ Branch 34 → 35 not taken.
✗ Branch 35 → 36 not taken.
✗ Branch 36 → 37 not taken.
✗ Branch 37 → 38 not taken.
✗ Branch 38 → 39 not taken.
✗ Branch 39 → 40 not taken.
✗ Branch 41 → 42 not taken.
649 simdb_assert(name != "Id", "Cannot explicitly create the Id column; call Table::setPrimaryKey(\"Id\")");
219
220
3/5
✓ Branch 43 → 44 taken 649 times.
✓ Branch 44 → 45 taken 649 times.
✓ Branch 45 → 46 taken 649 times.
✗ Branch 81 → 82 not taken.
✗ Branch 81 → 83 not taken.
649 columns_.emplace_back(new Column(name, dt));
221 649 columns_by_name_[name] = columns_.back();
222 649 return *this;
223 }
224
225 /// Get a column by its name. Throws if not found.
226 3 const Column& getColumn(const std::string& col_name) const
227 {
228
1/1
✓ Branch 2 → 3 taken 3 times.
3 auto iter = columns_by_name_.find(col_name);
229
15/15
✓ Branch 5 → 6 taken 1 time.
✓ Branch 5 → 27 taken 2 times.
✓ Branch 8 → 9 taken 1 time.
✓ Branch 9 → 10 taken 1 time.
✓ Branch 11 → 12 taken 1 time.
✓ Branch 15 → 16 taken 1 time.
✓ Branch 16 → 17 taken 1 time.
✓ Branch 17 → 18 taken 1 time.
✓ Branch 18 → 19 taken 1 time.
✓ Branch 19 → 20 taken 1 time.
✓ Branch 20 → 21 taken 1 time.
✓ Branch 21 → 22 taken 1 time.
✓ Branch 22 → 23 taken 1 time.
✓ Branch 23 → 24 taken 1 time.
✓ Branch 25 → 26 taken 1 time.
5 simdb_assert(iter != columns_by_name_.end(), "No column named " << col_name << " in table " << name_);
230
231 4 return *(iter->second);
232 }
233
234 /// Check if this table has a column with the given name.
235 671 bool hasColumn(const std::string& col_name) const
236 {
237
1/1
✓ Branch 3 → 4 taken 671 times.
671 return columns_by_name_.find(col_name) != columns_by_name_.end();
238 }
239
240 /// Assign a default value for the given column.
241 76 template <typename T> Table& setColumnDefaultValue(const std::string& col_name, const T default_val)
242 {
243
6/6
simdb::Table& simdb::Table::setColumnDefaultValue<simdb::SqlBlob>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, simdb::SqlBlob):
✓ Branch 2 → 3 taken 1 time.
simdb::Table& simdb::Table::setColumnDefaultValue<char const*>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*):
✓ Branch 2 → 3 taken 25 times.
simdb::Table& simdb::Table::setColumnDefaultValue<double>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, double):
✓ Branch 2 → 3 taken 14 times.
simdb::Table& simdb::Table::setColumnDefaultValue<int>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int):
✓ Branch 2 → 3 taken 32 times.
simdb::Table& simdb::Table::setColumnDefaultValue<unsigned int>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned int):
✓ Branch 2 → 3 taken 2 times.
simdb::Table& simdb::Table::setColumnDefaultValue<long>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, long):
✓ Branch 2 → 3 taken 2 times.
76 auto iter = columns_by_name_.find(col_name);
244
20/90
simdb::Table& simdb::Table::setColumnDefaultValue<simdb::SqlBlob>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, simdb::SqlBlob):
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 27 taken 1 time.
✗ Branch 8 → 9 not taken.
✗ Branch 9 → 10 not taken.
✗ Branch 11 → 12 not taken.
✗ Branch 15 → 16 not taken.
✗ Branch 16 → 17 not taken.
✗ Branch 17 → 18 not taken.
✗ Branch 18 → 19 not taken.
✗ Branch 19 → 20 not taken.
✗ Branch 20 → 21 not taken.
✗ Branch 21 → 22 not taken.
✗ Branch 22 → 23 not taken.
✗ Branch 23 → 24 not taken.
✗ Branch 25 → 26 not taken.
simdb::Table& simdb::Table::setColumnDefaultValue<char const*>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*):
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 27 taken 25 times.
✗ Branch 8 → 9 not taken.
✗ Branch 9 → 10 not taken.
✗ Branch 11 → 12 not taken.
✗ Branch 15 → 16 not taken.
✗ Branch 16 → 17 not taken.
✗ Branch 17 → 18 not taken.
✗ Branch 18 → 19 not taken.
✗ Branch 19 → 20 not taken.
✗ Branch 20 → 21 not taken.
✗ Branch 21 → 22 not taken.
✗ Branch 22 → 23 not taken.
✗ Branch 23 → 24 not taken.
✗ Branch 25 → 26 not taken.
simdb::Table& simdb::Table::setColumnDefaultValue<double>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, double):
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 27 taken 14 times.
✗ Branch 8 → 9 not taken.
✗ Branch 9 → 10 not taken.
✗ Branch 11 → 12 not taken.
✗ Branch 15 → 16 not taken.
✗ Branch 16 → 17 not taken.
✗ Branch 17 → 18 not taken.
✗ Branch 18 → 19 not taken.
✗ Branch 19 → 20 not taken.
✗ Branch 20 → 21 not taken.
✗ Branch 21 → 22 not taken.
✗ Branch 22 → 23 not taken.
✗ Branch 23 → 24 not taken.
✗ Branch 25 → 26 not taken.
simdb::Table& simdb::Table::setColumnDefaultValue<int>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int):
✓ Branch 5 → 6 taken 1 time.
✓ Branch 5 → 27 taken 31 times.
✓ Branch 8 → 9 taken 1 time.
✓ Branch 9 → 10 taken 1 time.
✓ Branch 11 → 12 taken 1 time.
✓ Branch 15 → 16 taken 1 time.
✓ Branch 16 → 17 taken 1 time.
✓ Branch 17 → 18 taken 1 time.
✓ Branch 18 → 19 taken 1 time.
✓ Branch 19 → 20 taken 1 time.
✓ Branch 20 → 21 taken 1 time.
✓ Branch 21 → 22 taken 1 time.
✓ Branch 22 → 23 taken 1 time.
✓ Branch 23 → 24 taken 1 time.
✓ Branch 25 → 26 taken 1 time.
simdb::Table& simdb::Table::setColumnDefaultValue<unsigned int>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned int):
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 27 taken 2 times.
✗ Branch 8 → 9 not taken.
✗ Branch 9 → 10 not taken.
✗ Branch 11 → 12 not taken.
✗ Branch 15 → 16 not taken.
✗ Branch 16 → 17 not taken.
✗ Branch 17 → 18 not taken.
✗ Branch 18 → 19 not taken.
✗ Branch 19 → 20 not taken.
✗ Branch 20 → 21 not taken.
✗ Branch 21 → 22 not taken.
✗ Branch 22 → 23 not taken.
✗ Branch 23 → 24 not taken.
✗ Branch 25 → 26 not taken.
simdb::Table& simdb::Table::setColumnDefaultValue<long>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, long):
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 27 taken 2 times.
✗ Branch 8 → 9 not taken.
✗ Branch 9 → 10 not taken.
✗ Branch 11 → 12 not taken.
✗ Branch 15 → 16 not taken.
✗ Branch 16 → 17 not taken.
✗ Branch 17 → 18 not taken.
✗ Branch 18 → 19 not taken.
✗ Branch 19 → 20 not taken.
✗ Branch 20 → 21 not taken.
✗ Branch 21 → 22 not taken.
✗ Branch 22 → 23 not taken.
✗ Branch 23 → 24 not taken.
✗ Branch 25 → 26 not taken.
78 simdb_assert(iter != columns_by_name_.end(), "No column named " << col_name << " in table " << name_);
245
246
5/6
simdb::Table& simdb::Table::setColumnDefaultValue<simdb::SqlBlob>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, simdb::SqlBlob):
✗ Branch 29 → 30 not taken.
simdb::Table& simdb::Table::setColumnDefaultValue<char const*>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*):
✓ Branch 29 → 30 taken 25 times.
simdb::Table& simdb::Table::setColumnDefaultValue<double>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, double):
✓ Branch 29 → 30 taken 14 times.
simdb::Table& simdb::Table::setColumnDefaultValue<int>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int):
✓ Branch 29 → 30 taken 31 times.
simdb::Table& simdb::Table::setColumnDefaultValue<unsigned int>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned int):
✓ Branch 29 → 30 taken 1 time.
simdb::Table& simdb::Table::setColumnDefaultValue<long>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, long):
✓ Branch 29 → 30 taken 2 times.
75 iter->second->setDefaultValue(default_val);
247 73 return *this;
248 }
249
250 /// Assign a default value for the given column.
251 2 Table& setColumnDefaultValue(const std::string& col_name, const std::string& default_val)
252 {
253
1/1
✓ Branch 2 → 3 taken 2 times.
2 auto iter = columns_by_name_.find(col_name);
254
1/15
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 27 taken 2 times.
✗ Branch 8 → 9 not taken.
✗ Branch 9 → 10 not taken.
✗ Branch 11 → 12 not taken.
✗ Branch 15 → 16 not taken.
✗ Branch 16 → 17 not taken.
✗ Branch 17 → 18 not taken.
✗ Branch 18 → 19 not taken.
✗ Branch 19 → 20 not taken.
✗ Branch 20 → 21 not taken.
✗ Branch 21 → 22 not taken.
✗ Branch 22 → 23 not taken.
✗ Branch 23 → 24 not taken.
✗ Branch 25 → 26 not taken.
2 simdb_assert(iter != columns_by_name_.end(), "No column named " << col_name << " in table " << name_);
255
256
1/1
✓ Branch 29 → 30 taken 2 times.
2 iter->second->setDefaultValue(default_val);
257 2 return *this;
258 }
259
260 /// Ensure the given column is unique:
261 /// CREATE TABLE my_table (
262 /// Id INTEGER PRIMARY KEY,
263 /// Timestamp INTEGER UNIQUE <---
264 /// );
265 37 Table& ensureUnique(const std::string& col_name)
266 {
267
1/1
✓ Branch 2 → 3 taken 37 times.
37 auto iter = columns_by_name_.find(col_name);
268
1/15
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 27 taken 37 times.
✗ Branch 8 → 9 not taken.
✗ Branch 9 → 10 not taken.
✗ Branch 11 → 12 not taken.
✗ Branch 15 → 16 not taken.
✗ Branch 16 → 17 not taken.
✗ Branch 17 → 18 not taken.
✗ Branch 18 → 19 not taken.
✗ Branch 19 → 20 not taken.
✗ Branch 20 → 21 not taken.
✗ Branch 21 → 22 not taken.
✗ Branch 22 → 23 not taken.
✗ Branch 23 → 24 not taken.
✗ Branch 25 → 26 not taken.
37 simdb_assert(iter != columns_by_name_.end(), "No column named " << col_name << " in table " << name_);
269
270
1/1
✓ Branch 29 → 30 taken 37 times.
37 iter->second->ensureUnique();
271 37 return *this;
272 }
273
274 /// Index this table's records on the given column.
275 /// CREATE INDEX IndexName ON TableName(ColumnName)
276
8/10
✓ Branch 2 → 3 taken 42 times.
✓ Branch 3 → 4 taken 41 times.
✓ Branch 6 → 7 taken 41 times.
✓ Branch 6 → 8 taken 41 times.
✓ Branch 11 → 12 taken 1 time.
✓ Branch 11 → 13 taken 1 time.
✓ Branch 14 → 15 taken 1 time.
✗ Branch 14 → 18 not taken.
✗ Branch 16 → 17 not taken.
✓ Branch 16 → 18 taken 1 time.
86 Table& createIndexOn(const std::string& col_name) { return createCompoundIndexOn({col_name}); }
277
278 /// Index this table's records on the given columns.
279 /// CREATE INDEX IndexName ON TableName(ColA,ColB,ColC)
280 56 Table& createCompoundIndexOn(const std::initializer_list<std::string>& col_names)
281 {
282
2/2
✓ Branch 6 → 7 taken 56 times.
✓ Branch 7 → 8 taken 54 times.
112 return createCompoundIndexOn(std::vector<std::string>(col_names.begin(), col_names.end()));
283 }
284
285 /// See std::initializer_list overload
286 58 Table& createCompoundIndexOn(const std::vector<std::string>& col_names)
287 {
288
2/2
✓ Branch 32 → 4 taken 77 times.
✓ Branch 32 → 33 taken 56 times.
133 for (const auto& col_name : col_names)
289 {
290
16/16
✓ Branch 6 → 7 taken 77 times.
✓ Branch 8 → 9 taken 2 times.
✓ Branch 8 → 30 taken 75 times.
✓ Branch 11 → 12 taken 2 times.
✓ Branch 12 → 13 taken 2 times.
✓ Branch 14 → 15 taken 2 times.
✓ Branch 18 → 19 taken 2 times.
✓ Branch 19 → 20 taken 2 times.
✓ Branch 20 → 21 taken 2 times.
✓ Branch 21 → 22 taken 2 times.
✓ Branch 22 → 23 taken 2 times.
✓ Branch 23 → 24 taken 2 times.
✓ Branch 24 → 25 taken 2 times.
✓ Branch 25 → 26 taken 2 times.
✓ Branch 26 → 27 taken 2 times.
✓ Branch 28 → 29 taken 2 times.
81 simdb_assert(columns_by_name_.find(col_name) != columns_by_name_.end(),
291 "Column " << col_name << " does not exist in table " << name_);
292 }
293
294
1/1
✓ Branch 33 → 34 taken 56 times.
56 std::ostringstream oss;
295
7/7
✓ Branch 34 → 35 taken 56 times.
✓ Branch 35 → 36 taken 56 times.
✓ Branch 36 → 37 taken 56 times.
✓ Branch 38 → 39 taken 56 times.
✓ Branch 39 → 40 taken 56 times.
✓ Branch 40 → 41 taken 56 times.
✓ Branch 41 → 42 taken 56 times.
56 oss << "CREATE INDEX " << name_ << "_Index" << index_creation_strs_.size() + 1 << " ON " << name_ << "(";
296
297 56 size_t idx = 0;
298 56 auto iter = col_names.begin();
299
2/2
✓ Branch 53 → 44 taken 74 times.
✓ Branch 53 → 54 taken 56 times.
130 while (iter != col_names.end())
300 {
301
1/1
✓ Branch 45 → 46 taken 74 times.
74 oss << *iter;
302
2/2
✓ Branch 47 → 48 taken 18 times.
✓ Branch 47 → 49 taken 56 times.
74 if (idx != col_names.size() - 1)
303 {
304
1/1
✓ Branch 48 → 49 taken 18 times.
18 oss << ",";
305 }
306 74 ++iter;
307 74 ++idx;
308 }
309
1/1
✓ Branch 54 → 55 taken 56 times.
56 oss << ")";
310
311
2/2
✓ Branch 55 → 56 taken 56 times.
✓ Branch 56 → 57 taken 56 times.
56 index_creation_strs_.push_back(oss.str());
312 56 return *this;
313 56 }
314
315 /// Get a list of table indexes. Say we created the table like this:
316 ///
317 /// using dt = SqlDataType;
318 /// Schema schema;
319 /// auto& tbl = schema.addTable("MyTable");
320 /// tbl.addColumn("Foo", dt::int32_t);
321 /// tbl.addColumn("Bar", dt::int32_t);
322 /// tbl.addColumn("Fiz", dt::int32_t);
323 /// tbl.addColumn("Buz", dt::int32_t);
324 ///
325 /// Then added these indexes:
326 ///
327 /// tbl.createIndexOn("Foo");
328 /// tbl.createIndexOn("Bar");
329 /// tbl.createCompoundIndexOn({"Fiz", "Buz"});
330 ///
331 /// Calling getTableIndexes() will return:
332 ///
333 /// [
334 /// ["Foo"],
335 /// ["Bar"],
336 /// ["Fiz", "Buz"]
337 /// ]
338 397 std::vector<std::vector<std::string>> getTableIndexes() const
339 {
340 397 std::vector<std::vector<std::string>> indexes;
341
2/2
✓ Branch 60 → 5 taken 102 times.
✓ Branch 60 → 61 taken 397 times.
499 for (const auto& cmd : index_creation_strs_)
342 {
343 // Command is something like:
344 // CREATE INDEX <index_name> ON <table_name> (Foo,Bar)
345
1/1
✓ Branch 6 → 7 taken 102 times.
102 auto lparen = cmd.rfind("(");
346
1/9
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 18 taken 102 times.
✗ Branch 9 → 10 not taken.
✗ Branch 10 → 11 not taken.
✗ Branch 11 → 12 not taken.
✗ Branch 12 → 13 not taken.
✗ Branch 13 → 14 not taken.
✗ Branch 14 → 15 not taken.
✗ Branch 16 → 17 not taken.
102 simdb_assert(lparen != std::string::npos);
347
348
1/1
✓ Branch 18 → 19 taken 102 times.
102 auto rparen = cmd.rfind(")");
349
1/9
✗ Branch 19 → 20 not taken.
✓ Branch 19 → 30 taken 102 times.
✗ Branch 21 → 22 not taken.
✗ Branch 22 → 23 not taken.
✗ Branch 23 → 24 not taken.
✗ Branch 24 → 25 not taken.
✗ Branch 25 → 26 not taken.
✗ Branch 26 → 27 not taken.
✗ Branch 28 → 29 not taken.
102 simdb_assert(rparen != std::string::npos);
350
1/9
✗ Branch 30 → 31 not taken.
✓ Branch 30 → 41 taken 102 times.
✗ Branch 32 → 33 not taken.
✗ Branch 33 → 34 not taken.
✗ Branch 34 → 35 not taken.
✗ Branch 35 → 36 not taken.
✗ Branch 36 → 37 not taken.
✗ Branch 37 → 38 not taken.
✗ Branch 39 → 40 not taken.
102 simdb_assert(rparen > lparen);
351
352
1/1
✓ Branch 41 → 42 taken 102 times.
102 auto idx_cols = cmd.substr(lparen + 1, rparen - lparen - 1);
353
1/1
✓ Branch 42 → 43 taken 102 times.
102 indexes.emplace_back();
354
2/2
✓ Branch 43 → 44 taken 102 times.
✓ Branch 45 → 46 taken 102 times.
102 boost::split(indexes.back(), idx_cols, boost::is_any_of(","));
355
356
2/2
✓ Branch 56 → 50 taken 135 times.
✓ Branch 56 → 57 taken 102 times.
237 for (auto& s : indexes.back())
357 {
358
1/1
✓ Branch 52 → 53 taken 135 times.
135 boost::trim(s);
359 }
360 102 }
361 397 return indexes;
362 ✗ }
363
364 /// Set this table's primary key. Defaults to "Id".
365 20 Table& setPrimaryKey(const std::string& pkey_column)
366 {
367
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 20 times.
20 if (pkey_column.empty())
368 {
369 ✗ return unsetPrimaryKey();
370 }
371
372
4/17
✓ Branch 6 → 7 taken 18 times.
✓ Branch 6 → 10 taken 2 times.
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 18 times.
✗ Branch 11 → 12 not taken.
✓ Branch 11 → 31 taken 20 times.
✗ Branch 14 → 15 not taken.
✗ Branch 15 → 16 not taken.
✗ Branch 17 → 18 not taken.
✗ Branch 21 → 22 not taken.
✗ Branch 22 → 23 not taken.
✗ Branch 23 → 24 not taken.
✗ Branch 24 → 25 not taken.
✗ Branch 25 → 26 not taken.
✗ Branch 26 → 27 not taken.
✗ Branch 27 → 28 not taken.
✗ Branch 29 → 30 not taken.
20 simdb_assert(hasColumn(pkey_column) || pkey_column == "Id",
373 "Primary key column does not exist: " << pkey_column);
374 20 primary_key_column_ = pkey_column;
375 20 return *this;
376 }
377
378 /// Do not use a primary key for this table.
379 38 Table& unsetPrimaryKey()
380 {
381 38 primary_key_column_.clear();
382 38 return *this;
383 }
384
385 /// Get the primary key column for this table. Defaults to "Id".
386 559 const std::string& getPrimaryKey() const { return primary_key_column_; }
387
388 /// Read-only access to this table's columns.
389 11149 const std::vector<std::shared_ptr<Column>>& getColumns() const { return columns_; }
390
391 /// Equivalency check.
392 7 bool operator==(const Table& rhs) const
393 {
394
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 7 times.
7 if (name_ != rhs.name_)
395 {
396 ✗ return false;
397 }
398
399
2/2
✓ Branch 7 → 8 taken 1 time.
✓ Branch 7 → 9 taken 6 times.
7 if (columns_.size() != rhs.columns_.size())
400 {
401 1 return false;
402 }
403
404
2/2
✓ Branch 19 → 10 taken 20 times.
✓ Branch 19 → 20 taken 6 times.
26 for (size_t idx = 0; idx < columns_.size(); ++idx)
405 {
406
1/2
✗ Branch 15 → 16 not taken.
✓ Branch 15 → 17 taken 20 times.
20 if (*(columns_[idx]) != *(rhs.columns_[idx]))
407 {
408 ✗ return false;
409 }
410 }
411
412
4/5
✓ Branch 20 → 21 taken 6 times.
✓ Branch 21 → 22 taken 6 times.
✓ Branch 22 → 23 taken 6 times.
✗ Branch 25 → 26 not taken.
✓ Branch 25 → 27 taken 6 times.
6 if (getTableIndexes() != rhs.getTableIndexes())
413 {
414 ✗ return false;
415 }
416
417
1/2
✗ Branch 28 → 29 not taken.
✓ Branch 28 → 30 taken 6 times.
6 if (primary_key_column_ != rhs.primary_key_column_)
418 {
419 ✗ return false;
420 }
421
422 6 return true;
423 }
424
425 /// Equivalency check.
426 3 bool operator!=(const Table& rhs) const { return !(*this == rhs); }
427
428 private:
429 /// Get a column by its name. Throws if not found.
430 15 Column& getColumn_(const std::string& col_name)
431 {
432
1/1
✓ Branch 2 → 3 taken 15 times.
15 auto iter = columns_by_name_.find(col_name);
433
1/15
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 27 taken 15 times.
✗ Branch 8 → 9 not taken.
✗ Branch 9 → 10 not taken.
✗ Branch 11 → 12 not taken.
✗ Branch 15 → 16 not taken.
✗ Branch 16 → 17 not taken.
✗ Branch 17 → 18 not taken.
✗ Branch 18 → 19 not taken.
✗ Branch 19 → 20 not taken.
✗ Branch 20 → 21 not taken.
✗ Branch 21 → 22 not taken.
✗ Branch 22 → 23 not taken.
✗ Branch 23 → 24 not taken.
✗ Branch 25 → 26 not taken.
15 simdb_assert(iter != columns_by_name_.end(), "No column named " << col_name << " in table " << name_);
434
435 30 return *(iter->second);
436 }
437
438 /// Name of this table
439 std::string name_;
440
441 /// Columns in this table
442 std::vector<std::shared_ptr<Column>> columns_;
443
444 /// Map of columns by their name
445 std::unordered_map<std::string, std::shared_ptr<Column>> columns_by_name_;
446
447 /// List of index creation strings that are executed on the database
448 /// when the schema is instantiated:
449 ///
450 /// CREATE INDEX IndexName ON TableName(ColumnName)
451 /// CREATE INDEX IndexName ON TableName(ColA,ColB,ColC)
452 /// . . . . . . . . . . . . . . . . .
453 std::vector<std::string> index_creation_strs_;
454
455 /// Use an auto-incrementing primary key "Id" for this table by default.
456 std::string primary_key_column_ = "Id";
457
458 friend class Connection;
459
460 /// DatabaseManager needs getColumn_
461 friend class DatabaseManager;
462 };
463
464 /*!
465 * \class Schema
466 *
467 * \brief This class is used to define SimDB schemas.
468 */
469 class Schema
470 {
471 public:
472 /// \brief Create a new Table in this Schema with the given name
473 ///
474 /// \return Reference to the added table
475 237 Table& addTable(const std::string& table_name)
476 {
477
2/2
✓ Branch 32 → 4 taken 821 times.
✓ Branch 32 → 33 taken 236 times.
1057 for (auto& lhs : tables_)
478 {
479
14/14
✓ Branch 7 → 8 taken 1 time.
✓ Branch 7 → 30 taken 820 times.
✓ Branch 10 → 11 taken 1 time.
✓ Branch 11 → 12 taken 1 time.
✓ Branch 13 → 14 taken 1 time.
✓ Branch 17 → 18 taken 1 time.
✓ Branch 18 → 19 taken 1 time.
✓ Branch 19 → 20 taken 1 time.
✓ Branch 22 → 23 taken 1 time.
✓ Branch 23 → 24 taken 1 time.
✓ Branch 24 → 25 taken 1 time.
✓ Branch 25 → 26 taken 1 time.
✓ Branch 26 → 27 taken 1 time.
✓ Branch 28 → 29 taken 1 time.
823 simdb_assert(lhs.getName() != table_name,
480 "Cannot add table '" + table_name + "' to schema. A table with that name already exists.");
481 }
482
483 236 tables_.emplace_back(table_name);
484 236 return tables_.back();
485 }
486
487 /// Combine this schema with the tables from another schema.
488 62 void appendSchema(const Schema& schema)
489 {
490
2/2
✓ Branch 38 → 5 taken 170 times.
✓ Branch 38 → 39 taken 61 times.
231 for (const auto& table : schema.getTables())
491 {
492
2/2
✓ Branch 8 → 9 taken 4 times.
✓ Branch 8 → 35 taken 166 times.
170 if (hasTable(table.getName()))
493 {
494
1/1
✓ Branch 10 → 11 taken 4 times.
4 auto& existing_table = getTable(table.getName());
495
16/16
✓ Branch 11 → 12 taken 4 times.
✓ Branch 12 → 13 taken 1 time.
✓ Branch 12 → 36 taken 3 times.
✓ Branch 15 → 16 taken 1 time.
✓ Branch 16 → 17 taken 1 time.
✓ Branch 18 → 19 taken 1 time.
✓ Branch 22 → 23 taken 1 time.
✓ Branch 23 → 24 taken 1 time.
✓ Branch 25 → 26 taken 1 time.
✓ Branch 26 → 27 taken 1 time.
✓ Branch 27 → 28 taken 1 time.
✓ Branch 28 → 29 taken 1 time.
✓ Branch 29 → 30 taken 1 time.
✓ Branch 30 → 31 taken 1 time.
✓ Branch 31 → 32 taken 1 time.
✓ Branch 33 → 34 taken 1 time.
6 simdb_assert(existing_table == table, "Cannot append schema - it has a table "
496 "we already have by that name "
497 << "(" << table.getName() << ")");
498 } else
499 {
500
1/1
✓ Branch 35 → 36 taken 166 times.
166 tables_.push_back(table);
501 }
502 }
503 61 }
504
505 /// Read-only access to this schema's tables.
506 199 const std::deque<Table>& getTables() const { return tables_; }
507
508 /// Get a table by its name. Throws if not found.
509 10555 const Table& getTable(const std::string& table_name) const
510 {
511
2/2
✓ Branch 11 → 4 taken 47286 times.
✓ Branch 11 → 12 taken 1 time.
47287 for (const auto& table : tables_)
512 {
513
2/2
✓ Branch 7 → 8 taken 10554 times.
✓ Branch 7 → 9 taken 36732 times.
47286 if (table.getName() == table_name)
514 {
515 10554 return table;
516 }
517 }
518
519
3/3
✓ Branch 13 → 14 taken 1 time.
✓ Branch 14 → 15 taken 1 time.
✓ Branch 16 → 17 taken 1 time.
1 throw DBException("Table '" + table_name + "' not found in schema");
520 }
521
522 /// Before calling getTable(), you can use this method to
523 /// check if a table with the given name exists in this schema.
524 208 bool hasTable(const std::string& table_name) const
525 {
526
2/2
✓ Branch 11 → 4 taken 956 times.
✓ Branch 11 → 12 taken 197 times.
1153 for (const auto& table : tables_)
527 {
528
2/2
✓ Branch 7 → 8 taken 11 times.
✓ Branch 7 → 9 taken 945 times.
956 if (table.getName() == table_name)
529 {
530 11 return true;
531 }
532 }
533
534 197 return false;
535 }
536
537 /// Equivalency check.
538 1 bool operator==(const Schema& rhs) const
539 {
540 2 auto getTableNames = [](const Schema& schema) {
541 2 std::unordered_set<std::string> table_names;
542
2/2
✓ Branch 11 → 6 taken 6 times.
✓ Branch 11 → 12 taken 2 times.
8 for (const auto& tbl : schema.getTables())
543 {
544
1/1
✓ Branch 8 → 9 taken 6 times.
6 table_names.insert(tbl.getName());
545 }
546 2 return table_names;
547 ✗ };
548
549
1/1
✓ Branch 2 → 3 taken 1 time.
1 auto my_table_names = getTableNames(*this);
550
1/1
✓ Branch 3 → 4 taken 1 time.
1 auto their_table_names = getTableNames(rhs);
551
2/3
✓ Branch 4 → 5 taken 1 time.
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 1 time.
1 if (my_table_names != their_table_names)
552 {
553 ✗ return false;
554 }
555
556
2/2
✓ Branch 17 → 9 taken 3 times.
✓ Branch 17 → 18 taken 1 time.
4 for (const auto& table_name : my_table_names)
557 {
558
1/1
✓ Branch 10 → 11 taken 3 times.
3 const auto& my_table = getTable(table_name);
559
1/1
✓ Branch 11 → 12 taken 3 times.
3 const auto& their_table = getTable(table_name);
560
2/3
✓ Branch 12 → 13 taken 3 times.
✗ Branch 13 → 14 not taken.
✓ Branch 13 → 15 taken 3 times.
3 if (my_table != their_table)
561 {
562 ✗ return false;
563 }
564 }
565
566 1 return true;
567 1 }
568
569 private:
570 /// All the tables in this schema, whether added via
571 /// addTable() or appendSchema().
572 std::deque<Table> tables_;
573 };
574
575 } // namespace simdb
576