1077 lines
19 KiB
C
1077 lines
19 KiB
C
|
/*
|
||
|
* Copyright (c) 2015, 2020, Oracle and/or its affiliates.
|
||
|
*
|
||
|
* This program is free software; you can redistribute it and/or modify
|
||
|
* it under the terms of the GNU General Public License, version 2.0, as
|
||
|
* published by the Free Software Foundation.
|
||
|
*
|
||
|
* This program is also distributed with certain software (including
|
||
|
* but not limited to OpenSSL) that is licensed under separate terms,
|
||
|
* as designated in a particular file or component or in included license
|
||
|
* documentation. The authors of MySQL hereby grant you an
|
||
|
* additional permission to link the program and your derivative works
|
||
|
* with the separately licensed software that they have included with
|
||
|
* MySQL.
|
||
|
*
|
||
|
* Without limiting anything contained in the foregoing, this file,
|
||
|
* which is part of MySQL Connector/C++, is also subject to the
|
||
|
* Universal FOSS Exception, version 1.0, a copy of which can be found at
|
||
|
* http://oss.oracle.com/licenses/universal-foss-exception.
|
||
|
*
|
||
|
* This program is distributed in the hope that it will be useful, but
|
||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||
|
* See the GNU General Public License, version 2.0, for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU General Public License
|
||
|
* along with this program; if not, write to the Free Software Foundation, Inc.,
|
||
|
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||
|
*/
|
||
|
|
||
|
#ifndef MYSQLX_DOCUMENT_H
|
||
|
#define MYSQLX_DOCUMENT_H
|
||
|
|
||
|
/**
|
||
|
@file
|
||
|
Declaration of DbDoc and related classes.
|
||
|
*/
|
||
|
|
||
|
#include "common.h"
|
||
|
|
||
|
#include <memory>
|
||
|
#include <stdint.h>
|
||
|
#include <limits>
|
||
|
#include <vector>
|
||
|
#include <assert.h>
|
||
|
|
||
|
#undef min
|
||
|
#undef max
|
||
|
|
||
|
|
||
|
namespace mysqlx {
|
||
|
MYSQLX_ABI_BEGIN(2,0)
|
||
|
|
||
|
class Value;
|
||
|
class DbDoc;
|
||
|
class DocResult;
|
||
|
class SessionSettings;
|
||
|
|
||
|
namespace internal{
|
||
|
class Schema_detail;
|
||
|
|
||
|
} //internal
|
||
|
|
||
|
using Field = std::string;
|
||
|
|
||
|
|
||
|
// Document class
|
||
|
// ==============
|
||
|
|
||
|
|
||
|
/**
|
||
|
Represents a collection of key-value pairs where value can be a scalar
|
||
|
or another document.
|
||
|
|
||
|
@note Internal document implementation is shared among DbDoc instances
|
||
|
and thus using DbDoc objects should be cheap.
|
||
|
|
||
|
@ingroup devapi_res
|
||
|
*/
|
||
|
|
||
|
class PUBLIC_API DbDoc
|
||
|
: public common::Printable
|
||
|
{
|
||
|
// TODO: move PUBLIC_API stuff to a detail class
|
||
|
|
||
|
class INTERNAL Impl;
|
||
|
|
||
|
DLL_WARNINGS_PUSH
|
||
|
|
||
|
std::shared_ptr<Impl> m_impl;
|
||
|
|
||
|
DLL_WARNINGS_POP
|
||
|
|
||
|
INTERNAL DbDoc(const std::shared_ptr<Impl>&);
|
||
|
|
||
|
const char* get_json() const;
|
||
|
|
||
|
public:
|
||
|
|
||
|
/**
|
||
|
Create null document instance.
|
||
|
|
||
|
@note Null document is different from empty document that has
|
||
|
no fields.
|
||
|
*/
|
||
|
|
||
|
DbDoc() {}
|
||
|
|
||
|
/**
|
||
|
Creates DbDoc instance out of given JSON string description.
|
||
|
*/
|
||
|
|
||
|
explicit DbDoc(const std::string&);
|
||
|
explicit DbDoc(std::string&&);
|
||
|
|
||
|
|
||
|
/**
|
||
|
Check if document is null
|
||
|
*/
|
||
|
|
||
|
bool isNull() const { return NULL == m_impl.get(); }
|
||
|
operator bool() const { return !isNull(); }
|
||
|
|
||
|
|
||
|
/**
|
||
|
Check if named field is a top-level field in the document.
|
||
|
*/
|
||
|
|
||
|
virtual bool hasField(const Field&) const;
|
||
|
|
||
|
|
||
|
/**
|
||
|
Return Value::XXX constant that identifies type of value
|
||
|
stored at given field.
|
||
|
*/
|
||
|
|
||
|
virtual int fieldType(const Field&) const;
|
||
|
|
||
|
/**
|
||
|
Return value of given field.
|
||
|
*/
|
||
|
|
||
|
virtual const Value& operator[](const Field&) const;
|
||
|
|
||
|
const Value& operator[](const char *name) const
|
||
|
{
|
||
|
return this->operator[](Field(name));
|
||
|
}
|
||
|
|
||
|
const Value& operator[](const mysqlx::string &name) const
|
||
|
{
|
||
|
return this->operator[](Field(name));
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
Print JSON description of the document.
|
||
|
*/
|
||
|
|
||
|
virtual void print(std::ostream&) const;
|
||
|
|
||
|
/**
|
||
|
Iterator instance can iterate over (top-level) fields of a document.
|
||
|
A new iterator is obtained from begin() method.
|
||
|
|
||
|
@note Only one instance of an iterator can be used at a time (not
|
||
|
thread safe!).
|
||
|
*/
|
||
|
|
||
|
class Iterator;
|
||
|
|
||
|
virtual Iterator begin();
|
||
|
virtual Iterator end();
|
||
|
|
||
|
friend Impl;
|
||
|
friend DocResult;
|
||
|
friend Value;
|
||
|
friend internal::Schema_detail;
|
||
|
};
|
||
|
|
||
|
|
||
|
class PUBLIC_API DbDoc::Iterator
|
||
|
{
|
||
|
DLL_WARNINGS_PUSH
|
||
|
std::shared_ptr<DbDoc::Impl> m_impl;
|
||
|
DLL_WARNINGS_POP
|
||
|
bool m_end;
|
||
|
|
||
|
public:
|
||
|
|
||
|
Iterator& operator++();
|
||
|
bool operator==(const Iterator&) const;
|
||
|
bool operator!=(const Iterator &other) const { return !(*this == other); }
|
||
|
const Field& operator*();
|
||
|
|
||
|
friend DbDoc;
|
||
|
};
|
||
|
|
||
|
|
||
|
// Value class
|
||
|
// ===========
|
||
|
|
||
|
/**
|
||
|
%Value object can store value of scalar type, string, array or document.
|
||
|
|
||
|
Implicit conversions to and from corresponding C++ types are defined.
|
||
|
If conversion to wrong type is attempted, an error is thrown. If Value
|
||
|
object holds an array or document, then array elements or fields of
|
||
|
the document can be accessed using operator[]. Array values can be used
|
||
|
as STL containers.
|
||
|
|
||
|
Only direct conversions of stored value to the corresponding C++ type
|
||
|
are supported. There are no implicit number->string conversions etc.
|
||
|
|
||
|
Values of type RAW can refer to a region of memory containing raw bytes.
|
||
|
Such values are created from `bytes` and can by casted to `bytes` type.
|
||
|
|
||
|
@note Value object copies the values it stores. Thus, after storing value
|
||
|
in Value object, the original value can be destroyed without invalidating
|
||
|
the copy. This includes RAW Values which hold a copy of bytes.
|
||
|
|
||
|
@ingroup devapi_res
|
||
|
*/
|
||
|
|
||
|
class Value
|
||
|
: public virtual common::Printable
|
||
|
, protected common::Value
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
using string = mysqlx::string;
|
||
|
|
||
|
/**
|
||
|
Possible types of values.
|
||
|
|
||
|
@sa getType()
|
||
|
*/
|
||
|
|
||
|
enum Type
|
||
|
{
|
||
|
VNULL, ///< Null value
|
||
|
UINT64, ///< Unsigned integer
|
||
|
INT64, ///< Signed integer
|
||
|
FLOAT, ///< Float number
|
||
|
DOUBLE, ///< Double number
|
||
|
BOOL, ///< Boolean
|
||
|
STRING, ///< String
|
||
|
DOCUMENT, ///< Document
|
||
|
RAW, ///< Raw bytes
|
||
|
ARRAY, ///< Array of values
|
||
|
};
|
||
|
|
||
|
typedef std::vector<Value>::iterator iterator;
|
||
|
typedef std::vector<Value>::const_iterator const_iterator;
|
||
|
|
||
|
///@name Value Constructors
|
||
|
///@{
|
||
|
|
||
|
Value(); ///< Constructs Null value.
|
||
|
Value(std::nullptr_t); ///< Constructs Null value.
|
||
|
|
||
|
Value(const mysqlx::string &str);
|
||
|
Value(mysqlx::string &&str);
|
||
|
//Value(const char16_t *str) : Value(mysqlx::string(str)) {}
|
||
|
|
||
|
Value(const std::string &str);
|
||
|
Value(std::string &&str);
|
||
|
Value(const char *str) : Value(std::string(str)) {}
|
||
|
|
||
|
template <typename C>
|
||
|
Value(const std::basic_string<C> &str)
|
||
|
: Value(mysqlx::string(str))
|
||
|
{}
|
||
|
|
||
|
template <typename C>
|
||
|
Value(const C *str)
|
||
|
: Value(mysqlx::string(str))
|
||
|
{}
|
||
|
|
||
|
Value(const bytes&);
|
||
|
Value(int64_t);
|
||
|
Value(uint64_t);
|
||
|
Value(float);
|
||
|
Value(double);
|
||
|
Value(bool);
|
||
|
Value(const DbDoc& doc);
|
||
|
|
||
|
Value(const std::initializer_list<Value> &list);
|
||
|
template <typename Iterator>
|
||
|
Value(Iterator begin_, Iterator end_);
|
||
|
|
||
|
///@}
|
||
|
|
||
|
Value(common::Value &&other);
|
||
|
Value(const common::Value &other);
|
||
|
|
||
|
Value(const Value&) = default;
|
||
|
|
||
|
#ifdef HAVE_MOVE_CTORS
|
||
|
|
||
|
Value(Value&&) = default;
|
||
|
|
||
|
#else
|
||
|
|
||
|
// Note move ctor implemented using move assignment defined below.
|
||
|
|
||
|
Value(Value &&other)
|
||
|
{
|
||
|
*this = std::move(other);
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
/*
|
||
|
Note: These templates are needed to disambiguate constructor resolution
|
||
|
for integer types.
|
||
|
*/
|
||
|
|
||
|
template <
|
||
|
typename T,
|
||
|
typename std::enable_if<std::is_signed<T>::value>::type* = nullptr
|
||
|
>
|
||
|
Value(T x)
|
||
|
: Value(static_cast<int64_t>(x))
|
||
|
{}
|
||
|
|
||
|
template <
|
||
|
typename T,
|
||
|
typename std::enable_if<std::is_unsigned<T>::value>::type* = nullptr
|
||
|
>
|
||
|
Value(T x)
|
||
|
: Value(static_cast<uint64_t>(x))
|
||
|
{}
|
||
|
|
||
|
|
||
|
Value& operator=(const Value&) = default;
|
||
|
|
||
|
/*
|
||
|
Note: Move assignment is defined explicitly to avoid problems with
|
||
|
virtual Printable base.
|
||
|
*/
|
||
|
|
||
|
Value& operator=(Value&&);
|
||
|
|
||
|
/*
|
||
|
Assignment is implemented in terms of constructors: first an instance
|
||
|
is created from the input data and then move assignment is used to place
|
||
|
the result into this instance.
|
||
|
*/
|
||
|
|
||
|
template<typename T>
|
||
|
Value& operator=(T&& x)
|
||
|
{
|
||
|
try {
|
||
|
*this = Value(std::forward<T>(x));
|
||
|
return *this;
|
||
|
}
|
||
|
CATCH_AND_WRAP
|
||
|
}
|
||
|
|
||
|
|
||
|
public:
|
||
|
|
||
|
/**
|
||
|
@name Conversion to C++ Types
|
||
|
|
||
|
Attempt to convert value of non-compatible type throws an error.
|
||
|
*/
|
||
|
//@{
|
||
|
|
||
|
operator int() const;
|
||
|
operator unsigned() const;
|
||
|
operator int64_t() const;
|
||
|
operator uint64_t() const;
|
||
|
|
||
|
operator float() const;
|
||
|
operator double() const;
|
||
|
|
||
|
explicit operator bool() const;
|
||
|
|
||
|
operator mysqlx::string() const;
|
||
|
explicit operator std::string() const;
|
||
|
|
||
|
template <typename C>
|
||
|
explicit operator std::basic_string<C>() const
|
||
|
{
|
||
|
return this->operator mysqlx::string();
|
||
|
}
|
||
|
|
||
|
explicit operator bytes() const;
|
||
|
operator DbDoc() const;
|
||
|
|
||
|
|
||
|
template<typename T>
|
||
|
T get() const;
|
||
|
|
||
|
//@}
|
||
|
|
||
|
|
||
|
bytes getRawBytes() const
|
||
|
{
|
||
|
try {
|
||
|
size_t len;
|
||
|
const byte *ptr = get_bytes(&len);
|
||
|
return { ptr, len };
|
||
|
}
|
||
|
CATCH_AND_WRAP
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
Return type of the value stored in this instance (or VNULL if no
|
||
|
value is stored).
|
||
|
*/
|
||
|
|
||
|
Type getType() const;
|
||
|
|
||
|
/// Convenience method for checking if value is null.
|
||
|
|
||
|
bool isNull() const
|
||
|
{
|
||
|
return VNULL == getType();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Check if document value contains given (top-level) field.
|
||
|
Throws error if this is not a document value.
|
||
|
*/
|
||
|
|
||
|
bool hasField(const Field&) const;
|
||
|
|
||
|
/**
|
||
|
If this value is not a document, throws error. Otherwise
|
||
|
returns value of given field of the document.
|
||
|
*/
|
||
|
|
||
|
const Value& operator[](const Field&) const;
|
||
|
|
||
|
const Value& operator[](const char *name) const
|
||
|
{ return (*this)[Field(name)]; }
|
||
|
|
||
|
const Value& operator[](const mysqlx::string &name) const
|
||
|
{ return (*this)[Field(name)]; }
|
||
|
|
||
|
|
||
|
/**
|
||
|
Access to elements of an array value.
|
||
|
|
||
|
If non-array value is accessed like an array, an error is thrown.
|
||
|
*/
|
||
|
//@{
|
||
|
|
||
|
iterator begin();
|
||
|
const_iterator begin() const;
|
||
|
iterator end();
|
||
|
const_iterator end() const;
|
||
|
size_t elementCount() const;
|
||
|
|
||
|
const Value& operator[](unsigned) const;
|
||
|
const Value& operator[](int pos) const
|
||
|
{
|
||
|
assert(pos >= 0);
|
||
|
return operator[]((unsigned)pos);
|
||
|
}
|
||
|
|
||
|
//@}
|
||
|
|
||
|
|
||
|
/// Print the value to a stream.
|
||
|
|
||
|
void print(std::ostream &out) const
|
||
|
{
|
||
|
switch (m_type)
|
||
|
{
|
||
|
case DOC: out << m_doc; return;
|
||
|
case ARR:
|
||
|
{
|
||
|
bool first = true;
|
||
|
out << "[";
|
||
|
for (auto it = m_arr->begin();it!=m_arr->end();++it)
|
||
|
{
|
||
|
if (!first)
|
||
|
{
|
||
|
out << ", ";
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
first = false;
|
||
|
}
|
||
|
|
||
|
switch (it->get_type())
|
||
|
{
|
||
|
case common::Value::STRING:
|
||
|
case common::Value::USTRING:
|
||
|
case common::Value::EXPR:
|
||
|
out << R"(")" << *it << R"(")";
|
||
|
break;
|
||
|
default:
|
||
|
out << *it;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|
||
|
out << "]";
|
||
|
return;
|
||
|
}
|
||
|
default: common::Value::print(out); return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
|
||
|
enum { VAL, ARR, DOC } m_type = VAL;
|
||
|
|
||
|
void check_type(Type t) const
|
||
|
{
|
||
|
if (getType() != t)
|
||
|
throw Error("Invalid value type");
|
||
|
}
|
||
|
|
||
|
bool is_expr() const
|
||
|
{
|
||
|
return VAL == m_type && common::Value::EXPR == common::Value::get_type();
|
||
|
}
|
||
|
|
||
|
void set_as_expr()
|
||
|
{
|
||
|
common::Value::m_type = common::Value::EXPR;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
TODO: Instead extend common::Value with array and document types. Requires
|
||
|
moving DbDoc code to the common layer.
|
||
|
*/
|
||
|
|
||
|
typedef std::vector<Value> Array;
|
||
|
|
||
|
DLL_WARNINGS_PUSH
|
||
|
|
||
|
DbDoc m_doc;
|
||
|
|
||
|
// Note: shared with other Value instances for the same array.
|
||
|
std::shared_ptr<Array> m_arr;
|
||
|
|
||
|
DLL_WARNINGS_POP
|
||
|
|
||
|
public:
|
||
|
|
||
|
friend SessionSettings;
|
||
|
friend DbDoc;
|
||
|
|
||
|
///@cond IGNORE
|
||
|
friend mysqlx::string;
|
||
|
///@endcond IGNORE
|
||
|
|
||
|
struct INTERNAL Access;
|
||
|
friend Access;
|
||
|
};
|
||
|
|
||
|
static const Value nullvalue;
|
||
|
|
||
|
|
||
|
inline
|
||
|
Value& Value::operator=(Value &&other)
|
||
|
{
|
||
|
m_type = other.m_type;
|
||
|
|
||
|
switch (m_type)
|
||
|
{
|
||
|
case VAL:
|
||
|
common::Value::operator=(std::move(other));
|
||
|
break;
|
||
|
|
||
|
case DOC: m_doc = std::move(other.m_doc); break;
|
||
|
case ARR: m_arr = std::move(other.m_arr); break;
|
||
|
|
||
|
default: break;
|
||
|
}
|
||
|
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
|
||
|
namespace internal {
|
||
|
|
||
|
/*
|
||
|
Helper class to identify usage of expressions
|
||
|
*/
|
||
|
|
||
|
class Expression
|
||
|
: public mysqlx::Value
|
||
|
{
|
||
|
Expression()
|
||
|
{}
|
||
|
|
||
|
template <typename V>
|
||
|
Expression(V&& val)
|
||
|
: Value(std::forward<V>(val))
|
||
|
{
|
||
|
set_as_expr();
|
||
|
}
|
||
|
|
||
|
template <typename V>
|
||
|
Expression(const V& val)
|
||
|
: Value(val)
|
||
|
{
|
||
|
set_as_expr();
|
||
|
}
|
||
|
|
||
|
friend Expression expr(std::string&& s);
|
||
|
friend Expression expr(const std::string& s);
|
||
|
};
|
||
|
|
||
|
|
||
|
/**
|
||
|
Function which indicates that a given string should be treated
|
||
|
as expression.
|
||
|
|
||
|
If `s` is a string value, then in contexts where values are
|
||
|
expected, `expr(s)` treats `s` as a DevAPI expression. For
|
||
|
example statement
|
||
|
|
||
|
table.select("foo > 1").execute();
|
||
|
|
||
|
returns the string `"foo 1"` for each row in the table while
|
||
|
|
||
|
table.select(expr("foo > 1")).execute();
|
||
|
|
||
|
returns true/false, depending on the value of the expression.
|
||
|
|
||
|
@ingroup devapi
|
||
|
*/
|
||
|
|
||
|
inline
|
||
|
internal::Expression expr(std::string&& e)
|
||
|
{
|
||
|
return std::forward<std::string>(e);
|
||
|
}
|
||
|
|
||
|
inline
|
||
|
internal::Expression expr(const std::string& e)
|
||
|
{
|
||
|
return e;
|
||
|
}
|
||
|
|
||
|
} // internal
|
||
|
|
||
|
|
||
|
using internal::expr;
|
||
|
|
||
|
|
||
|
inline
|
||
|
Value::Type Value::getType() const
|
||
|
{
|
||
|
switch (m_type)
|
||
|
{
|
||
|
case ARR: return ARRAY;
|
||
|
case DOC: return DOCUMENT;
|
||
|
case VAL:
|
||
|
switch (common::Value::get_type())
|
||
|
{
|
||
|
case common::Value::VNULL: return VNULL;
|
||
|
case common::Value::UINT64: return UINT64;
|
||
|
case common::Value::INT64: return INT64;
|
||
|
case common::Value::FLOAT: return FLOAT;
|
||
|
case common::Value::DOUBLE: return DOUBLE;
|
||
|
case common::Value::BOOL: return BOOL;
|
||
|
case common::Value::STRING: return STRING;
|
||
|
case common::Value::USTRING: return STRING;
|
||
|
case common::Value::RAW: return RAW;
|
||
|
case common::Value::EXPR: return STRING;
|
||
|
case common::Value::JSON: return DOCUMENT;
|
||
|
}
|
||
|
}
|
||
|
return VNULL; // quiet compiler warning
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
Value type conversions
|
||
|
----------------------
|
||
|
TODO: more informative errors
|
||
|
*/
|
||
|
|
||
|
|
||
|
inline
|
||
|
Value::Value(const std::initializer_list<Value> &list)
|
||
|
: m_type(ARR)
|
||
|
{
|
||
|
try {
|
||
|
m_arr = std::make_shared<Array>(list);
|
||
|
}
|
||
|
CATCH_AND_WRAP
|
||
|
}
|
||
|
|
||
|
template <typename Iterator>
|
||
|
inline
|
||
|
Value::Value(Iterator begin_, Iterator end_)
|
||
|
: m_type(ARR)
|
||
|
{
|
||
|
try {
|
||
|
m_arr = std::make_shared<Array>(begin_, end_);
|
||
|
}
|
||
|
CATCH_AND_WRAP
|
||
|
}
|
||
|
|
||
|
|
||
|
inline
|
||
|
Value::Value(common::Value &&other)
|
||
|
try
|
||
|
: common::Value(std::move(other))
|
||
|
{}
|
||
|
CATCH_AND_WRAP
|
||
|
|
||
|
inline
|
||
|
Value::Value(const common::Value &other)
|
||
|
try
|
||
|
: common::Value(other)
|
||
|
{}
|
||
|
CATCH_AND_WRAP
|
||
|
|
||
|
|
||
|
inline Value::Value()
|
||
|
{}
|
||
|
|
||
|
inline Value::Value(std::nullptr_t)
|
||
|
{}
|
||
|
|
||
|
inline Value::Value(int64_t val)
|
||
|
try
|
||
|
: common::Value(val)
|
||
|
{}
|
||
|
CATCH_AND_WRAP
|
||
|
|
||
|
inline Value::Value(uint64_t val)
|
||
|
try
|
||
|
: common::Value(val)
|
||
|
{}
|
||
|
CATCH_AND_WRAP
|
||
|
|
||
|
template<>
|
||
|
inline
|
||
|
int Value::get<int>() const
|
||
|
{
|
||
|
try {
|
||
|
int64_t val = get_sint();
|
||
|
if (val > std::numeric_limits<int>::max())
|
||
|
throw Error("Numeric conversion overflow");
|
||
|
if (val < std::numeric_limits<int>::min())
|
||
|
throw Error("Numeric conversion overflow");
|
||
|
|
||
|
return (int)val;
|
||
|
}
|
||
|
CATCH_AND_WRAP
|
||
|
}
|
||
|
|
||
|
inline
|
||
|
Value::operator int() const
|
||
|
{
|
||
|
return get<int>();
|
||
|
}
|
||
|
|
||
|
|
||
|
template<>
|
||
|
inline unsigned Value::get<unsigned>() const
|
||
|
{
|
||
|
try {
|
||
|
uint64_t val = get_uint();
|
||
|
if (val > std::numeric_limits<unsigned>::max())
|
||
|
throw Error("Numeric conversion overflow");
|
||
|
|
||
|
return (unsigned)val;
|
||
|
}
|
||
|
CATCH_AND_WRAP
|
||
|
}
|
||
|
|
||
|
inline
|
||
|
Value::operator unsigned() const
|
||
|
{
|
||
|
return get<unsigned>();
|
||
|
}
|
||
|
|
||
|
|
||
|
template<>
|
||
|
inline int64_t Value::get<int64_t>() const
|
||
|
{
|
||
|
try {
|
||
|
return get_sint();
|
||
|
}
|
||
|
CATCH_AND_WRAP
|
||
|
}
|
||
|
|
||
|
inline
|
||
|
Value::operator int64_t() const
|
||
|
{
|
||
|
return get<int64_t>();
|
||
|
}
|
||
|
|
||
|
|
||
|
template<>
|
||
|
inline uint64_t Value::get<uint64_t>() const
|
||
|
{
|
||
|
try {
|
||
|
return get_uint();
|
||
|
}
|
||
|
CATCH_AND_WRAP
|
||
|
}
|
||
|
|
||
|
inline
|
||
|
Value::operator uint64_t() const
|
||
|
{
|
||
|
return get<uint64_t>();
|
||
|
}
|
||
|
|
||
|
|
||
|
inline Value::Value(float val)
|
||
|
try
|
||
|
: common::Value(val)
|
||
|
{}
|
||
|
CATCH_AND_WRAP
|
||
|
|
||
|
template<>
|
||
|
inline
|
||
|
float Value::get<float>() const
|
||
|
{
|
||
|
try {
|
||
|
return get_float();
|
||
|
}
|
||
|
CATCH_AND_WRAP
|
||
|
}
|
||
|
|
||
|
inline
|
||
|
Value::operator float() const
|
||
|
{
|
||
|
return get<float>();
|
||
|
}
|
||
|
|
||
|
|
||
|
inline Value::Value(double val)
|
||
|
try
|
||
|
: common::Value(val)
|
||
|
{}
|
||
|
CATCH_AND_WRAP
|
||
|
|
||
|
template<>
|
||
|
inline
|
||
|
double Value::get<double>() const
|
||
|
{
|
||
|
try {
|
||
|
return get_double();
|
||
|
}
|
||
|
CATCH_AND_WRAP
|
||
|
}
|
||
|
|
||
|
inline
|
||
|
Value::operator double() const
|
||
|
{
|
||
|
return get<double>();
|
||
|
}
|
||
|
|
||
|
|
||
|
inline Value::Value(bool val)
|
||
|
try
|
||
|
: common::Value(val)
|
||
|
{}
|
||
|
CATCH_AND_WRAP
|
||
|
|
||
|
|
||
|
template<>
|
||
|
inline
|
||
|
bool Value::get<bool>() const
|
||
|
{
|
||
|
try {
|
||
|
return get_bool();
|
||
|
}
|
||
|
CATCH_AND_WRAP
|
||
|
}
|
||
|
|
||
|
inline
|
||
|
Value::operator bool() const
|
||
|
{
|
||
|
return get<bool>();
|
||
|
}
|
||
|
|
||
|
|
||
|
inline Value::Value(const DbDoc &doc)
|
||
|
try
|
||
|
: m_type(DOC)
|
||
|
, m_doc(doc)
|
||
|
{}
|
||
|
CATCH_AND_WRAP
|
||
|
|
||
|
|
||
|
|
||
|
inline Value::Value(const mysqlx::string &val)
|
||
|
try
|
||
|
: common::Value(val)
|
||
|
{}
|
||
|
CATCH_AND_WRAP
|
||
|
|
||
|
inline Value::Value(mysqlx::string &&val)
|
||
|
try
|
||
|
: common::Value(std::move(val))
|
||
|
{}
|
||
|
CATCH_AND_WRAP
|
||
|
|
||
|
|
||
|
inline Value::Value(const std::string &val)
|
||
|
try
|
||
|
: common::Value(val)
|
||
|
{}
|
||
|
CATCH_AND_WRAP
|
||
|
|
||
|
inline Value::Value(std::string &&val)
|
||
|
try
|
||
|
: common::Value(std::move(val))
|
||
|
{}
|
||
|
CATCH_AND_WRAP
|
||
|
|
||
|
|
||
|
template<>
|
||
|
inline
|
||
|
std::wstring Value::get<std::wstring>() const
|
||
|
{
|
||
|
try {
|
||
|
return mysqlx::string(this->get_ustring());
|
||
|
}
|
||
|
CATCH_AND_WRAP
|
||
|
}
|
||
|
|
||
|
|
||
|
template<>
|
||
|
inline
|
||
|
std::string Value::get<std::string>() const
|
||
|
{
|
||
|
try {
|
||
|
return get_string();
|
||
|
}
|
||
|
CATCH_AND_WRAP
|
||
|
}
|
||
|
|
||
|
inline
|
||
|
Value::operator std::string() const
|
||
|
{
|
||
|
return get<std::string>();
|
||
|
}
|
||
|
|
||
|
|
||
|
template<>
|
||
|
inline
|
||
|
mysqlx::string Value::get<mysqlx::string>() const
|
||
|
{
|
||
|
try {
|
||
|
return this->get_ustring();
|
||
|
}
|
||
|
CATCH_AND_WRAP
|
||
|
}
|
||
|
|
||
|
inline
|
||
|
Value::operator mysqlx::string() const
|
||
|
{
|
||
|
return get<mysqlx::string>();
|
||
|
}
|
||
|
|
||
|
|
||
|
inline Value::Value(const bytes &data)
|
||
|
try
|
||
|
: common::Value(data.begin(), data.length())
|
||
|
{}
|
||
|
CATCH_AND_WRAP
|
||
|
|
||
|
template<>
|
||
|
inline
|
||
|
bytes Value::get<bytes>() const
|
||
|
{
|
||
|
return getRawBytes();
|
||
|
}
|
||
|
|
||
|
inline
|
||
|
Value::operator bytes() const
|
||
|
{
|
||
|
return get<bytes>();
|
||
|
}
|
||
|
|
||
|
|
||
|
template<>
|
||
|
inline
|
||
|
DbDoc Value::get<DbDoc>() const
|
||
|
{
|
||
|
check_type(DOCUMENT);
|
||
|
return m_doc;
|
||
|
}
|
||
|
|
||
|
inline
|
||
|
Value::operator DbDoc() const
|
||
|
{
|
||
|
return get<DbDoc>();
|
||
|
}
|
||
|
|
||
|
|
||
|
inline
|
||
|
bool Value::hasField(const Field &fld) const
|
||
|
{
|
||
|
check_type(DOCUMENT);
|
||
|
return m_doc.hasField(fld);
|
||
|
}
|
||
|
|
||
|
inline
|
||
|
const Value& Value::operator[](const Field &fld) const
|
||
|
{
|
||
|
check_type(DOCUMENT);
|
||
|
return m_doc[fld];
|
||
|
}
|
||
|
|
||
|
inline
|
||
|
int DbDoc::fieldType(const Field &fld) const
|
||
|
{
|
||
|
return (*this)[fld].getType();
|
||
|
}
|
||
|
|
||
|
// Array access
|
||
|
|
||
|
|
||
|
inline
|
||
|
Value::iterator Value::begin()
|
||
|
{
|
||
|
if (ARR != m_type)
|
||
|
throw Error("Attempt to iterate over non-array value");
|
||
|
return m_arr->begin();
|
||
|
}
|
||
|
|
||
|
inline
|
||
|
Value::const_iterator Value::begin() const
|
||
|
{
|
||
|
if (ARR != m_type)
|
||
|
throw Error("Attempt to iterate over non-array value");
|
||
|
return m_arr->begin();
|
||
|
}
|
||
|
|
||
|
inline
|
||
|
Value::iterator Value::end()
|
||
|
{
|
||
|
if (ARR != m_type)
|
||
|
throw Error("Attempt to iterate over non-array value");
|
||
|
return m_arr->end();
|
||
|
}
|
||
|
|
||
|
inline
|
||
|
Value::const_iterator Value::end() const
|
||
|
{
|
||
|
if (ARR != m_type)
|
||
|
throw Error("Attempt to iterate over non-array value");
|
||
|
return m_arr->end();
|
||
|
}
|
||
|
|
||
|
inline
|
||
|
const Value& Value::operator[](unsigned pos) const
|
||
|
{
|
||
|
check_type(ARRAY);
|
||
|
return m_arr->at(pos);
|
||
|
}
|
||
|
|
||
|
inline
|
||
|
size_t Value::elementCount() const
|
||
|
{
|
||
|
check_type(ARRAY);
|
||
|
return m_arr->size();
|
||
|
}
|
||
|
|
||
|
|
||
|
MYSQLX_ABI_END(2,0)
|
||
|
} // mysqlx
|
||
|
|
||
|
|
||
|
#endif
|