| 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 |
|
|
|