Zero  0.1.0
row.h
Go to the documentation of this file.
1 /* -*- mode:C++; c-basic-offset:4 -*-
2  Shore-kits -- Benchmark implementations for Shore-MT
3 
4  Copyright (c) 2007-2009
5  Data Intensive Applications and Systems Labaratory (DIAS)
6  Ecole Polytechnique Federale de Lausanne
7 
8  All Rights Reserved.
9 
10  Permission to use, copy, modify and distribute this software and
11  its documentation is hereby granted, provided that both the
12  copyright notice and this permission notice appear in all copies of
13  the software, derivative works or modified versions, and any
14  portions thereof, and that both notices appear in supporting
15  documentation.
16 
17  This code is distributed in the hope that it will be useful, but
18  WITHOUT ANY WARRANTY; without even the implied warranty of
19  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS
20  DISCLAIM ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER
21  RESULTING FROM THE USE OF THIS SOFTWARE.
22 */
23 
35 /* shore_row.h contains the (abstract) base class (table_row_t) for the
36  * tuple representation.
37  *
38  *
39  * FUNCTIONALITY
40  *
41  * There are methods for formatting a tuple to its disk representation,
42  * and loading it to memory, as well as, methods for accessing
43  * the various fields of the tuple.
44  *
45  *
46  * BUGS:
47  *
48  * Timestamp field is not fully implemented: no set function.
49  *
50  *
51  * EXTENSIONS:
52  *
53  * The mapping between SQL types and C++ types are defined in
54  * (field_desc_t). Modify the class to support more SQL types or
55  * change the mapping. The NUMERIC type is currently stored as string;
56  * no further understanding is provided yet.
57  *
58  */
59 
60 /* The disk format of the record looks like this:
61  *
62  * +--+-----+------------+-+-+-----+-------------+
63  * |NF| a | d | | | b | c |
64  * +--+-----+------------+-+-+-----+-------------+
65  * | | ^ ^
66  * | +------+-------------+
67  * | |
68  * +--------+
69  *
70  * The first part of tuple (NF) is dedicated to the null flags. There
71  * is a bit for each nullable field in null flags to tell whether the
72  * data is presented. The space for the null flag is rounded to bytes.
73  *
74  * All the fixed size fields go first (a and d) and variable length
75  * fields are appended after that. (b and c). For the variable length
76  * fields, we don't reserve the space for the full length of the value
77  * but allocate as much space as needed. Therefore, we need offsets
78  * to tell the length of the actual values. So here comes the two
79  * additional slots in the middle (between d and b). In our
80  * implementation, we store the offset of the end of b relative to the
81  * beginning of the tuple (address of a).
82  *
83  */
84 
85 #ifndef __ROW_H
86 #define __ROW_H
87 
88 
89 //#include "k_defines.h"
90 
91 #include "field.h"
92 #include "block_alloc.h"
93 
95 
96 /* ---------------------------------------------------------------
97  *
98  * @struct: rep_row_t
99  *
100  * @brief: A simple structure with a pointer to a buffer and its
101  * corresponding size.
102  *
103  * @note: Not thread-safe, the caller should regulate access.
104  *
105  * --------------------------------------------------------------- */
106 
107 typedef intptr_t offset_t;
108 
109 /* ---------------------------------------------------------------
110  *
111  * @struct: rep_row_t
112  *
113  * @brief: A scratchpad for writing the disk format of a tuple
114  *
115  * --------------------------------------------------------------- */
116 
117 struct rep_row_t {
118  char* _dest; /* pointer to a buffer */
119  unsigned _bufsz; /* buffer size */
120  blob_pool* _pts; /* pointer to a trash stack */
121 
122 
123  rep_row_t();
124 
125  rep_row_t(blob_pool* apts);
126 
127  ~rep_row_t();
128 
129  void set(const unsigned nsz);
130 
131  void set_ts(blob_pool* apts, const unsigned nsz);
132 }; // EOF: rep_row_t
133 
134 
135 
136 /* ---------------------------------------------------------------
137  *
138  * @abstract struct: table_row_t
139  *
140  * @brief: Abstract base class for the representation a row (record)
141  * of a table.
142  *
143  * --------------------------------------------------------------- */
144 
145 class table_desc_t;
146 
147 class table_row_t {
148 public:
149  table_desc_t* _ptable; /* pointer back to the table description */
150 
151  unsigned _field_cnt; /* number of fields */
152  bool _is_setup; /* flag if already setup */
153 
154  field_value_t* _pvalues; /* set of values */
155 
156  // pre-calculated offsets
158 
160 
162 
163  unsigned _null_count;
164 
165  // CS TODO -- get rid of these
166  // But think about whether we should maintain the general principle,
167  // which is to maintain a buffer for the serialized format of the tuple.
168  // This could be useful to avoid repeated conversions, but it relies on
169  // the caller to know whether the tuple changed since the last conversion
170  // or not.
171  rep_row_t* _rep; /* a pointer to a row representation struct */
173 
174  /*
175  * CS: New methods for serialization and deserialization
176  * (a.k.a. conversion between disk and memory format)
177  */
178  void load_key(char* data, index_desc_t* pindex = nullptr);
179 
180  void load_value(char* data, index_desc_t* pindex = nullptr);
181 
182  void store_key(char* data, size_t& length, index_desc_t* pindex = nullptr);
183 
184  void store_value(char* data, size_t& length, index_desc_t* pindex = nullptr);
185 
186 
187  /* -------------------- */
188  /* --- construction --- */
189  /* -------------------- */
190 
191  table_row_t();
192 
194  : _ptable(nullptr),
195  _field_cnt(0),
196  _is_setup(false),
197  _pvalues(nullptr),
198  _fixed_offset(0),
199  _var_slot_offset(0),
200  _var_offset(0),
201  _null_count(0),
202  _rep(nullptr),
203  _rep_key(nullptr) {
204  assert (ptd);
205  setup(ptd);
206  }
207 
208  virtual ~table_row_t();
209 
210 
211 
212  /* ----------------------------------------------------------------- */
213  /* --- setup row according to table description, asserts if NULL --- */
214  /* --- this setup is done only once, at the initialization of --- */
215  /* --- the record in the cache --- */
216  /* ----------------------------------------------------------------- */
217 
218  int setup(table_desc_t* ptd);
219 
220 
221  /* ---------------------- */
222  /* --- access methods --- */
223  /* ---------------------- */
224 
225  inline offset_t get_fixed_offset() const {
226  return (_fixed_offset);
227  }
228 
229  inline offset_t get_var_slot_offset() const {
230  return (_var_slot_offset);
231  }
232 
233  inline offset_t get_var_offset() const {
234  return (_var_offset);
235  }
236 
237  inline unsigned get_null_count() const {
238  return (_null_count);
239  }
240 
241  unsigned size() const;
242 
243 
244  /* ------------------------ */
245  /* --- set field values --- */
246  /* ------------------------ */
247 
248  void set_null(const unsigned idx);
249 
250  void set_value(const unsigned idx, const int v);
251 
252  void set_value(const unsigned idx, const bool v);
253 
254  void set_value(const unsigned idx, const short v);
255 
256  void set_value(const unsigned idx, const double v);
257 
258  void set_value(const unsigned idx, const long long v);
259 
260  void set_value(const unsigned idx, const uint64_t v);
261 
262  void set_value(const unsigned idx, const decimal v);
263 
264  void set_value(const unsigned idx, const time_t v);
265 
266  void set_value(const unsigned idx, const char v);
267 
268  void set_value(const unsigned idx, const char* string);
269 
270  void set_value(const unsigned idx, const timestamp_t& time);
271 
272 
273  /* ------------------------ */
274  /* --- get field values --- */
275  /* ------------------------ */
276 
277  bool get_value(const unsigned idx, int& dest) const;
278 
279  bool get_value(const unsigned idx, bool& dest) const;
280 
281  bool get_value(const unsigned idx, short& dest) const;
282 
283  bool get_value(const unsigned idx, char& dest) const;
284 
285  bool get_value(const unsigned idx, char* destbuf, const unsigned bufsize) const;
286 
287  bool get_value(const unsigned idx, double& dest) const;
288 
289  bool get_value(const unsigned idx, uint64_t& dest) const;
290 
291  bool get_value(const unsigned idx, long long& dest) const;
292 
293  bool get_value(const unsigned idx, decimal& dest) const;
294 
295  bool get_value(const unsigned idx, time_t& dest) const;
296 
297  bool get_value(const unsigned idx, timestamp_t& dest) const;
298 
299 
300  /* ----------------- */
301  /* --- debugging --- */
302  /* ----------------- */
303 
304  void print_values(ostream& os = cout); /* print the tuple values */
305  void print_tuple(); /* print the whole tuple */
306  void print_tuple_no_tracing(); /* print the whole tuple without trace msg */
307 
308 
309  /* ------------------------------ */
310  /* --- required functionality --- */
311  /* ------------------------------ */
312 
313  // virtual void reset()=0; /* clear the tuple and prepare it for re-use */
314 
315  /* clear the tuple and prepare it for re-use */
316  void reset() {
317  assert (_is_setup);
318  for (unsigned i = 0; i < _field_cnt; i++) {
319  _pvalues[i].reset();
320  }
321  }
322 
323  void freevalues() {
324  if (_pvalues) {
325  delete[] _pvalues;
326  _pvalues = nullptr;
327  }
328  }
329 }; // EOF: table_row_t
330 
331 
332 /******************************************************************
333  *
334  * class tuple_guard
335  *
336  * @brief: guard object to manage table_row_t operations more easily
337  * reduces code complexity when using table_row_t in xcts
338  *
339  ******************************************************************/
340 template<class M, class T=table_row_t>
341 struct tuple_guard {
342  T* ptr;
343 
345 
347  : ptr(m->get_tuple()),
348  manager(m) {
349  assert(ptr);
350  }
351 
353  manager->give_tuple(ptr);
354  }
355 
357  return ptr;
358  }
359 
360  operator T*() {
361  return ptr;
362  }
363 
364 private:
365  // no you copy!
367 
368  void operator=(tuple_guard&);
369 };
370 
371 
372 /******************************************************************
373  *
374  * class table_row_t methods
375  *
376  * @brief: The {set,get}_value() functions are very frequently called.
377  * Therefore, they have been inlined here.
378  *
379  ******************************************************************/
380 
381 
382 /******************************************************************
383  *
384  * SET value functions
385  *
386  ******************************************************************/
387 
388 inline void table_row_t::set_null(const unsigned idx) {
389  assert (_is_setup);
390  assert (idx < _field_cnt);
391  assert (_pvalues[idx].is_setup());
392  _pvalues[idx].set_null();
393 }
394 
395 inline void table_row_t::set_value(const unsigned idx, const int v) {
396  assert (_is_setup);
397  assert (idx < _field_cnt);
398  assert (_pvalues[idx].is_setup());
399  _pvalues[idx].set_int_value(v);
400 }
401 
402 inline void table_row_t::set_value(const unsigned idx, const bool v) {
403  assert (_is_setup);
404  assert (idx < _field_cnt);
405  assert (_pvalues[idx].is_setup());
406  _pvalues[idx].set_bit_value(v);
407 }
408 
409 inline void table_row_t::set_value(const unsigned idx, const short v) {
410  assert (_is_setup);
411  assert (idx < _field_cnt);
412  assert (_pvalues[idx].is_setup());
413  _pvalues[idx].set_smallint_value(v);
414 }
415 
416 inline void table_row_t::set_value(const unsigned idx, const double v) {
417  assert (_is_setup);
418  assert (idx < _field_cnt);
419  assert (_pvalues[idx].is_setup());
420  _pvalues[idx].set_float_value(v);
421 }
422 
423 inline void table_row_t::set_value(const unsigned idx, const long long v) {
424  assert (_is_setup);
425  assert (idx < _field_cnt);
426  assert (_pvalues[idx].is_setup());
427  _pvalues[idx].set_long_value(v);
428 }
429 
430 inline void table_row_t::set_value(const unsigned idx, const uint64_t v) {
431  assert (_is_setup);
432  assert (idx < _field_cnt);
433  assert (_pvalues[idx].is_setup());
434  _pvalues[idx].set_long_value(v);
435 }
436 
437 inline void table_row_t::set_value(const unsigned idx, const decimal v) {
438  assert (_is_setup);
439  assert (idx < _field_cnt);
440  assert (_pvalues[idx].is_setup());
441  _pvalues[idx].set_decimal_value(v);
442 }
443 
444 inline void table_row_t::set_value(const unsigned idx, const time_t v) {
445  assert (_is_setup);
446  assert (idx < _field_cnt);
447  assert (_pvalues[idx].is_setup());
448  _pvalues[idx].set_time_value(v);
449 }
450 
451 inline void table_row_t::set_value(const unsigned idx, const char v) {
452  assert (_is_setup);
453  assert (idx < _field_cnt);
454  assert (_pvalues[idx].is_setup());
455  _pvalues[idx].set_char_value(v);
456 }
457 
458 inline void table_row_t::set_value(const unsigned idx, const char* string) {
459  assert (_is_setup);
460  assert (idx < _field_cnt);
461  assert (_pvalues[idx].is_setup());
462 
463  sqltype_t sqlt = _pvalues[idx].field_desc()->type();
464  assert (sqlt == SQL_VARCHAR || sqlt == SQL_FIXCHAR);
465 
466  int len = strlen(string);
467  if (sqlt == SQL_VARCHAR) {
468  // if variable length
469  _pvalues[idx].set_var_string_value(string, len);
470  } else {
471  // if fixed length
472  _pvalues[idx].set_fixed_string_value(string, len);
473  }
474 }
475 
476 inline void table_row_t::set_value(const unsigned idx, const timestamp_t& time) {
477  assert (_is_setup);
478  assert (idx < _field_cnt);
479  assert (_pvalues[idx].is_setup());
480  _pvalues[idx].set_value(&time, 0);
481 }
482 
483 /******************************************************************
484  *
485  * GET value functions
486  *
487  ******************************************************************/
488 
489 inline bool table_row_t::get_value(const unsigned idx,
490  int& dest) const {
491  assert (_is_setup);
492  assert(idx < _field_cnt);
493  if (_pvalues[idx].is_null()) {
494  dest = 0;
495  return false;
496  }
497  dest = _pvalues[idx].get_int_value();
498  return true;
499 }
500 
501 inline bool table_row_t::get_value(const unsigned idx,
502  bool& dest) const {
503  assert (_is_setup);
504  assert(idx < _field_cnt);
505  if (_pvalues[idx].is_null()) {
506  dest = false;
507  return false;
508  }
509  dest = _pvalues[idx].get_bit_value();
510  return true;
511 }
512 
513 inline bool table_row_t::get_value(const unsigned idx,
514  short& dest) const {
515  assert (_is_setup);
516  assert(idx < _field_cnt);
517  if (_pvalues[idx].is_null()) {
518  dest = 0;
519  return false;
520  }
521  dest = _pvalues[idx].get_smallint_value();
522  return true;
523 }
524 
525 inline bool table_row_t::get_value(const unsigned idx,
526  char& dest) const {
527  assert (_is_setup);
528  assert(idx < _field_cnt);
529  if (_pvalues[idx].is_null()) {
530  dest = 0;
531  return false;
532  }
533  dest = _pvalues[idx].get_char_value();
534  return true;
535 }
536 
537 inline bool table_row_t::get_value(const unsigned idx,
538  char* destbuf,
539  const unsigned bufsize) const {
540  assert (_is_setup);
541  assert(idx < _field_cnt);
542  if (_pvalues[idx].is_null()) {
543  destbuf[0] = '\0';
544  return (false);
545  }
546  // if variable length
547  unsigned sz = MIN(bufsize - 1, _pvalues[idx]._max_size);
548  _pvalues[idx].get_string_value(destbuf, sz);
549  destbuf[sz] = '\0';
550  return (true);
551 }
552 
553 inline bool table_row_t::get_value(const unsigned idx,
554  double& dest) const {
555  assert (_is_setup);
556  assert(idx < _field_cnt);
557  if (_pvalues[idx].is_null()) {
558  dest = 0;
559  return false;
560  }
561  dest = _pvalues[idx].get_float_value();
562  return true;
563 }
564 
565 inline bool table_row_t::get_value(const unsigned idx,
566  long long& dest) const {
567  assert (_is_setup);
568  assert(idx < _field_cnt);
569  if (_pvalues[idx].is_null()) {
570  dest = 0;
571  return false;
572  }
573  dest = _pvalues[idx].get_long_value();
574  return true;
575 }
576 
577 inline bool table_row_t::get_value(const unsigned idx,
578  uint64_t& dest) const {
579  assert (_is_setup);
580  assert(idx < _field_cnt);
581  if (_pvalues[idx].is_null()) {
582  dest = 0;
583  return false;
584  }
585  dest = _pvalues[idx].get_long_value();
586  return true;
587 }
588 
589 inline bool table_row_t::get_value(const unsigned idx,
590  decimal& dest) const {
591  assert (_is_setup);
592  assert(idx < _field_cnt);
593  if (_pvalues[idx].is_null()) {
594  dest = decimal(0);
595  return false;
596  }
597  dest = _pvalues[idx].get_decimal_value();
598  return true;
599 }
600 
601 inline bool table_row_t::get_value(const unsigned idx,
602  time_t& dest) const {
603  assert (_is_setup);
604  assert(idx < _field_cnt);
605  if (_pvalues[idx].is_null()) {
606  return false;
607  }
608  dest = _pvalues[idx].get_time_value();
609  return true;
610 }
611 
612 inline bool table_row_t::get_value(const unsigned idx,
613  timestamp_t& dest) const {
614  assert (_is_setup);
615  assert(idx < _field_cnt);
616  if (_pvalues[idx].is_null()) {
617  return false;
618  }
619  dest = _pvalues[idx].get_tstamp_value();
620  return true;
621 }
622 
623 #endif // __ROW_H
Definition: row.h:341
Definition: table_desc.h:122
unsigned _null_count
Definition: row.h:163
M * manager
Definition: row.h:344
Definition: decimal.h:32
offset_t _var_slot_offset
Definition: row.h:159
offset_t _var_offset
Definition: row.h:161
unsigned get_null_count() const
Definition: row.h:237
~tuple_guard()
Definition: row.h:352
unsigned _field_cnt
Definition: row.h:151
~rep_row_t()
Definition: row.cpp:63
field_value_t * _pvalues
Definition: row.h:154
table_desc_t * _ptable
Definition: row.h:149
bool _is_setup
Definition: row.h:152
void reset()
Definition: row.h:316
#define MIN(x, y)
Definition: w_minmax.h:69
rep_row_t()
Definition: row.cpp:51
Definition: field.h:219
bool get_value(const unsigned idx, int &dest) const
Definition: row.h:489
void reset()
Definition: field.h:624
void set_value(const unsigned idx, const int v)
Definition: row.h:395
blob_pool * _pts
Definition: row.h:120
offset_t get_var_slot_offset() const
Definition: row.h:229
T * operator->()
Definition: row.h:356
Definition: field.h:107
Definition: index_desc.h:60
void freevalues()
Definition: row.h:323
offset_t get_var_offset() const
Definition: row.h:233
table_row_t(table_desc_t *ptd)
Definition: row.h:193
Definition: field.h:106
rep_row_t * _rep
Definition: row.h:171
tuple_guard(M *m)
Definition: row.h:346
Definition: row.h:117
void set_ts(blob_pool *apts, const unsigned nsz)
Definition: row.cpp:111
T * ptr
Definition: row.h:342
: Description and current value of a field (column)
sqltype_t
Definition: field.h:99
Definition: field.h:61
void set_null(const unsigned idx)
Definition: row.h:388
rep_row_t * _rep_key
Definition: row.h:172
offset_t get_fixed_offset() const
Definition: row.h:225
intptr_t offset_t
Definition: row.h:94
char * _dest
Definition: row.h:118
Definition: row.h:147
#define T
Definition: w_okvl_inl.h:45
unsigned _bufsz
Definition: row.h:119
offset_t _fixed_offset
Definition: row.h:157