MySQL Connector/C++ 9.3.0
MySQL connector library for C and C++ applications
All Classes Files Functions Variables Typedefs Enumerations Enumerator Modules Pages
document.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2015, 2024, Oracle and/or its affiliates.
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, as
6 * published by the Free Software Foundation.
7 *
8 * This program is designed to work with certain software (including
9 * but not limited to OpenSSL) that is licensed under separate terms, as
10 * 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 either included with
14 * the program or referenced in the documentation.
15 *
16 * Without limiting anything contained in the foregoing, this file,
17 * which is part of Connector/C++, is also subject to the
18 * Universal FOSS Exception, version 1.0, a copy of which can be found at
19 * https://oss.oracle.com/licenses/universal-foss-exception.
20 *
21 * This program is distributed in the hope that it will be useful, but
22 * WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
24 * See the GNU General Public License, version 2.0, for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software Foundation, Inc.,
28 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
29 */
30
31#ifndef MYSQLX_DOCUMENT_H
32#define MYSQLX_DOCUMENT_H
33
39#include "common.h"
40
41#include <memory>
42#include <stdint.h>
43#include <limits>
44#include <vector>
45#include <assert.h>
46
47#undef min
48#undef max
49
50
51namespace mysqlx {
52MYSQLX_ABI_BEGIN(2,0)
53
54class Value;
55class DbDoc;
56class DocResult;
57class SessionSettings;
58
59namespace internal{
60class Schema_detail;
61
62} //internal
63
64using Field = std::string;
65
66
67// Document class
68// ==============
69
70
81class PUBLIC_API DbDoc
82 : public common::Printable
83{
84 // TODO: move PUBLIC_API stuff to a detail class
85
86 class INTERNAL Impl;
87
88DLL_WARNINGS_PUSH
89
90 std::shared_ptr<Impl> m_impl;
91
92DLL_WARNINGS_POP
93
94 INTERNAL DbDoc(const std::shared_ptr<Impl>&);
95
96 const char* get_json() const;
97
98public:
99
107 DbDoc() {}
108
113 explicit DbDoc(const std::string&);
114 explicit DbDoc(std::string&&);
115
116
121 bool isNull() const { return NULL == m_impl.get(); }
122 operator bool() const { return !isNull(); }
123
124
129 virtual bool hasField(const Field&) const;
130
131
137 virtual int fieldType(const Field&) const;
138
143 virtual const Value& operator[](const Field&) const;
144
145 const Value& operator[](const char *name) const
146 {
147 return this->operator[](Field(name));
148 }
149
150 const Value& operator[](const mysqlx::string &name) const
151 {
152 return this->operator[](Field(name));
153 }
154
155
160 virtual void print(std::ostream&) const;
161
170 class Iterator;
171
172 virtual Iterator begin();
173 virtual Iterator end();
174
175 friend Impl;
176 friend DocResult;
177 friend Value;
179 friend internal::Schema_detail;
181};
182
183
184class PUBLIC_API DbDoc::Iterator
185{
186 DLL_WARNINGS_PUSH
187 std::shared_ptr<DbDoc::Impl> m_impl;
188 DLL_WARNINGS_POP
189 bool m_end;
190
191public:
192
193 Iterator& operator++();
194 bool operator==(const Iterator&) const;
195 bool operator!=(const Iterator &other) const { return !(*this == other); }
196 const Field& operator*();
197
198 friend DbDoc;
199};
200
201
202// Value class
203// ===========
204
227class Value
228 : public virtual common::Printable
229 , protected common::Value
230{
231public:
232
233 using string = mysqlx::string;
234
241 enum Type
242 {
253 };
254
255 typedef std::vector<Value>::iterator iterator;
256 typedef std::vector<Value>::const_iterator const_iterator;
257
260
261 Value();
262 Value(std::nullptr_t);
263
264 Value(const mysqlx::string &str);
265 Value(mysqlx::string &&str);
266 //Value(const char16_t *str) : Value(mysqlx::string(str)) {}
267
268 Value(const std::string &str);
269 Value(std::string &&str);
270 Value(const char *str) : Value(std::string(str)) {}
271
272 template <typename C>
273 Value(const std::basic_string<C> &str)
274 : Value(mysqlx::string(str))
275 {}
276
277 template <typename C>
278 Value(const C *str)
279 : Value(mysqlx::string(str))
280 {}
281
282 Value(const bytes&);
283 Value(int64_t);
284 Value(uint64_t);
285 Value(float);
286 Value(double);
287 Value(bool);
288 Value(const DbDoc& doc);
289
290 Value(const std::initializer_list<Value> &list);
291 template <typename Iterator>
292 Value(Iterator begin_, Iterator end_);
293
295
296 Value(common::Value &&other);
297 Value(const common::Value &other);
298
299 Value(const Value&) = default;
300
301#ifdef HAVE_MOVE_CTORS
302
303 Value(Value&&) = default;
304
305#else
306
307 // Note move ctor implemented using move assignment defined below.
308
309 Value(Value &&other)
310 {
311 *this = std::move(other);
312 }
313
314#endif
315
316 /*
317 Note: These templates are needed to disambiguate constructor resolution
318 for integer types.
319 */
320
321 template <
322 typename T,
323 typename std::enable_if<std::is_signed<T>::value>::type* = nullptr
324 >
325 Value(T x)
326 : Value(static_cast<int64_t>(x))
327 {}
328
329 template <
330 typename T,
331 typename std::enable_if<std::is_unsigned<T>::value>::type* = nullptr
332 >
333 Value(T x)
334 : Value(static_cast<uint64_t>(x))
335 {}
336
337
338 Value& operator=(const Value&) = default;
339
340 /*
341 Note: Move assignment is defined explicitly to avoid problems with
342 virtual Printable base.
343 */
344
345 Value& operator=(Value&&);
346
347 /*
348 Assignment is implemented in terms of constructors: first an instance
349 is created from the input data and then move assignment is used to place
350 the result into this instance.
351 */
352
353 template<typename T>
354 Value& operator=(T&& x)
355 {
356 try {
357 *this = Value(std::forward<T>(x));
358 return *this;
359 }
360 CATCH_AND_WRAP
361 }
362
363 virtual ~Value() {}
364
365public:
366
373
374 operator int() const;
375 operator unsigned() const;
376 operator int64_t() const;
377 operator uint64_t() const;
378
379 operator float() const;
380 operator double() const;
381
382 explicit operator bool() const;
383
384 operator mysqlx::string() const;
385 explicit operator std::string() const;
386
387 template <typename C>
388 explicit operator std::basic_string<C>() const
389 {
390 return this->operator mysqlx::string();
391 }
392
393 explicit operator bytes() const;
394 operator DbDoc() const;
395
396
397 template<typename T>
398 T get() const;
399
401
402
404 {
405 try {
406 size_t len;
407 const byte *ptr = get_bytes(&len);
408 return { ptr, len };
409 }
410 CATCH_AND_WRAP
411 }
412
413
419 Type getType() const;
420
422
423 bool isNull() const
424 {
425 return VNULL == getType();
426 }
427
433 bool hasField(const Field&) const;
434
440 const Value& operator[](const Field&) const;
441
442 const Value& operator[](const char *name) const
443 { return (*this)[Field(name)]; }
444
445 const Value& operator[](const mysqlx::string &name) const
446 { return (*this)[Field(name)]; }
447
448
455
456 iterator begin();
457 const_iterator begin() const;
458 iterator end();
459 const_iterator end() const;
460 size_t elementCount() const;
461
462 const Value& operator[](unsigned) const;
463 const Value& operator[](int pos) const
464 {
465 assert(pos >= 0);
466 return operator[]((unsigned)pos);
467 }
468
470
471
473
474 void print(std::ostream &out) const
475 {
476 switch (m_type)
477 {
478 case DOC: out << m_doc; return;
479 case ARR:
480 {
481 bool first = true;
482 out << "[";
483 for (auto it = m_arr->begin();it!=m_arr->end();++it)
484 {
485 if (!first)
486 {
487 out << ", ";
488 }
489 else
490 {
491 first = false;
492 }
493
494 switch (it->get_type())
495 {
496 case common::Value::STRING:
497 case common::Value::USTRING:
498 case common::Value::EXPR:
499 out << R"(")" << *it << R"(")";
500 break;
501 default:
502 out << *it;
503 break;
504 }
505
506
507 }
508 out << "]";
509 return;
510 }
511 default: common::Value::print(out); return;
512 }
513 }
514
515protected:
516
517 enum { VAL, ARR, DOC } m_type = VAL;
518
519 void check_type(Type t) const
520 {
521 if (getType() != t)
522 throw Error("Invalid value type");
523 }
524
525 bool is_expr() const
526 {
527 return VAL == m_type && common::Value::EXPR == common::Value::get_type();
528 }
529
531 {
532 common::Value::m_type = common::Value::EXPR;
533 }
534
535 /*
536 TODO: Instead extend common::Value with array and document types. Requires
537 moving DbDoc code to the common layer.
538 */
539
540 typedef std::vector<Value> Array;
541
542 DLL_WARNINGS_PUSH
543
545
546 // Note: shared with other Value instances for the same array.
547 std::shared_ptr<Array> m_arr;
548
549 DLL_WARNINGS_POP
550
551public:
552
554 friend DbDoc;
555
557 friend mysqlx::string;
559
560 struct INTERNAL Access;
561 friend Access;
562};
563
564static const Value nullvalue;
565
566
567inline
568Value& Value::operator=(Value &&other)
569{
570 m_type = other.m_type;
571
572 switch (m_type)
573 {
574 case VAL:
575 common::Value::operator=(std::move(other));
576 break;
577
578 case DOC: m_doc = std::move(other.m_doc); break;
579 case ARR: m_arr = std::move(other.m_arr); break;
580
581 default: break;
582 }
583
584 return *this;
585}
586
587
588namespace internal {
589
590/*
591 Helper class to identify usage of expressions
592*/
593
594class Expression
595 : public mysqlx::Value
596{
597 Expression()
598 {}
599
600 template <typename V>
601 Expression(V&& val)
602 : Value(std::forward<V>(val))
603 {
604 set_as_expr();
605 }
606
607 template <typename V>
608 Expression(const V& val)
609 : Value(val)
610 {
611 set_as_expr();
612 }
613
614 friend Expression expr(std::string&& s);
615 friend Expression expr(const std::string& s);
616};
617
618
638inline
639internal::Expression expr(std::string&& e)
640{
641 return std::forward<std::string>(e);
642}
643
644inline
645internal::Expression expr(const std::string& e)
646{
647 return e;
648}
649
650} // internal
651
652
653using internal::expr;
654
655
656inline
657Value::Type Value::getType() const
658{
659 switch (m_type)
660 {
661 case ARR: return ARRAY;
662 case DOC: return DOCUMENT;
663 case VAL:
664 switch (common::Value::get_type())
665 {
666 case common::Value::VNULL: return VNULL;
667 case common::Value::UINT64: return UINT64;
668 case common::Value::INT64: return INT64;
669 case common::Value::FLOAT: return FLOAT;
670 case common::Value::DOUBLE: return DOUBLE;
671 case common::Value::BOOL: return BOOL;
672 case common::Value::STRING: return STRING;
673 case common::Value::USTRING: return STRING;
674 case common::Value::RAW: return RAW;
675 case common::Value::EXPR: return STRING;
676 case common::Value::JSON: return DOCUMENT;
677 }
678 }
679 return VNULL; // quiet compiler warning
680}
681
682
683/*
684 Value type conversions
685 ----------------------
686 TODO: more informative errors
687*/
688
689
690inline
691Value::Value(const std::initializer_list<Value> &list)
692 : m_type(ARR)
693{
694 try {
695 m_arr = std::make_shared<Array>(list);
696 }
697 CATCH_AND_WRAP
698}
699
700template <typename Iterator>
701inline
702Value::Value(Iterator begin_, Iterator end_)
703 : m_type(ARR)
704{
705 try {
706 m_arr = std::make_shared<Array>(begin_, end_);
707 }
708 CATCH_AND_WRAP
709}
710
711
712inline
713Value::Value(common::Value &&other)
714try
715 : common::Value(std::move(other))
716{}
717CATCH_AND_WRAP
718
719inline
720Value::Value(const common::Value &other)
721try
722 : common::Value(other)
723{}
724CATCH_AND_WRAP
725
726
728{}
729
730inline Value::Value(std::nullptr_t)
731{}
732
733inline Value::Value(int64_t val)
734try
735 : common::Value(val)
736{}
737CATCH_AND_WRAP
738
739inline Value::Value(uint64_t val)
740try
741 : common::Value(val)
742{}
743CATCH_AND_WRAP
744
745template <>
746PUBLIC_API common::Value Value::get<common::Value>() const;
747
748template<>
749inline
750int Value::get<int>() const
751{
752 try {
753 int64_t val = get_sint();
754 if (val > std::numeric_limits<int>::max())
755 throw Error("Numeric conversion overflow");
756 if (val < std::numeric_limits<int>::min())
757 throw Error("Numeric conversion overflow");
758
759 return (int)val;
760 }
761 CATCH_AND_WRAP
762}
763
764inline
765Value::operator int() const
766{
767 return get<int>();
768}
769
770
771template<>
772inline unsigned Value::get<unsigned>() const
773{
774 try {
775 uint64_t val = get_uint();
776 if (val > std::numeric_limits<unsigned>::max())
777 throw Error("Numeric conversion overflow");
778
779 return (unsigned)val;
780 }
781 CATCH_AND_WRAP
782}
783
784inline
785Value::operator unsigned() const
786{
787 return get<unsigned>();
788}
789
790
791template<>
792inline int64_t Value::get<int64_t>() const
793{
794 try {
795 return get_sint();
796 }
797 CATCH_AND_WRAP
798}
799
800inline
801Value::operator int64_t() const
802{
803 return get<int64_t>();
804}
805
806
807template<>
808inline uint64_t Value::get<uint64_t>() const
809{
810 try {
811 return get_uint();
812 }
813 CATCH_AND_WRAP
814}
815
816inline
817Value::operator uint64_t() const
818{
819 return get<uint64_t>();
820}
821
822
823inline Value::Value(float val)
824try
825 : common::Value(val)
826{}
827CATCH_AND_WRAP
828
829template<>
830inline
831float Value::get<float>() const
832{
833 try {
834 return get_float();
835 }
836 CATCH_AND_WRAP
837}
838
839inline
840Value::operator float() const
841{
842 return get<float>();
843}
844
845
846inline Value::Value(double val)
847try
848 : common::Value(val)
849{}
850CATCH_AND_WRAP
851
852template<>
853inline
854double Value::get<double>() const
855{
856 try {
857 return get_double();
858 }
859 CATCH_AND_WRAP
860}
861
862inline
863Value::operator double() const
864{
865 return get<double>();
866}
867
868
869inline Value::Value(bool val)
870try
871 : common::Value(val)
872{}
873CATCH_AND_WRAP
874
875
876template<>
877inline
878bool Value::get<bool>() const
879{
880 try {
881 return get_bool();
882 }
883 CATCH_AND_WRAP
884}
885
886inline
887Value::operator bool() const
888{
889 return get<bool>();
890}
891
892
893inline Value::Value(const DbDoc &doc)
894try
895 : m_type(DOC)
896 , m_doc(doc)
897{}
898CATCH_AND_WRAP
899
900
901
902inline Value::Value(const mysqlx::string &val)
903try
904 : common::Value(val)
905{}
906CATCH_AND_WRAP
907
909try
910 : common::Value(std::move(val))
911{}
912CATCH_AND_WRAP
913
914
915inline Value::Value(const std::string &val)
916try
917 : common::Value(val)
918{}
919CATCH_AND_WRAP
920
921inline Value::Value(std::string &&val)
922try
923 : common::Value(std::move(val))
924{}
925CATCH_AND_WRAP
926
927
928template<>
929inline
930std::wstring Value::get<std::wstring>() const
931{
932 try {
933 return mysqlx::string(this->get_ustring());
934 }
935 CATCH_AND_WRAP
936}
937
938
939template<>
940inline
941std::string Value::get<std::string>() const
942{
943 try {
944 return get_string();
945 }
946 CATCH_AND_WRAP
947}
948
949inline
950Value::operator std::string() const
951{
952 return get<std::string>();
953}
954
955
956template<>
957inline
958mysqlx::string Value::get<mysqlx::string>() const
959{
960 try {
961 return this->get_ustring();
962 }
963 CATCH_AND_WRAP
964}
965
966inline
967Value::operator mysqlx::string() const
968{
969 return get<mysqlx::string>();
970}
971
972
973inline Value::Value(const bytes &data)
974try
975 : common::Value(data.begin(), data.length())
976{}
977CATCH_AND_WRAP
978
979template<>
980inline
981bytes Value::get<bytes>() const
982{
983 return getRawBytes();
984}
985
986inline
987Value::operator bytes() const
988{
989 return get<bytes>();
990}
991
992
993template<>
994inline
995DbDoc Value::get<DbDoc>() const
996{
998 return m_doc;
999}
1000
1001inline
1002Value::operator DbDoc() const
1003{
1004 return get<DbDoc>();
1005}
1006
1007
1008inline
1009bool Value::hasField(const Field &fld) const
1010{
1012 return m_doc.hasField(fld);
1013}
1014
1015inline
1016const Value& Value::operator[](const Field &fld) const
1017{
1019 return m_doc[fld];
1020}
1021
1022inline
1023int DbDoc::fieldType(const Field &fld) const
1024{
1025 return (*this)[fld].getType();
1026}
1027
1028// Array access
1029
1030
1031inline
1032Value::iterator Value::begin()
1033{
1034 if (ARR != m_type)
1035 throw Error("Attempt to iterate over non-array value");
1036 return m_arr->begin();
1037}
1038
1039inline
1040Value::const_iterator Value::begin() const
1041{
1042 if (ARR != m_type)
1043 throw Error("Attempt to iterate over non-array value");
1044 return m_arr->begin();
1045}
1046
1047inline
1048Value::iterator Value::end()
1049{
1050 if (ARR != m_type)
1051 throw Error("Attempt to iterate over non-array value");
1052 return m_arr->end();
1053}
1054
1055inline
1056Value::const_iterator Value::end() const
1057{
1058 if (ARR != m_type)
1059 throw Error("Attempt to iterate over non-array value");
1060 return m_arr->end();
1061}
1062
1063inline
1064const Value& Value::operator[](unsigned pos) const
1065{
1067 return m_arr->at(pos);
1068}
1069
1070inline
1072{
1074 return m_arr->size();
1075}
1076
1077
1078MYSQLX_ABI_END(2,0)
1079} // mysqlx
1080
1081
1082#endif
Represents a collection of key-value pairs where value can be a scalar or another document.
Definition: document.h:83
virtual void print(std::ostream &) const
Print JSON description of the document.
virtual bool hasField(const Field &) const
Check if named field is a top-level field in the document.
DbDoc()
Create null document instance.
Definition: document.h:107
DbDoc(const std::string &)
Creates DbDoc instance out of given JSON string description.
virtual int fieldType(const Field &) const
Return Value::XXX constant that identifies type of value stored at given field.
Definition: document.h:1023
virtual const Value & operator[](const Field &) const
Return value of given field.
bool isNull() const
Check if document is null.
Definition: document.h:121
Result of an operation that returns documents.
Definition: result.h:818
Base class for connector errors.
Definition: common.h:84
Value object can store value of scalar type, string, array or document.
Definition: document.h:230
bytes getRawBytes() const
Return type of the value stored in this instance (or VNULL if no value is stored).
Definition: document.h:403
const Value & operator[](const char *name) const
Return type of the value stored in this instance (or VNULL if no value is stored).
Definition: document.h:442
void check_type(Type t) const
Return type of the value stored in this instance (or VNULL if no value is stored).
Definition: document.h:519
Type getType() const
Return type of the value stored in this instance (or VNULL if no value is stored).
Definition: document.h:657
Type
Possible types of values.
Definition: document.h:242
@ DOCUMENT
Document.
Definition: document.h:250
@ ARRAY
Array of values.
Definition: document.h:252
@ DOUBLE
Double number.
Definition: document.h:247
@ INT64
Signed integer.
Definition: document.h:245
@ FLOAT
Float number.
Definition: document.h:246
@ UINT64
Unsigned integer.
Definition: document.h:244
@ VNULL
Null value.
Definition: document.h:243
@ RAW
Raw bytes.
Definition: document.h:251
@ BOOL
Boolean.
Definition: document.h:248
@ STRING
String.
Definition: document.h:249
bool hasField(const Field &) const
Check if document value contains given (top-level) field.
Definition: document.h:1009
friend DbDoc
Return type of the value stored in this instance (or VNULL if no value is stored).
Definition: document.h:554
iterator begin()
Access to elements of an array value.
Definition: document.h:1032
enum mysqlx::abi2::r0::Value::@1 m_type
Return type of the value stored in this instance (or VNULL if no value is stored).
bool is_expr() const
Return type of the value stored in this instance (or VNULL if no value is stored).
Definition: document.h:525
DbDoc m_doc
Return type of the value stored in this instance (or VNULL if no value is stored).
Definition: document.h:544
const Value & operator[](const Field &) const
If this value is not a document, throws error.
Definition: document.h:1016
iterator end()
Return type of the value stored in this instance (or VNULL if no value is stored).
Definition: document.h:1048
friend Access
Return type of the value stored in this instance (or VNULL if no value is stored).
Definition: document.h:560
Value(const std::basic_string< C > &str)
Constructs Null value.
Definition: document.h:273
const Value & operator[](const mysqlx::string &name) const
Return type of the value stored in this instance (or VNULL if no value is stored).
Definition: document.h:445
std::shared_ptr< Array > m_arr
Return type of the value stored in this instance (or VNULL if no value is stored).
Definition: document.h:547
bool isNull() const
Convenience method for checking if value is null.
Definition: document.h:423
Value()
Constructs Null value.
Definition: document.h:727
std::vector< Value > Array
Return type of the value stored in this instance (or VNULL if no value is stored).
Definition: document.h:540
Value(const char *str)
Constructs Null value.
Definition: document.h:270
friend SessionSettings
Return type of the value stored in this instance (or VNULL if no value is stored).
Definition: document.h:553
void print(std::ostream &out) const
Print the value to a stream.
Definition: document.h:474
Value(const C *str)
Constructs Null value.
Definition: document.h:278
const Value & operator[](int pos) const
Return type of the value stored in this instance (or VNULL if no value is stored).
Definition: document.h:463
size_t elementCount() const
Return type of the value stored in this instance (or VNULL if no value is stored).
Definition: document.h:1071
void set_as_expr()
Return type of the value stored in this instance (or VNULL if no value is stored).
Definition: document.h:530
T get() const
Return type of the value stored in this instance (or VNULL if no value is stored).
Class representing a region of memory holding raw bytes.
Definition: common.h:298
A wrapper around std::wstring that can perform conversions from/to different character encodings used...
Definition: common.h:114
Type
Types that can be reported in result meta-data.
Definition: result.h:241
internal::Expression expr(std::string &&e)
Function which indicates that a given string should be treated as expression.
Definition: document.h:639