taco-db  0.1.0
IndexKey.h
Go to the documentation of this file.
1 #ifndef INDEX_INDEXKEY_H
2 #define INDEX_INDEXKEY_H
3 
4 #include "tdb.h"
5 
6 #include "catalog/Schema.h"
7 
8 namespace taco {
9 
10 struct IndexKey;
11 
13 typedef std::unique_ptr<IndexKey, AlignedAllocImpl::FreeMem> UniqueIndexKey;
14 
35 struct IndexKey {
36 public:
42  template<class SomeDatum>
43  static UniqueIndexKey
44  Create(const std::vector<SomeDatum> &data) {
45  if (data.size() > (size_t) std::numeric_limits<FieldId>::max()) {
46  LOG(kFatal, "too many fields in a key: %lu", data.size());
47  }
48  FieldId nkeys = (FieldId) data.size();
49  size_t sz = ComputeStructSize(nkeys);
50  void *new_key = aligned_alloc(8, sz);
51  ConstructImpl(new_key, data.data(), nkeys, sz);
52  return UniqueIndexKey((IndexKey*) new_key);
53  }
54 
55  template<class SomeDatum>
56  static UniqueIndexKey
57  Create(SomeDatum *data, FieldId nkeys) {
58  size_t sz = ComputeStructSize(nkeys);
59  void *new_key = aligned_alloc(8, sz);
60  ConstructImpl(new_key, data, nkeys, sz);
61  return UniqueIndexKey((IndexKey*) new_key);
62  }
63 
74  template<class SomeDatum>
75  static void
76  Construct(void *key, const std::vector<SomeDatum> &data) {
77  if (data.size() > (size_t) std::numeric_limits<FieldId>::max()) {
78  LOG(kFatal, "too many fields in a key: %lu", data.size());
79  }
80  FieldId nkeys = (FieldId) data.size();
81  size_t sz = ComputeStructSize(nkeys);
82  ConstructImpl(key, data.data(), nkeys, sz);
83  }
84 
85  template<class SomeDatum>
86  static void
87  Construct(void *key, SomeDatum *data, FieldId nkeys) {
88  size_t sz = ComputeStructSize(nkeys);
89  ConstructImpl(key, data, nkeys, sz);
90  }
91 
98  Copy() const {
99  size_t sz = ComputeStructSize(GetNumKeys());
100  void *new_key = aligned_alloc(8, sz);
101  ConstructImpl(new_key, &GetKey(0), GetNumKeys(), sz);
102  return UniqueIndexKey((IndexKey*) new_key);
103  }
104 
113  void
114  CopyTo(IndexKey *key2) const {
115  memcpy((void*) key2, (void*) this, GetStructSize());
116  }
117 
128  void
129  DeepCopy(const Schema *sch, std::vector<Datum> &data_buffer) {
130  FieldId nkeys = GetNumKeys();
131  ASSERT(nkeys <= sch->GetNumFields());
132  for (FieldId i = 0; i < nkeys; ++i) {
133  if (!IsNull(i) && sch->FieldPassByRef(i)) {
134  Datum &old_datum = GetKey(i).GetDatum();
135  if (data_buffer.size() == data_buffer.capacity() &&
136  !data_buffer.empty()) {
137  LOG(kFatal, "causing the data buffer to increase capacity "
138  "and this will make previously deep copied "
139  "IndexKey contain dangling pointers (need to "
140  "reserve space on the vector first!).");
141  }
142  data_buffer.emplace_back(old_datum.DeepCopy());
143  GetKey(i) = data_buffer.back();
144  }
145  }
146  }
147 
151  inline FieldId
152  GetNumKeys() const {
153  return *reinterpret_cast<const FieldId*>(this);
154  }
155 
163  inline DatumRef&
164  GetKey(FieldId keyid) const {
165  return ((DatumRef*)(((uint8_t*) m_data)
166  + MAXALIGN(2 + ((GetNumKeys() + 7) >> 3))))[keyid];
167  }
168 
177  template<class SomeDatum>
178  void
179  SetKey(FieldId keyid, const SomeDatum &key) {
180  if (key.isnull()) {
181  SetNullBit(keyid, true);
182  // The datum is left as is here because it is undefined to
183  // call GetKey() if a field is declared as null.
184  } else {
185  SetNullBit(keyid, false);
186  // relying on implicit conversions if SomeDatum is not DatumRef
187  GetKey(keyid) = key;
188  }
189  }
190 
195  inline bool
196  IsNull(FieldId keyid) const {
197  if (keyid >= GetNumKeys()) {
198  return true;
199  }
200  return !!(((uint8_t*) &m_data)[2 + (keyid >> 3)] & (1 << (keyid & 7)));
201  }
202 
207  inline void
208  SetNullBit(FieldId keyid, bool isnull) const {
209  if (isnull)
210  ((uint8_t*) &m_data)[2 + (keyid >> 3)] |= (1 << (keyid & 7));
211  else
212  ((uint8_t*) &m_data)[2 + (keyid >> 3)] &=
213  ~(uint8_t)(1 << (keyid & 7));
214  }
215 
219  inline bool
220  HasAnyNull() const {
221  uint8_t *bm = ((uint8_t *) &m_data) + 2;
222  size_t n = GetNumKeys() >> 3;
223  for (size_t i = 0; i < n; ++i) {
224  // this is ok because we zero filled the null bitmap initially.
225  if (bm[i] != 0)
226  return true;
227  }
228  return false;
229  }
230 
236  inline size_t
237  GetStructSize() const {
238  return ComputeStructSize(GetNumKeys());
239  }
240 
245  inline static size_t
247  size_t sz = MAXALIGN(2 + ((nkeys + 7) >> 3)) + nkeys * sizeof(DatumRef);
248  return sz;
249  }
250 
254  inline NullableDatumRef
255  GetNullableKey(FieldId keyid) const {
256  if (IsNull(keyid)) {
258  }
259  return NullableDatumRef(GetKey(keyid));
260  }
261 
265  std::vector<NullableDatumRef>
267  std::vector<NullableDatumRef> vec;
268  vec.reserve(GetNumKeys());
269  for (FieldId i = 0; i < GetNumKeys(); ++i) {
270  vec.emplace_back(GetNullableKey(i));
271  }
272  return vec;
273  }
274 
275  IndexKey(const IndexKey&) = delete;
276  IndexKey(IndexKey&&) = delete;
277  IndexKey &operator=(const IndexKey&) = delete;
279 
280 private:
281  template<class SomeDatum>
282  static void
283  ConstructImpl(void *key, SomeDatum *data,
284  FieldId nkeys, size_t sz) {
285  *(FieldId *)key = nkeys;
286  uint8_t *bm = ((uint8_t *) key ) + 2;
287  DatumRef *key_data =
288  (DatumRef*)(((uint8_t *) key) + sz - nkeys * sizeof(DatumRef));
289  memset(bm, 0, ((nkeys + 7) >> 3));
290  for (FieldId i = 0; i < nkeys; ++i) {
291  if (data[i].isnull()) {
292  bm[i >> 3] |= 1 << (i & 7);
293  } else {
294  key_data[i] = DatumRef(data[i]);
295  }
296  }
297  }
298 
299  // forces 8-byte alignment
300  uint64_t m_data[1];
301 };
302 
303 } // namespace taco
304 
305 #endif // INDEX_INDEXKEY_H
306 
A DatumRef object is a read-only reference to an C++ object of a supported runtime type.
Definition: datum.h:823
A Datum stores and possibly manage the memory resource of a read-only value of a plain fixed-length C...
Definition: datum.h:250
static Datum FromNull()
Definition: datum.h:343
Datum DeepCopy() const
Returns a deep copy of this datum so that HasExternalRef() == false and the owned value is a copy of ...
Definition: datum.h:621
Definition: datum.h:861
A Schema object stores the information for accessing an ordered set of typed fields either from a dis...
Definition: Schema.h:39
bool FieldPassByRef(FieldId field_id) const
Returns whether this field is passed by reference or by value in memory.
Definition: Schema.h:262
constexpr Datum & GetDatum() const
Returns a reference to the underlying datum if this references one with a variable-length value.
Definition: datum.h:777
#define LOG(level,...)
LOG(LogSeverity level, const char *fmt, ...)
Definition: logging.h:116
Definition: datum.h:28
constexpr LogSeverity kFatal
Definition: logging.h:22
int16_t FieldId
Definition: tdb_base.h:212
std::unique_ptr< IndexKey, AlignedAllocImpl::FreeMem > UniqueIndexKey
The returned smart pointer of IndexKey::Create().
Definition: IndexKey.h:10
An IndexKey stores references to a few data (Datum objects) that comprise a key tuple to in an index.
Definition: IndexKey.h:35
static void Construct(void *key, const std::vector< SomeDatum > &data)
Constructs a new IndexKey that references the data on a preallocated key.
Definition: IndexKey.h:76
static void Construct(void *key, SomeDatum *data, FieldId nkeys)
Definition: IndexKey.h:87
static size_t ComputeStructSize(FieldId nkeys)
Computes the minimum size of an byte array to store this IndexKey that holds nkeys.
Definition: IndexKey.h:246
DatumRef & GetKey(FieldId keyid) const
Returns the key keyid.
Definition: IndexKey.h:164
void DeepCopy(const Schema *sch, std::vector< Datum > &data_buffer)
Makes a deep copy of all the variable-length Datum the key is refernecing in a newly allocated memory...
Definition: IndexKey.h:129
uint64_t m_data[1]
Definition: IndexKey.h:300
void CopyTo(IndexKey *key2) const
Makes a copy of the index key to an existing index key.
Definition: IndexKey.h:114
size_t GetStructSize() const
Returns the minimum size of the byte array to store this IndexKey.
Definition: IndexKey.h:237
IndexKey & operator=(IndexKey &&)=delete
bool HasAnyNull() const
Returns if any of the keys is null.
Definition: IndexKey.h:220
std::vector< NullableDatumRef > ToNullableDatumVector() const
Returns the IndexKey as an std::vector<NullableDatumRef>.
Definition: IndexKey.h:266
void SetKey(FieldId keyid, const SomeDatum &key)
Sets the keyid-th field in this index key.
Definition: IndexKey.h:179
static UniqueIndexKey Create(const std::vector< SomeDatum > &data)
Allocates and constructs a new IndexKey that references the data.
Definition: IndexKey.h:44
void SetNullBit(FieldId keyid, bool isnull) const
Sets or clears the null bit for the key \keyid.
Definition: IndexKey.h:208
FieldId GetNumKeys() const
Returns the number of keys in this IndexKey.
Definition: IndexKey.h:152
IndexKey(IndexKey &&)=delete
NullableDatumRef GetNullableKey(FieldId keyid) const
Returns the key \keyid as a NullableDatumRef.
Definition: IndexKey.h:255
UniqueIndexKey Copy() const
Makes a copy of the index key in a newly allocated buffer.
Definition: IndexKey.h:98
bool IsNull(FieldId keyid) const
Returns the key keyid is null.
Definition: IndexKey.h:196
IndexKey(const IndexKey &)=delete
static UniqueIndexKey Create(SomeDatum *data, FieldId nkeys)
Definition: IndexKey.h:57
static void ConstructImpl(void *key, SomeDatum *data, FieldId nkeys, size_t sz)
Definition: IndexKey.h:283
IndexKey & operator=(const IndexKey &)=delete
#define MAXALIGN(LEN)
Definition: tdb_base.h:327
#define ASSERT(...)
Definition: tdb_base.h:190