1 /*
2 Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is also distributed with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have included with MySQL.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License, version 2.0, for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25 #ifndef NDB_PACK_HPP
26 #define NDB_PACK_HPP
27
28 #include <ndb_global.h>
29 #include <my_sys.h>
30 #include <kernel/AttributeHeader.hpp>
31 #include <NdbSqlUtil.hpp>
32 #include <NdbEnv.h>
33 class NdbOut;
34
35 /*
36 * Pack an array of NDB data values. The types are specified by an
37 * array of data types. There is no associated table or attribute ids.
38 * All or an initial sequence of the specified values are present.
39 *
40 * Currently used for ordered index keys and bounds in kernel (DBTUX)
41 * and in index statistics (mysqld). The comparison methods use the
42 * primitive type comparisons from NdbSqlUtil.
43 *
44 * Keys and bounds use same spec. However a value in an index bound can
45 * be NULL even if the key attribute is not nullable. Therefore bounds
46 * set the "allNullable" property and have a longer null mask.
47 *
48 * There are two distinct use occasions: 1) construction of data or
49 * bound 2) operating on previously constructed data or bound. There
50 * are classes Data/DataC and Bound/BoundC for these uses. The latter
51 * often can return a result without interpreting the full value.
52 *
53 * Methods return -1 on error and 0 on success. Comparison methods
54 * assume well-formed data and return negative, zero, positive for less,
55 * equal, greater.
56 */
57
58 class NdbPack {
59 public:
60 class Endian;
61 class Type;
62 class Spec;
63 class Iter;
64 class DataC;
65 class Data;
66 class BoundC;
67 class Bound;
68
69 /*
70 * Get SQL type.
71 */
72 static const NdbSqlUtil::Type& getSqlType(Uint32 typeId);
73
74 /*
75 * Error codes for core dumps.
76 */
77 class Error {
78 public:
79 enum {
80 TypeNotSet = -101, // type id was not set
81 TypeOutOfRange = -102, // type id is out of range
82 TypeNotSupported = -103, // blob (and for now bit) types
83 TypeSizeZero = -104, // max size was set to zero
84 TypeFixSizeInvalid = -105, // fixed size specified wrong
85 TypeNullableNotBool = -106, // nullable must be 0 or 1
86 CharsetNotSpecified = -107, // char type with no charset number
87 CharsetNotFound = -108, // cannot install in all_charsets[]
88 CharsetNotAllowed = -109, // non-char type with charset
89 SpecBufOverflow = -201, // more spec items than allocated
90 DataCntOverflow = -301, // more data items than in spec
91 DataBufOverflow = -302, // more data bytes than allocated
92 DataValueOverflow = -303, // var length exceeds max size
93 DataNotNullable = -304, // NULL value to not-nullable type
94 InvalidAttrInfo = -305, // invalid plain old attr info
95 BoundEmptySide = -401, // side not 0 for empty bound
96 BoundNonemptySide = -402, // side not -1,+1 for non-empty bound
97 InternalError = -901,
98 ValidationError = -902,
99 NoError = 0
100 };
101 Error();
~Error()102 ~Error() {}
103 int get_error_code() const;
104 int get_error_line() const;
105
106 private:
107 friend class Endian;
108 friend class Type;
109 friend class Spec;
110 friend class Iter;
111 friend class DataC;
112 friend class Data;
113 friend class BoundC;
114 friend class Bound;
115 void set_error(int code, int line) const;
116 void set_error(const Error& e2) const;
117 mutable int m_error_code;
118 mutable int m_error_line;
119 };
120
121 /*
122 * Endian definitions.
123 */
124 class Endian {
125 public:
126 enum Value {
127 Native = 0, // replaced by actual value
128 Little = 1,
129 Big = 2
130 };
131 static Value get_endian();
132 static void convert(void* ptr, Uint32 len);
133 };
134
135 /*
136 * Data type.
137 */
138 class Type : public Error {
139 public:
140 Type();
141 Type(int typeId, Uint32 byteSize, bool nullable, Uint32 csNumber);
~Type()142 ~Type() {}
143 /*
144 * Define the type. Size is fixed or max size. Values of variable
145 * length have length bytes. The definition is verified when the
146 * type is added to the specification. This also installs missing
147 * CHARSET_INFO* into all_charsets[].
148 */
149 void set(Uint32 typeId, Uint32 byteSize, bool nullable, Uint32 csNumber);
150 // getters
151 Uint32 get_type_id() const;
152 Uint32 get_byte_size() const;
153 bool get_nullable() const;
154 Uint32 get_cs_number() const;
155 Uint32 get_array_type() const;
156 // print
157 friend NdbOut& operator<<(NdbOut&, const Type&);
158 void print(NdbOut& out) const;
159 const char* print(char* buf, Uint32 bufsz) const;
160 int validate() const;
161
162 private:
163 friend class Spec;
164 friend class Iter;
165 friend class DataC;
166 friend class Data;
167 // verify and complete when added to specification
168 int complete();
169 Uint16 m_typeId;
170 Uint16 m_byteSize; // fixed or max size in bytes
171 Uint16 m_nullable;
172 Uint16 m_csNumber;
173 Uint16 m_arrayType; // 0,1,2 length bytes
174 Uint16 m_nullbitPos; // computed as part of Spec
175 };
176
177 /*
178 * Data specification i.e. array of types. Usually constructed on the
179 * heap, so keep fairly small. Used for boths keys and bounds.
180 */
181 class Spec : public Error {
182 public:
183 Spec();
~Spec()184 ~Spec() {}
185 // set initial buffer (calls reset)
186 void set_buf(Type* buf, Uint32 bufMaxCnt);
187 // use if buffer is relocated
188 void set_buf(Type* buf);
189 // reset but keep buffer
190 void reset();
191 // add type to specification once or number of times
192 int add(Type type);
193 int add(Type type, Uint32 cnt);
194 // copy from
195 void copy(const Spec& s2);
196 // getters (bounds set allNullable)
197 const Type& get_type(Uint32 i) const;
198 Uint32 get_cnt() const;
199 Uint32 get_nullable_cnt(bool allNullable) const;
200 Uint32 get_nullmask_len(bool allNullable) const;
201 // max data length including null mask
202 Uint32 get_max_data_len(bool allNullable) const;
203 // minimum var bytes (if used by Data instance)
204 Uint32 get_min_var_bytes(bool allNullable) const;
205 // print
206 friend NdbOut& operator<<(NdbOut&, const Spec&);
207 void print(NdbOut& out) const;
208 const char* print(char* buf, Uint32 bufsz) const;
209 int validate() const;
210
211 private:
212 friend class Iter;
213 friend class DataC;
214 friend class Data;
215 friend class BoundC;
216 // undefined
217 Spec(const Spec&);
218 Spec& operator=(const Spec&);
219 Type* m_buf;
220 Uint16 m_bufMaxCnt;
221 Uint16 m_cnt;
222 Uint16 m_nullableCnt;
223 Uint16 m_varsizeCnt;
224 Uint32 m_maxByteSize; // excludes null mask
225 };
226
227 /*
228 * Iterator over data items. DataC uses external Iter instances in
229 * comparison methods etc. Data contains an Iter instance which
230 * iterates on items added.
231 */
232 class Iter : public Error {
233 public:
234 // the data instance is only used to set metadata
235 Iter(const DataC& data);
~Iter()236 ~Iter() {}
237 void reset();
238
239 private:
240 friend class DataC;
241 friend class Data;
242 friend class BoundC;
243 // undefined
244 Iter(const Iter&);
245 Iter& operator=(const Iter&);
246 // describe next non-null or null item and advance iterator
247 int desc(const Uint8* item);
248 int desc_null();
249 // compare current items (DataC buffers are passed)
250 int cmp(const Iter& r2, const Uint8* buf1, const Uint8* buf2) const;
251
252 const Spec& m_spec;
253 const bool m_allNullable;
254 // iterator
255 Uint32 m_itemPos; // position of current item in DataC buffer
256 Uint32 m_cnt; // number of items described so far
257 Uint32 m_nullCnt;
258 // current item
259 Uint32 m_lenBytes; // 0-2
260 Uint32 m_bareLen; // excludes length bytes
261 Uint32 m_itemLen; // full length, value zero means null
262 };
263
264 /*
265 * Read-only superclass of Data. Initialized from a previously
266 * constructed Data buffer (any var bytes skipped). Methods interpret
267 * one data item at a time. Values are native endian.
268 */
269 class DataC : public Error {
270 public:
271 DataC(const Spec& spec, bool allNullable);
272 // set buffer to previously constructed one with given item count
273 void set_buf(const void* buf, Uint32 bufMaxLen, Uint32 cnt);
274 // interpret next data item
275 int desc(Iter& r) const;
276 // compare cnt attrs and also return number of initial equal attrs
277 int cmp(const DataC& d2, Uint32 cnt, Uint32& num_eq) const;
278 // getters
279 const Spec& get_spec() const;
280 bool get_all_nullable() const;
281 const void* get_data_buf() const;
282 Uint32 get_cnt() const;
283 bool is_empty() const;
284 bool is_full() const;
285 // print
286 friend NdbOut& operator<<(NdbOut&, const DataC&);
287 void print(NdbOut& out) const;
288 const char* print(char* buf, Uint32 bufsz, bool convert_flag = false) const;
validate() const289 int validate() const { return 0; }
290
291 private:
292 friend class Iter;
293 friend class Data;
294 friend class BoundC;
295 // undefined
296 DataC(const Data&);
297 DataC& operator=(const DataC&);
298 const Spec& m_spec;
299 const bool m_allNullable;
300 const Uint8* m_buf;
301 Uint32 m_bufMaxLen;
302 // can be updated as part of Data instance
303 Uint32 m_cnt;
304 };
305
306 /*
307 * Instance of an array of data values. The values are packed into
308 * a byte buffer. The buffer is also maintained as a single varbinary
309 * value if non-zero var bytes (length bytes) is specified.
310 *
311 * Data instances can be received from another source (such as table
312 * in database) and may not be native-endian. Such instances must
313 * first be completed with desc_all() and convert().
314 */
315 class Data : public DataC {
316 public:
317 Data(const Spec& spec, bool allNullable, Uint32 varBytes);
318 // set buffer (calls reset)
319 void set_buf(void* buf, Uint32 bufMaxLen);
320 // reset but keep buffer (header is zeroed)
321 void reset();
322 // add non-null data items and return length in bytes
323 int add(const void* data, Uint32* len_out);
324 int add(const void* data, Uint32 cnt, Uint32* len_out);
325 // add null data items and return length 0 bytes
326 int add_null(Uint32* len_out);
327 int add_null(Uint32 cnt, Uint32* len_out);
328 // add from "plain old attr info"
329 int add_poai(const Uint32* poai, Uint32* len_out);
330 int add_poai(const Uint32* poai, Uint32 cnt, Uint32* len_out);
331 // call this before first use
332 int finalize();
333 // copy from
334 int copy(const DataC& d2);
335 // convert endian
336 int convert(Endian::Value to_endian);
337 // create complete instance from buffer contents
338 int desc_all(Uint32 cnt, Endian::Value from_endian);
339 // getters
340 Uint32 get_max_len() const;
341 Uint32 get_max_len4() const;
342 Uint32 get_var_bytes() const;
343 const void* get_full_buf() const;
344 Uint32 get_full_len() const;
345 Uint32 get_data_len() const;
346 Uint32 get_null_cnt() const;
347 Endian::Value get_endian() const;
348 // print
349 friend NdbOut& operator<<(NdbOut&, const Data&);
350 void print(NdbOut& out) const;
351 const char* print(char* buf, Uint32 bufsz) const;
352 int validate() const;
353
354 private:
355 friend class Iter;
356 friend class Bound;
357 // undefined
358 Data(const Data&);
359 Data& operator=(const Data&);
360 int finalize_impl();
361 int convert_impl(Endian::Value to_endian);
362 const Uint32 m_varBytes;
363 Uint8* m_buf;
364 Uint32 m_bufMaxLen;
365 Endian::Value m_endian;
366 // iterator on items added
367 Iter m_iter;
368 };
369
370 /*
371 * Read-only superclass of BoundC, analogous to DataC. Initialized
372 * from a previously constructed Bound or DataC buffer.
373 */
374 class BoundC : public Error {
375 public:
376 BoundC(DataC& data);
~BoundC()377 ~BoundC() {}
378 // call this before first use
379 int finalize(int side);
380 // compare bound to key (may return 0 if bound is longer)
381 int cmp(const DataC& d2, Uint32 cnt, Uint32& num_eq) const;
382 // compare bounds (may return 0 if cnt is less than min length)
383 int cmp(const BoundC& b2, Uint32 cnt, Uint32& num_eq) const;
384 // getters
385 DataC& get_data() const;
386 int get_side() const;
387 // print
388 friend NdbOut& operator<<(NdbOut&, const BoundC&);
389 void print(NdbOut& out) const;
390 const char* print(char* buf, Uint32 bufsz) const;
391 int validate() const;
392
393 private:
394 friend class Bound;
395 // undefined
396 BoundC(const BoundC&);
397 BoundC& operator=(const BoundC&);
398 DataC& m_data;
399 int m_side;
400 };
401
402 /*
403 * Ordered index range bound consists of a partial key and a "side".
404 * The partial key is a Data instance where some initial number of
405 * values are present. It is defined separately by the caller and
406 * passed to Bound ctor by reference.
407 */
408 class Bound : public BoundC {
409 public:
410 Bound(Data& data);
~Bound()411 ~Bound() {}
412 void reset();
413 // call this before first use
414 int finalize(int side);
415 // getters
416 Data& get_data() const;
417 // print
418 friend NdbOut& operator<<(NdbOut&, const Bound&);
419 void print(NdbOut& out) const;
420 const char* print(char* buf, Uint32 bufsz) const;
421 int validate() const;
422
423 private:
424 // undefined
425 Bound(const Bound&);
426 Bound& operator=(const Bound&);
427 Data& m_data;
428 };
429
430 /*
431 * Helper for print() methods.
432 */
433 struct Print {
434 private:
435 friend class Endian;
436 friend class Type;
437 friend class Spec;
438 friend class Iter;
439 friend class DataC;
440 friend class Data;
441 friend class BoundC;
442 friend class Bound;
443 Print(char* buf, Uint32 bufsz);
444 void print(const char* frm, ...);
445 char* m_buf;
446 Uint32 m_bufsz;
447 Uint32 m_sz;
448 };
449 };
450
451 // NdbPack
452
453 inline const NdbSqlUtil::Type&
getSqlType(Uint32 typeId)454 NdbPack::getSqlType(Uint32 typeId)
455 {
456 return NdbSqlUtil::m_typeList[typeId];
457 }
458
459 // NdbPack::Error
460
461 inline
Error()462 NdbPack::Error::Error()
463 {
464 m_error_code = 0;
465 m_error_line = 0;
466 }
467
468 // NdbPack::Endian
469
470 inline NdbPack::Endian::Value
get_endian()471 NdbPack::Endian::get_endian()
472 {
473 #ifndef WORDS_BIGENDIAN
474 return Little;
475 #else
476 return Big;
477 #endif
478 }
479
480 // NdbPack::Type
481
482 inline
Type()483 NdbPack::Type::Type()
484 {
485 m_typeId = NDB_TYPE_UNDEFINED;
486 m_byteSize = 0;
487 m_nullable = true;
488 m_csNumber = 0;
489 m_arrayType = 0;
490 m_nullbitPos = 0;
491 }
492
493 inline
Type(int typeId,Uint32 byteSize,bool nullable,Uint32 csNumber)494 NdbPack::Type::Type(int typeId, Uint32 byteSize, bool nullable, Uint32 csNumber)
495 {
496 set(typeId, byteSize, nullable, csNumber);
497 }
498
499 inline void
set(Uint32 typeId,Uint32 byteSize,bool nullable,Uint32 csNumber)500 NdbPack::Type::set(Uint32 typeId, Uint32 byteSize, bool nullable, Uint32 csNumber)
501 {
502 m_typeId = typeId;
503 m_byteSize = byteSize;
504 m_nullable = nullable;
505 m_csNumber = csNumber;
506 }
507
508 inline Uint32
get_type_id() const509 NdbPack::Type::get_type_id() const
510 {
511 return m_typeId;
512 }
513
514 inline Uint32
get_byte_size() const515 NdbPack::Type::get_byte_size() const
516 {
517 return m_byteSize;
518 }
519
520 inline bool
get_nullable() const521 NdbPack::Type::get_nullable() const
522 {
523 return (bool)m_nullable;
524 }
525
526 inline Uint32
get_cs_number() const527 NdbPack::Type::get_cs_number() const
528 {
529 return m_csNumber;
530 }
531
532 inline Uint32
get_array_type() const533 NdbPack::Type::get_array_type() const
534 {
535 return m_arrayType;
536 }
537
538 // NdbPack::Spec
539
540 inline
Spec()541 NdbPack::Spec::Spec()
542 {
543 reset();
544 m_buf = 0;
545 m_bufMaxCnt = 0;
546 }
547
548 inline void
set_buf(Type * buf,Uint32 bufMaxCnt)549 NdbPack::Spec::set_buf(Type* buf, Uint32 bufMaxCnt)
550 {
551 reset();
552 m_buf = buf;
553 m_bufMaxCnt = bufMaxCnt;
554 }
555
556 inline void
set_buf(Type * buf)557 NdbPack::Spec::set_buf(Type* buf)
558 {
559 m_buf = buf;
560 }
561
562 inline void
reset()563 NdbPack::Spec::reset()
564 {
565 m_cnt = 0;
566 m_nullableCnt = 0;
567 m_varsizeCnt = 0;
568 m_maxByteSize = 0;
569 }
570
571 inline const NdbPack::Type&
get_type(Uint32 i) const572 NdbPack::Spec::get_type(Uint32 i) const
573 {
574 assert(i < m_cnt);
575 return m_buf[i];
576 }
577
578 inline Uint32
get_cnt() const579 NdbPack::Spec::get_cnt() const
580 {
581 return m_cnt;
582 }
583
584 inline Uint32
get_nullable_cnt(bool allNullable) const585 NdbPack::Spec::get_nullable_cnt(bool allNullable) const
586 {
587 if (!allNullable)
588 return m_nullableCnt;
589 else
590 return m_cnt;
591 }
592
593 inline Uint32
get_nullmask_len(bool allNullable) const594 NdbPack::Spec::get_nullmask_len(bool allNullable) const
595 {
596 return (get_nullable_cnt(allNullable) + 7) / 8;
597 }
598
599 inline Uint32
get_max_data_len(bool allNullable) const600 NdbPack::Spec::get_max_data_len(bool allNullable) const
601 {
602 return get_nullmask_len(allNullable) + m_maxByteSize;
603 }
604
605 inline Uint32
get_min_var_bytes(bool allNullable) const606 NdbPack::Spec::get_min_var_bytes(bool allNullable) const
607 {
608 const Uint32 len = get_max_data_len(allNullable);
609 return (len < 256 ? 1 : 2);
610 }
611
612 // NdbPack::Iter
613
614 inline
Iter(const DataC & data)615 NdbPack::Iter::Iter(const DataC& data) :
616 m_spec(data.m_spec),
617 m_allNullable(data.m_allNullable)
618 {
619 reset();
620 }
621
622 inline void
reset()623 NdbPack::Iter::reset()
624 {
625 m_itemPos = m_spec.get_nullmask_len(m_allNullable);
626 m_cnt = 0;
627 m_nullCnt = 0;
628 m_lenBytes = 0;
629 m_bareLen = 0;
630 m_itemLen = 0;
631 }
632
633 // NdbPack::DataC
634
635 inline
DataC(const Spec & spec,bool allNullable)636 NdbPack::DataC::DataC(const Spec& spec, bool allNullable) :
637 m_spec(spec),
638 m_allNullable(allNullable)
639 {
640 m_buf = 0;
641 m_bufMaxLen = 0;
642 m_cnt = 0;
643 }
644
645 inline void
set_buf(const void * buf,Uint32 bufMaxLen,Uint32 cnt)646 NdbPack::DataC::set_buf(const void* buf, Uint32 bufMaxLen, Uint32 cnt)
647 {
648 m_buf = static_cast<const Uint8*>(buf);
649 m_bufMaxLen = bufMaxLen;
650 m_cnt = cnt;
651 }
652
653 inline const NdbPack::Spec&
get_spec() const654 NdbPack::DataC::get_spec() const
655 {
656 return m_spec;
657 }
658
659 inline bool
get_all_nullable() const660 NdbPack::DataC::get_all_nullable() const
661 {
662 return &m_allNullable;
663 }
664
665 inline const void*
get_data_buf() const666 NdbPack::DataC::get_data_buf() const
667 {
668 return &m_buf[0];
669 }
670
671 inline Uint32
get_cnt() const672 NdbPack::DataC::get_cnt() const
673 {
674 return m_cnt;
675 }
676
677 inline bool
is_empty() const678 NdbPack::DataC::is_empty() const
679 {
680 return m_cnt == 0;
681 }
682
683 inline bool
is_full() const684 NdbPack::DataC::is_full() const
685 {
686 return m_cnt == m_spec.m_cnt;
687 }
688
689 // NdbPack::Data
690
691 inline
Data(const Spec & spec,bool allNullable,Uint32 varBytes)692 NdbPack::Data::Data(const Spec& spec, bool allNullable, Uint32 varBytes) :
693 DataC(spec, allNullable),
694 m_varBytes(varBytes),
695 m_iter(*this)
696 {
697 m_buf = 0;
698 m_bufMaxLen = 0;
699 m_endian = Endian::get_endian();
700 }
701
702 inline void
set_buf(void * buf,Uint32 bufMaxLen)703 NdbPack::Data::set_buf(void* buf, Uint32 bufMaxLen)
704 {
705 m_buf = static_cast<Uint8*>(buf);
706 m_bufMaxLen = bufMaxLen;
707 reset();
708 assert(bufMaxLen >= m_varBytes);
709 DataC::set_buf(&m_buf[m_varBytes], m_bufMaxLen - m_varBytes, 0);
710 }
711
712 inline void
reset()713 NdbPack::Data::reset()
714 {
715 m_cnt = 0; // in DataC
716 const Uint32 bytes = m_varBytes + m_spec.get_nullmask_len(m_allNullable);
717 memset(m_buf, 0, bytes);
718 m_endian = Endian::get_endian();
719 m_iter.reset();
720 }
721
722 inline int
finalize()723 NdbPack::Data::finalize()
724 {
725 if (m_varBytes == 0 ||
726 finalize_impl() == 0)
727 return 0;
728 return -1;
729 }
730
731 inline int
convert(Endian::Value to_endian)732 NdbPack::Data::convert(Endian::Value to_endian)
733 {
734 if (to_endian == Endian::Native)
735 to_endian = Endian::get_endian();
736 if (m_endian == to_endian)
737 return 0;
738 if (convert_impl(to_endian) == 0)
739 {
740 m_endian = to_endian;
741 return 0;
742 }
743 return -1;
744 }
745
746 inline Uint32
get_max_len() const747 NdbPack::Data::get_max_len() const
748 {
749 return m_varBytes + m_spec.get_max_data_len(m_allNullable);
750 }
751
752 inline Uint32
get_max_len4() const753 NdbPack::Data::get_max_len4() const
754 {
755 Uint32 len4 = get_max_len();
756 len4 += 3;
757 len4 /= 4;
758 len4 *= 4;
759 return len4;
760 }
761
762 inline Uint32
get_var_bytes() const763 NdbPack::Data::get_var_bytes() const
764 {
765 return m_varBytes;
766 }
767
768 inline const void*
get_full_buf() const769 NdbPack::Data::get_full_buf() const
770 {
771 return &m_buf[0];
772 }
773
774 inline Uint32
get_full_len() const775 NdbPack::Data::get_full_len() const
776 {
777 return m_varBytes + m_iter.m_itemPos + m_iter.m_itemLen;
778 }
779
780 inline Uint32
get_data_len() const781 NdbPack::Data::get_data_len() const
782 {
783 return m_iter.m_itemPos + m_iter.m_itemLen;
784 }
785
786 inline Uint32
get_null_cnt() const787 NdbPack::Data::get_null_cnt() const
788 {
789 return m_iter.m_nullCnt;
790 }
791
792 inline NdbPack::Endian::Value
get_endian() const793 NdbPack::Data::get_endian() const
794 {
795 return m_endian;
796 }
797
798 // NdbPack::BoundC
799
800 inline
BoundC(DataC & data)801 NdbPack::BoundC::BoundC(DataC& data) :
802 m_data(data)
803 {
804 m_side = 0;
805 }
806
807 inline int
cmp(const DataC & d2,Uint32 cnt,Uint32 & num_eq) const808 NdbPack::BoundC::cmp(const DataC& d2, Uint32 cnt, Uint32& num_eq) const
809 {
810 const BoundC& b1 = *this;
811 const DataC& d1 = b1.m_data;
812 int res = d1.cmp(d2, cnt, num_eq);
813 if (res == 0 && d1.m_cnt <= d2.m_cnt)
814 res = b1.m_side;
815 return res;
816 }
817
818 inline NdbPack::DataC&
get_data() const819 NdbPack::BoundC::get_data() const
820 {
821 return m_data;
822 }
823
824 inline int
get_side() const825 NdbPack::BoundC::get_side() const
826 {
827 return m_side;
828 }
829
830 // NdbPack::Bound
831
832 inline
Bound(Data & data)833 NdbPack::Bound::Bound(Data& data) :
834 BoundC(data),
835 m_data(data)
836 {
837 }
838
839 inline void
reset()840 NdbPack::Bound::reset()
841 {
842 m_data.reset();
843 m_side = 0;
844 }
845
846 inline int
finalize(int side)847 NdbPack::Bound::finalize(int side)
848 {
849 if (m_data.finalize() == -1)
850 {
851 set_error(m_data);
852 return -1;
853 }
854 if (BoundC::finalize(side) == -1)
855 return -1;
856 return 0;
857 }
858
859 inline NdbPack::Data&
get_data() const860 NdbPack::Bound::get_data() const
861 {
862 return m_data;
863 }
864
865 #endif // NDB_PACK_HPP
866