MySQL Connector/C++
MySQL connector library for C and C++ applications
document.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2015, 2023, 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 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
12 * additional permission to link the program and your derivative works
13 * with the separately licensed software that they have included with
14 * MySQL.
15 *
16 * Without limiting anything contained in the foregoing, this file,
17 * which is part of MySQL Connector/C++, is also subject to the
18 * Universal FOSS Exception, version 1.0, a copy of which can be found at
19 * http://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;
178 friend internal::Schema_detail;
179};
180
181
182class PUBLIC_API DbDoc::Iterator
183{
184 DLL_WARNINGS_PUSH
185 std::shared_ptr<DbDoc::Impl> m_impl;
186 DLL_WARNINGS_POP
187 bool m_end;
188
189public:
190
191 Iterator& operator++();
192 bool operator==(const Iterator&) const;
193 bool operator!=(const Iterator &other) const { return !(*this == other); }
194 const Field& operator*();
195
196 friend DbDoc;
197};
198
199
200// Value class
201// ===========
202
225class Value
226 : public virtual common::Printable
227 , protected common::Value
228{
229public:
230
231 using string = mysqlx::string;
232
239 enum Type
240 {
251 };
252
253 typedef std::vector<Value>::iterator iterator;
254 typedef std::vector<Value>::const_iterator const_iterator;
255
258
259 Value();
260 Value(std::nullptr_t);
261
262 Value(const mysqlx::string &str);
263 Value(mysqlx::string &&str);
264 //Value(const char16_t *str) : Value(mysqlx::string(str)) {}
265
266 Value(const std::string &str);
267 Value(std::string &&str);
268 Value(const char *str) : Value(std::string(str)) {}
269
270 template <typename C>
271 Value(const std::basic_string<C> &str)
272 : Value(mysqlx::string(str))
273 {}
274
275 template <typename C>
276 Value(const C *str)
277 : Value(mysqlx::string(str))
278 {}
279
280 Value(const bytes&);
281 Value(int64_t);
282 Value(uint64_t);
283 Value(float);
284 Value(double);
285 Value(bool);
286 Value(const DbDoc& doc);
287
288 Value(const std::initializer_list<Value> &list);
289 template <typename Iterator>
290 Value(Iterator begin_, Iterator end_);
291
293
294 Value(common::Value &&other);
295 Value(const common::Value &other);
296
297 Value(const Value&) = default;
298
299#ifdef HAVE_MOVE_CTORS
300
301 Value(Value&&) = default;
302
303#else
304
305 // Note move ctor implemented using move assignment defined below.
306
307 Value(Value &&other)
308 {
309 *this = std::move(other);
310 }
311
312#endif
313
314 /*
315 Note: These templates are needed to disambiguate constructor resolution
316 for integer types.
317 */
318
319 template <
320 typename T,
321 typename std::enable_if<std::is_signed<T>::value>::type* = nullptr
322 >
323 Value(T x)
324 : Value(static_cast<int64_t>(x))
325 {}
326
327 template <
328 typename T,
329 typename std::enable_if<std::is_unsigned<T>::value>::type* = nullptr
330 >
331 Value(T x)
332 : Value(static_cast<uint64_t>(x))
333 {}
334
335
336 Value& operator=(const Value&) = default;
337
338 /*
339 Note: Move assignment is defined explicitly to avoid problems with
340 virtual Printable base.
341 */
342
343 Value& operator=(Value&&);
344
345 /*
346 Assignment is implemented in terms of constructors: first an instance
347 is created from the input data and then move assignment is used to place
348 the result into this instance.
349 */
350
351 template<typename T>
352 Value& operator=(T&& x)
353 {
354 try {
355 *this = Value(std::forward<T>(x));
356 return *this;
357 }
358 CATCH_AND_WRAP
359 }
360
361
362public:
363
370
371 operator int() const;
372 operator unsigned() const;
373 operator int64_t() const;
374 operator uint64_t() const;
375
376 operator float() const;
377 operator double() const;
378
379 explicit operator bool() const;
380
381 operator mysqlx::string() const;
382 explicit operator std::string() const;
383
384 template <typename C>
385 explicit operator std::basic_string<C>() const
386 {
387 return this->operator mysqlx::string();
388 }
389
390 explicit operator bytes() const;
391 operator DbDoc() const;
392
393
394 template<typename T>
395 T get() const;
396
398
399
401 {
402 try {
403 size_t len;
404 const byte *ptr = get_bytes(&len);
405 return { ptr, len };
406 }
407 CATCH_AND_WRAP
408 }
409
410
416 Type getType() const;
417
419
420 bool isNull() const
421 {
422 return VNULL == getType();
423 }
424
430 bool hasField(const Field&) const;
431
437 const Value& operator[](const Field&) const;
438
439 const Value& operator[](const char *name) const
440 { return (*this)[Field(name)]; }
441
442 const Value& operator[](const mysqlx::string &name) const
443 { return (*this)[Field(name)]; }
444
445
452
453 iterator begin();
454 const_iterator begin() const;
455 iterator end();
456 const_iterator end() const;
457 size_t elementCount() const;
458
459 const Value& operator[](unsigned) const;
460 const Value& operator[](int pos) const
461 {
462 assert(pos >= 0);
463 return operator[]((unsigned)pos);
464 }
465
467
468
470
471 void print(std::ostream &out) const
472 {
473 switch (m_type)
474 {
475 case DOC: out << m_doc; return;
476 case ARR:
477 {
478 bool first = true;
479 out << "[";
480 for (auto it = m_arr->begin();it!=m_arr->end();++it)
481 {
482 if (!first)
483 {
484 out << ", ";
485 }
486 else
487 {
488 first = false;
489 }
490
491 switch (it->get_type())
492 {
493 case common::Value::STRING:
494 case common::Value::USTRING:
495 case common::Value::EXPR:
496 out << R"(")" << *it << R"(")";
497 break;
498 default:
499 out << *it;
500 break;
501 }
502
503
504 }
505 out << "]";
506 return;
507 }
508 default: common::Value::print(out); return;
509 }
510 }
511
512protected:
513
514 enum { VAL, ARR, DOC } m_type = VAL;
515
516 void check_type(Type t) const
517 {
518 if (getType() != t)
519 throw Error("Invalid value type");
520 }
521
522 bool is_expr() const
523 {
524 return VAL == m_type && common::Value::EXPR == common::Value::get_type();
525 }
526
528 {
529 common::Value::m_type = common::Value::EXPR;
530 }
531
532 /*
533 TODO: Instead extend common::Value with array and document types. Requires
534 moving DbDoc code to the common layer.
535 */
536
537 typedef std::vector<Value> Array;
538
539 DLL_WARNINGS_PUSH
540
542
543 // Note: shared with other Value instances for the same array.
544 std::shared_ptr<Array> m_arr;
545
546 DLL_WARNINGS_POP
547
548public:
549
551 friend DbDoc;
552
554 friend mysqlx::string;
556
557 struct INTERNAL Access;
558 friend Access;
559};
560
561static const Value nullvalue;
562
563
564inline
565Value& Value::operator=(Value &&other)
566{
567 m_type = other.m_type;
568
569 switch (m_type)
570 {
571 case VAL:
572 common::Value::operator=(std::move(other));
573 break;
574
575 case DOC: m_doc = std::move(other.m_doc); break;
576 case ARR: m_arr = std::move(other.m_arr); break;
577
578 default: break;
579 }
580
581 return *this;
582}
583
584
585namespace internal {
586
587/*
588 Helper class to identify usage of expressions
589*/
590
591class Expression
592 : public mysqlx::Value
593{
594 Expression()
595 {}
596
597 template <typename V>
598 Expression(V&& val)
599 : Value(std::forward<V>(val))
600 {
601 set_as_expr();
602 }
603
604 template <typename V>
605 Expression(const V& val)
606 : Value(val)
607 {
608 set_as_expr();
609 }
610
611 friend Expression expr(std::string&& s);
612 friend Expression expr(const std::string& s);
613};
614
615
635inline
636internal::Expression expr(std::string&& e)
637{
638 return std::forward<std::string>(e);
639}
640
641inline
642internal::Expression expr(const std::string& e)
643{
644 return e;
645}
646
647} // internal
648
649
650using internal::expr;
651
652
653inline
654Value::Type Value::getType() const
655{
656 switch (m_type)
657 {
658 case ARR: return ARRAY;
659 case DOC: return DOCUMENT;
660 case VAL:
661 switch (common::Value::get_type())
662 {
663 case common::Value::VNULL: return VNULL;
664 case common::Value::UINT64: return UINT64;
665 case common::Value::INT64: return INT64;
666 case common::Value::FLOAT: return FLOAT;
667 case common::Value::DOUBLE: return DOUBLE;
668 case common::Value::BOOL: return BOOL;
669 case common::Value::STRING: return STRING;
670 case common::Value::USTRING: return STRING;
671 case common::Value::RAW: return RAW;
672 case common::Value::EXPR: return STRING;
673 case common::Value::JSON: return DOCUMENT;
674 }
675 }
676 return VNULL; // quiet compiler warning
677}
678
679
680/*
681 Value type conversions
682 ----------------------
683 TODO: more informative errors
684*/
685
686
687inline
688Value::Value(const std::initializer_list<Value> &list)
689 : m_type(ARR)
690{
691 try {
692 m_arr = std::make_shared<Array>(list);
693 }
694 CATCH_AND_WRAP
695}
696
697template <typename Iterator>
698inline
699Value::Value(Iterator begin_, Iterator end_)
700 : m_type(ARR)
701{
702 try {
703 m_arr = std::make_shared<Array>(begin_, end_);
704 }
705 CATCH_AND_WRAP
706}
707
708
709inline
710Value::Value(common::Value &&other)
711try
712 : common::Value(std::move(other))
713{}
714CATCH_AND_WRAP
715
716inline
717Value::Value(const common::Value &other)
718try
719 : common::Value(other)
720{}
721CATCH_AND_WRAP
722
723
725{}
726
727inline Value::Value(std::nullptr_t)
728{}
729
730inline Value::Value(int64_t val)
731try
732 : common::Value(val)
733{}
734CATCH_AND_WRAP
735
736inline Value::Value(uint64_t val)
737try
738 : common::Value(val)
739{}
740CATCH_AND_WRAP
741
742template <>
743PUBLIC_API common::Value Value::get<common::Value>() const;
744
745template<>
746inline
747int Value::get<int>() const
748{
749 try {
750 int64_t val = get_sint();
751 if (val > std::numeric_limits<int>::max())
752 throw Error("Numeric conversion overflow");
753 if (val < std::numeric_limits<int>::min())
754 throw Error("Numeric conversion overflow");
755
756 return (int)val;
757 }
758 CATCH_AND_WRAP
759}
760
761inline
762Value::operator int() const
763{
764 return get<int>();
765}
766
767
768template<>
769inline unsigned Value::get<unsigned>() const
770{
771 try {
772 uint64_t val = get_uint();
773 if (val > std::numeric_limits<unsigned>::max())
774 throw Error("Numeric conversion overflow");
775
776 return (unsigned)val;
777 }
778 CATCH_AND_WRAP
779}
780
781inline
782Value::operator unsigned() const
783{
784 return get<unsigned>();
785}
786
787
788template<>
789inline int64_t Value::get<int64_t>() const
790{
791 try {
792 return get_sint();
793 }
794 CATCH_AND_WRAP
795}
796
797inline
798Value::operator int64_t() const
799{
800 return get<int64_t>();
801}
802
803
804template<>
805inline uint64_t Value::get<uint64_t>() const
806{
807 try {
808 return get_uint();
809 }
810 CATCH_AND_WRAP
811}
812
813inline
814Value::operator uint64_t() const
815{
816 return get<uint64_t>();
817}
818
819
820inline Value::Value(float val)
821try
822 : common::Value(val)
823{}
824CATCH_AND_WRAP
825
826template<>
827inline
828float Value::get<float>() const
829{
830 try {
831 return get_float();
832 }
833 CATCH_AND_WRAP
834}
835
836inline
837Value::operator float() const
838{
839 return get<float>();
840}
841
842
843inline Value::Value(double val)
844try
845 : common::Value(val)
846{}
847CATCH_AND_WRAP
848
849template<>
850inline
851double Value::get<double>() const
852{
853 try {
854 return get_double();
855 }
856 CATCH_AND_WRAP
857}
858
859inline
860Value::operator double() const
861{
862 return get<double>();
863}
864
865
866inline Value::Value(bool val)
867try
868 : common::Value(val)
869{}
870CATCH_AND_WRAP
871
872
873template<>
874inline
875bool Value::get<bool>() const
876{
877 try {
878 return get_bool();
879 }
880 CATCH_AND_WRAP
881}
882
883inline
884Value::operator bool() const
885{
886 return get<bool>();
887}
888
889
890inline Value::Value(const DbDoc &doc)
891try
892 : m_type(DOC)
893 , m_doc(doc)
894{}
895CATCH_AND_WRAP
896
897
898
899inline Value::Value(const mysqlx::string &val)
900try
901 : common::Value(val)
902{}
903CATCH_AND_WRAP
904
906try
907 : common::Value(std::move(val))
908{}
909CATCH_AND_WRAP
910
911
912inline Value::Value(const std::string &val)
913try
914 : common::Value(val)
915{}
916CATCH_AND_WRAP
917
918inline Value::Value(std::string &&val)
919try
920 : common::Value(std::move(val))
921{}
922CATCH_AND_WRAP
923
924
925template<>
926inline
927std::wstring Value::get<std::wstring>() const
928{
929 try {
930 return mysqlx::string(this->get_ustring());
931 }
932 CATCH_AND_WRAP
933}
934
935
936template<>
937inline
938std::string Value::get<std::string>() const
939{
940 try {
941 return get_string();
942 }
943 CATCH_AND_WRAP
944}
945
946inline
947Value::operator std::string() const
948{
949 return get<std::string>();
950}
951
952
953template<>
954inline
955mysqlx::string Value::get<mysqlx::string>() const
956{
957 try {
958 return this->get_ustring();
959 }
960 CATCH_AND_WRAP
961}
962
963inline
964Value::operator mysqlx::string() const
965{
966 return get<mysqlx::string>();
967}
968
969
970inline Value::Value(const bytes &data)
971try
972 : common::Value(data.begin(), data.length())
973{}
974CATCH_AND_WRAP
975
976template<>
977inline
978bytes Value::get<bytes>() const
979{
980 return getRawBytes();
981}
982
983inline
984Value::operator bytes() const
985{
986 return get<bytes>();
987}
988
989
990template<>
991inline
992DbDoc Value::get<DbDoc>() const
993{
995 return m_doc;
996}
997
998inline
999Value::operator DbDoc() const
1000{
1001 return get<DbDoc>();
1002}
1003
1004
1005inline
1006bool Value::hasField(const Field &fld) const
1007{
1009 return m_doc.hasField(fld);
1010}
1011
1012inline
1013const Value& Value::operator[](const Field &fld) const
1014{
1016 return m_doc[fld];
1017}
1018
1019inline
1020int DbDoc::fieldType(const Field &fld) const
1021{
1022 return (*this)[fld].getType();
1023}
1024
1025// Array access
1026
1027
1028inline
1029Value::iterator Value::begin()
1030{
1031 if (ARR != m_type)
1032 throw Error("Attempt to iterate over non-array value");
1033 return m_arr->begin();
1034}
1035
1036inline
1037Value::const_iterator Value::begin() const
1038{
1039 if (ARR != m_type)
1040 throw Error("Attempt to iterate over non-array value");
1041 return m_arr->begin();
1042}
1043
1044inline
1045Value::iterator Value::end()
1046{
1047 if (ARR != m_type)
1048 throw Error("Attempt to iterate over non-array value");
1049 return m_arr->end();
1050}
1051
1052inline
1053Value::const_iterator Value::end() const
1054{
1055 if (ARR != m_type)
1056 throw Error("Attempt to iterate over non-array value");
1057 return m_arr->end();
1058}
1059
1060inline
1061const Value& Value::operator[](unsigned pos) const
1062{
1064 return m_arr->at(pos);
1065}
1066
1067inline
1069{
1071 return m_arr->size();
1072}
1073
1074
1075MYSQLX_ABI_END(2,0)
1076} // mysqlx
1077
1078
1079#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:1020
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:815
Base class for connector errors.
Definition: common.h:84
Value object can store value of scalar type, string, array or document.
Definition: document.h:228
bytes getRawBytes() const
Return type of the value stored in this instance (or VNULL if no value is stored).
Definition: document.h:400
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:439
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:516
Type getType() const
Return type of the value stored in this instance (or VNULL if no value is stored).
Definition: document.h:654
Type
Possible types of values.
Definition: document.h:240
@ DOCUMENT
Document.
Definition: document.h:248
@ ARRAY
Array of values.
Definition: document.h:250
@ DOUBLE
Double number.
Definition: document.h:245
@ INT64
Signed integer.
Definition: document.h:243
@ FLOAT
Float number.
Definition: document.h:244
@ UINT64
Unsigned integer.
Definition: document.h:242
@ VNULL
Null value.
Definition: document.h:241
@ RAW
Raw bytes.
Definition: document.h:249
@ BOOL
Boolean.
Definition: document.h:246
@ STRING
String.
Definition: document.h:247
bool hasField(const Field &) const
Check if document value contains given (top-level) field.
Definition: document.h:1006
friend DbDoc
Return type of the value stored in this instance (or VNULL if no value is stored).
Definition: document.h:551
iterator begin()
Access to elements of an array value.
Definition: document.h:1029
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:522
DbDoc m_doc
Return type of the value stored in this instance (or VNULL if no value is stored).
Definition: document.h:541
const Value & operator[](const Field &) const
If this value is not a document, throws error.
Definition: document.h:1013
iterator end()
Return type of the value stored in this instance (or VNULL if no value is stored).
Definition: document.h:1045
friend Access
Return type of the value stored in this instance (or VNULL if no value is stored).
Definition: document.h:557
Value(const std::basic_string< C > &str)
Constructs Null value.
Definition: document.h:271
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:442
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:544
bool isNull() const
Convenience method for checking if value is null.
Definition: document.h:420
Value()
Constructs Null value.
Definition: document.h:724
std::vector< Value > Array
Return type of the value stored in this instance (or VNULL if no value is stored).
Definition: document.h:537
Value(const char *str)
Constructs Null value.
Definition: document.h:268
friend SessionSettings
Return type of the value stored in this instance (or VNULL if no value is stored).
Definition: document.h:550
void print(std::ostream &out) const
Print the value to a stream.
Definition: document.h:471
Value(const C *str)
Constructs Null value.
Definition: document.h:276
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:460
size_t elementCount() const
Return type of the value stored in this instance (or VNULL if no value is stored).
Definition: document.h:1068
void set_as_expr()
Return type of the value stored in this instance (or VNULL if no value is stored).
Definition: document.h:527
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:636