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;
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
364public:
365
372
373 operator int() const;
374 operator unsigned() const;
375 operator int64_t() const;
376 operator uint64_t() const;
377
378 operator float() const;
379 operator double() const;
380
381 explicit operator bool() const;
382
383 operator mysqlx::string() const;
384 explicit operator std::string() const;
385
386 template <typename C>
387 explicit operator std::basic_string<C>() const
388 {
389 return this->operator mysqlx::string();
390 }
391
392 explicit operator bytes() const;
393 operator DbDoc() const;
394
395
396 template<typename T>
397 T get() const;
398
400
401
403 {
404 try {
405 size_t len;
406 const byte *ptr = get_bytes(&len);
407 return { ptr, len };
408 }
409 CATCH_AND_WRAP
410 }
411
412
418 Type getType() const;
419
421
422 bool isNull() const
423 {
424 return VNULL == getType();
425 }
426
432 bool hasField(const Field&) const;
433
439 const Value& operator[](const Field&) const;
440
441 const Value& operator[](const char *name) const
442 { return (*this)[Field(name)]; }
443
444 const Value& operator[](const mysqlx::string &name) const
445 { return (*this)[Field(name)]; }
446
447
454
455 iterator begin();
456 const_iterator begin() const;
457 iterator end();
458 const_iterator end() const;
459 size_t elementCount() const;
460
461 const Value& operator[](unsigned) const;
462 const Value& operator[](int pos) const
463 {
464 assert(pos >= 0);
465 return operator[]((unsigned)pos);
466 }
467
469
470
472
473 void print(std::ostream &out) const
474 {
475 switch (m_type)
476 {
477 case DOC: out << m_doc; return;
478 case ARR:
479 {
480 bool first = true;
481 out << "[";
482 for (auto it = m_arr->begin();it!=m_arr->end();++it)
483 {
484 if (!first)
485 {
486 out << ", ";
487 }
488 else
489 {
490 first = false;
491 }
492
493 switch (it->get_type())
494 {
495 case common::Value::STRING:
496 case common::Value::USTRING:
497 case common::Value::EXPR:
498 out << R"(")" << *it << R"(")";
499 break;
500 default:
501 out << *it;
502 break;
503 }
504
505
506 }
507 out << "]";
508 return;
509 }
510 default: common::Value::print(out); return;
511 }
512 }
513
514protected:
515
516 enum { VAL, ARR, DOC } m_type = VAL;
517
518 void check_type(Type t) const
519 {
520 if (getType() != t)
521 throw Error("Invalid value type");
522 }
523
524 bool is_expr() const
525 {
526 return VAL == m_type && common::Value::EXPR == common::Value::get_type();
527 }
528
530 {
531 common::Value::m_type = common::Value::EXPR;
532 }
533
534 /*
535 TODO: Instead extend common::Value with array and document types. Requires
536 moving DbDoc code to the common layer.
537 */
538
539 typedef std::vector<Value> Array;
540
541 DLL_WARNINGS_PUSH
542
544
545 // Note: shared with other Value instances for the same array.
546 std::shared_ptr<Array> m_arr;
547
548 DLL_WARNINGS_POP
549
550public:
551
553 friend DbDoc;
554
556 friend mysqlx::string;
558
559 struct INTERNAL Access;
560 friend Access;
561};
562
563static const Value nullvalue;
564
565
566inline
567Value& Value::operator=(Value &&other)
568{
569 m_type = other.m_type;
570
571 switch (m_type)
572 {
573 case VAL:
574 common::Value::operator=(std::move(other));
575 break;
576
577 case DOC: m_doc = std::move(other.m_doc); break;
578 case ARR: m_arr = std::move(other.m_arr); break;
579
580 default: break;
581 }
582
583 return *this;
584}
585
586
587namespace internal {
588
589/*
590 Helper class to identify usage of expressions
591*/
592
593class Expression
594 : public mysqlx::Value
595{
596 Expression()
597 {}
598
599 template <typename V>
600 Expression(V&& val)
601 : Value(std::forward<V>(val))
602 {
603 set_as_expr();
604 }
605
606 template <typename V>
607 Expression(const V& val)
608 : Value(val)
609 {
610 set_as_expr();
611 }
612
613 friend Expression expr(std::string&& s);
614 friend Expression expr(const std::string& s);
615};
616
617
637inline
638internal::Expression expr(std::string&& e)
639{
640 return std::forward<std::string>(e);
641}
642
643inline
644internal::Expression expr(const std::string& e)
645{
646 return e;
647}
648
649} // internal
650
651
652using internal::expr;
653
654
655inline
656Value::Type Value::getType() const
657{
658 switch (m_type)
659 {
660 case ARR: return ARRAY;
661 case DOC: return DOCUMENT;
662 case VAL:
663 switch (common::Value::get_type())
664 {
665 case common::Value::VNULL: return VNULL;
666 case common::Value::UINT64: return UINT64;
667 case common::Value::INT64: return INT64;
668 case common::Value::FLOAT: return FLOAT;
669 case common::Value::DOUBLE: return DOUBLE;
670 case common::Value::BOOL: return BOOL;
671 case common::Value::STRING: return STRING;
672 case common::Value::USTRING: return STRING;
673 case common::Value::RAW: return RAW;
674 case common::Value::EXPR: return STRING;
675 case common::Value::JSON: return DOCUMENT;
676 }
677 }
678 return VNULL; // quiet compiler warning
679}
680
681
682/*
683 Value type conversions
684 ----------------------
685 TODO: more informative errors
686*/
687
688
689inline
690Value::Value(const std::initializer_list<Value> &list)
691 : m_type(ARR)
692{
693 try {
694 m_arr = std::make_shared<Array>(list);
695 }
696 CATCH_AND_WRAP
697}
698
699template <typename Iterator>
700inline
701Value::Value(Iterator begin_, Iterator end_)
702 : m_type(ARR)
703{
704 try {
705 m_arr = std::make_shared<Array>(begin_, end_);
706 }
707 CATCH_AND_WRAP
708}
709
710
711inline
712Value::Value(common::Value &&other)
713try
714 : common::Value(std::move(other))
715{}
716CATCH_AND_WRAP
717
718inline
719Value::Value(const common::Value &other)
720try
721 : common::Value(other)
722{}
723CATCH_AND_WRAP
724
725
727{}
728
729inline Value::Value(std::nullptr_t)
730{}
731
732inline Value::Value(int64_t val)
733try
734 : common::Value(val)
735{}
736CATCH_AND_WRAP
737
738inline Value::Value(uint64_t val)
739try
740 : common::Value(val)
741{}
742CATCH_AND_WRAP
743
744template <>
745PUBLIC_API common::Value Value::get<common::Value>() const;
746
747template<>
748inline
749int Value::get<int>() const
750{
751 try {
752 int64_t val = get_sint();
753 if (val > std::numeric_limits<int>::max())
754 throw Error("Numeric conversion overflow");
755 if (val < std::numeric_limits<int>::min())
756 throw Error("Numeric conversion overflow");
757
758 return (int)val;
759 }
760 CATCH_AND_WRAP
761}
762
763inline
764Value::operator int() const
765{
766 return get<int>();
767}
768
769
770template<>
771inline unsigned Value::get<unsigned>() const
772{
773 try {
774 uint64_t val = get_uint();
775 if (val > std::numeric_limits<unsigned>::max())
776 throw Error("Numeric conversion overflow");
777
778 return (unsigned)val;
779 }
780 CATCH_AND_WRAP
781}
782
783inline
784Value::operator unsigned() const
785{
786 return get<unsigned>();
787}
788
789
790template<>
791inline int64_t Value::get<int64_t>() const
792{
793 try {
794 return get_sint();
795 }
796 CATCH_AND_WRAP
797}
798
799inline
800Value::operator int64_t() const
801{
802 return get<int64_t>();
803}
804
805
806template<>
807inline uint64_t Value::get<uint64_t>() const
808{
809 try {
810 return get_uint();
811 }
812 CATCH_AND_WRAP
813}
814
815inline
816Value::operator uint64_t() const
817{
818 return get<uint64_t>();
819}
820
821
822inline Value::Value(float val)
823try
824 : common::Value(val)
825{}
826CATCH_AND_WRAP
827
828template<>
829inline
830float Value::get<float>() const
831{
832 try {
833 return get_float();
834 }
835 CATCH_AND_WRAP
836}
837
838inline
839Value::operator float() const
840{
841 return get<float>();
842}
843
844
845inline Value::Value(double val)
846try
847 : common::Value(val)
848{}
849CATCH_AND_WRAP
850
851template<>
852inline
853double Value::get<double>() const
854{
855 try {
856 return get_double();
857 }
858 CATCH_AND_WRAP
859}
860
861inline
862Value::operator double() const
863{
864 return get<double>();
865}
866
867
868inline Value::Value(bool val)
869try
870 : common::Value(val)
871{}
872CATCH_AND_WRAP
873
874
875template<>
876inline
877bool Value::get<bool>() const
878{
879 try {
880 return get_bool();
881 }
882 CATCH_AND_WRAP
883}
884
885inline
886Value::operator bool() const
887{
888 return get<bool>();
889}
890
891
892inline Value::Value(const DbDoc &doc)
893try
894 : m_type(DOC)
895 , m_doc(doc)
896{}
897CATCH_AND_WRAP
898
899
900
901inline Value::Value(const mysqlx::string &val)
902try
903 : common::Value(val)
904{}
905CATCH_AND_WRAP
906
908try
909 : common::Value(std::move(val))
910{}
911CATCH_AND_WRAP
912
913
914inline Value::Value(const std::string &val)
915try
916 : common::Value(val)
917{}
918CATCH_AND_WRAP
919
920inline Value::Value(std::string &&val)
921try
922 : common::Value(std::move(val))
923{}
924CATCH_AND_WRAP
925
926
927template<>
928inline
929std::wstring Value::get<std::wstring>() const
930{
931 try {
932 return mysqlx::string(this->get_ustring());
933 }
934 CATCH_AND_WRAP
935}
936
937
938template<>
939inline
940std::string Value::get<std::string>() const
941{
942 try {
943 return get_string();
944 }
945 CATCH_AND_WRAP
946}
947
948inline
949Value::operator std::string() const
950{
951 return get<std::string>();
952}
953
954
955template<>
956inline
957mysqlx::string Value::get<mysqlx::string>() const
958{
959 try {
960 return this->get_ustring();
961 }
962 CATCH_AND_WRAP
963}
964
965inline
966Value::operator mysqlx::string() const
967{
968 return get<mysqlx::string>();
969}
970
971
972inline Value::Value(const bytes &data)
973try
974 : common::Value(data.begin(), data.length())
975{}
976CATCH_AND_WRAP
977
978template<>
979inline
980bytes Value::get<bytes>() const
981{
982 return getRawBytes();
983}
984
985inline
986Value::operator bytes() const
987{
988 return get<bytes>();
989}
990
991
992template<>
993inline
994DbDoc Value::get<DbDoc>() const
995{
997 return m_doc;
998}
999
1000inline
1001Value::operator DbDoc() const
1002{
1003 return get<DbDoc>();
1004}
1005
1006
1007inline
1008bool Value::hasField(const Field &fld) const
1009{
1011 return m_doc.hasField(fld);
1012}
1013
1014inline
1015const Value& Value::operator[](const Field &fld) const
1016{
1018 return m_doc[fld];
1019}
1020
1021inline
1022int DbDoc::fieldType(const Field &fld) const
1023{
1024 return (*this)[fld].getType();
1025}
1026
1027// Array access
1028
1029
1030inline
1031Value::iterator Value::begin()
1032{
1033 if (ARR != m_type)
1034 throw Error("Attempt to iterate over non-array value");
1035 return m_arr->begin();
1036}
1037
1038inline
1039Value::const_iterator Value::begin() const
1040{
1041 if (ARR != m_type)
1042 throw Error("Attempt to iterate over non-array value");
1043 return m_arr->begin();
1044}
1045
1046inline
1047Value::iterator Value::end()
1048{
1049 if (ARR != m_type)
1050 throw Error("Attempt to iterate over non-array value");
1051 return m_arr->end();
1052}
1053
1054inline
1055Value::const_iterator Value::end() const
1056{
1057 if (ARR != m_type)
1058 throw Error("Attempt to iterate over non-array value");
1059 return m_arr->end();
1060}
1061
1062inline
1063const Value& Value::operator[](unsigned pos) const
1064{
1066 return m_arr->at(pos);
1067}
1068
1069inline
1071{
1073 return m_arr->size();
1074}
1075
1076
1077MYSQLX_ABI_END(2,0)
1078} // mysqlx
1079
1080
1081#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:1022
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:230
bytes getRawBytes() const
Return type of the value stored in this instance (or VNULL if no value is stored).
Definition: document.h:402
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:441
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:518
Type getType() const
Return type of the value stored in this instance (or VNULL if no value is stored).
Definition: document.h:656
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:1008
friend DbDoc
Return type of the value stored in this instance (or VNULL if no value is stored).
Definition: document.h:553
iterator begin()
Access to elements of an array value.
Definition: document.h:1031
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:524
DbDoc m_doc
Return type of the value stored in this instance (or VNULL if no value is stored).
Definition: document.h:543
const Value & operator[](const Field &) const
If this value is not a document, throws error.
Definition: document.h:1015
iterator end()
Return type of the value stored in this instance (or VNULL if no value is stored).
Definition: document.h:1047
friend Access
Return type of the value stored in this instance (or VNULL if no value is stored).
Definition: document.h:559
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:444
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:546
bool isNull() const
Convenience method for checking if value is null.
Definition: document.h:422
Value()
Constructs Null value.
Definition: document.h:726
std::vector< Value > Array
Return type of the value stored in this instance (or VNULL if no value is stored).
Definition: document.h:539
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:552
void print(std::ostream &out) const
Print the value to a stream.
Definition: document.h:473
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:462
size_t elementCount() const
Return type of the value stored in this instance (or VNULL if no value is stored).
Definition: document.h:1070
void set_as_expr()
Return type of the value stored in this instance (or VNULL if no value is stored).
Definition: document.h:529
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:638