mirror of
https://github.com/php/pecl-database-mysql_xdevapi.git
synced 2026-04-26 08:28:11 +02:00
246 lines
5.9 KiB
C++
246 lines
5.9 KiB
C++
/*
|
|
+----------------------------------------------------------------------+
|
|
| PHP Version 7 |
|
|
+----------------------------------------------------------------------+
|
|
| Copyright (c) The PHP Group |
|
|
+----------------------------------------------------------------------+
|
|
| This source file is subject to version 3.01 of the PHP license, |
|
|
| that is bundled with this package in the file LICENSE, and is |
|
|
| available through the world-wide-web at the following url: |
|
|
| http://www.php.net/license/3_01.txt |
|
|
| If you did not receive a copy of the PHP license and are unable to |
|
|
| obtain it through the world-wide-web, please send a note to |
|
|
| license@php.net so we can mail you a copy immediately. |
|
|
+----------------------------------------------------------------------+
|
|
| Authors: Darek Slusarczyk <marines@php.net> |
|
|
+----------------------------------------------------------------------+
|
|
*/
|
|
#include "pb_utils.h"
|
|
#include "exceptions.h"
|
|
#include "mysqlnd_api.h"
|
|
#include "protobuf_api.h"
|
|
#include "xmysqlnd/xmysqlnd_zval2any.h"
|
|
#include "xmysqlnd/proto_gen/mysqlx_crud.pb.h"
|
|
#include "xmysqlnd/proto_gen/mysqlx_sql.pb.h"
|
|
#include "util/value.h"
|
|
|
|
namespace mysqlx {
|
|
|
|
namespace util {
|
|
|
|
namespace pb {
|
|
|
|
using namespace Mysqlx::Datatypes;
|
|
|
|
bool read_variant_64(::google::protobuf::io::CodedInputStream& input_stream, uint64_t* value)
|
|
{
|
|
/*
|
|
fix for protobuf 3.0.0, there is problem with routine:
|
|
|
|
bool CodedInputStream::ReadVarint64(uint64* value)
|
|
|
|
it stores random number in 'value' in case it cannot read next value (e.g. stream is
|
|
at the end)
|
|
it returns 'false' as expected, but in many places we also expected it will NOT
|
|
touch the output 'value'
|
|
|
|
|
|
e.g.
|
|
uint64_t val = INIT_VALUE;
|
|
if (!input_stream.ReadVarint64(&val)) break;
|
|
|
|
in case it returns false in 'val' there may be random number != INIT_VALUE, while we
|
|
would expect it will be not touched, and still INIT_VALUE
|
|
|
|
it may cause severe problems, besides valgrind treats such values as uninitialized
|
|
hence this helper routine to wrap CodedInputStream::ReadVarint64
|
|
|
|
btw behaviour met on both Linux/Win x64, doesn't occur on Win32
|
|
*/
|
|
uint64_t tmp;
|
|
if (input_stream.ReadVarint64(&tmp)) {
|
|
*value = tmp;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
void to_any(
|
|
std::nullptr_t /*nil*/,
|
|
Any& any)
|
|
{
|
|
any.set_type(Any_Type_SCALAR);
|
|
any.mutable_scalar()->set_type(Scalar_Type_V_NULL);
|
|
}
|
|
|
|
void to_any(
|
|
bool value,
|
|
Any& any)
|
|
{
|
|
any.set_type(Any_Type_SCALAR);
|
|
any.mutable_scalar()->set_type(Scalar_Type_V_BOOL);
|
|
any.mutable_scalar()->set_v_bool(value);
|
|
}
|
|
|
|
void to_any(
|
|
int value,
|
|
Any& any)
|
|
{
|
|
any.set_type(Any_Type_SCALAR);
|
|
any.mutable_scalar()->set_type(Scalar_Type_V_SINT);
|
|
any.mutable_scalar()->set_v_signed_int(value);
|
|
}
|
|
|
|
void to_any(
|
|
long value,
|
|
Any& any)
|
|
{
|
|
any.set_type(Any_Type_SCALAR);
|
|
any.mutable_scalar()->set_type(Scalar_Type_V_SINT);
|
|
any.mutable_scalar()->set_v_signed_int(value);
|
|
}
|
|
|
|
void to_any(
|
|
long long value,
|
|
Any& any)
|
|
{
|
|
any.set_type(Any_Type_SCALAR);
|
|
any.mutable_scalar()->set_type(Scalar_Type_V_SINT);
|
|
any.mutable_scalar()->set_v_signed_int(value);
|
|
}
|
|
|
|
void to_any(
|
|
unsigned int value,
|
|
Any& any)
|
|
{
|
|
any.set_type(Any_Type_SCALAR);
|
|
any.mutable_scalar()->set_type(Scalar_Type_V_UINT);
|
|
any.mutable_scalar()->set_v_unsigned_int(value);
|
|
}
|
|
|
|
void to_any(
|
|
unsigned long value,
|
|
Any& any)
|
|
{
|
|
any.set_type(Any_Type_SCALAR);
|
|
any.mutable_scalar()->set_type(Scalar_Type_V_UINT);
|
|
any.mutable_scalar()->set_v_unsigned_int(value);
|
|
}
|
|
|
|
void to_any(
|
|
unsigned long long value,
|
|
Any& any)
|
|
{
|
|
any.set_type(Any_Type_SCALAR);
|
|
any.mutable_scalar()->set_type(Scalar_Type_V_UINT);
|
|
any.mutable_scalar()->set_v_unsigned_int(value);
|
|
}
|
|
|
|
void to_any(
|
|
float value,
|
|
Any& any)
|
|
{
|
|
any.set_type(Any_Type_SCALAR);
|
|
any.mutable_scalar()->set_type(Scalar_Type_V_FLOAT);
|
|
any.mutable_scalar()->set_v_float(value);
|
|
}
|
|
|
|
void to_any(
|
|
double value,
|
|
Any& any)
|
|
{
|
|
any.set_type(Any_Type_SCALAR);
|
|
any.mutable_scalar()->set_type(Scalar_Type_V_DOUBLE);
|
|
any.mutable_scalar()->set_v_double(value);
|
|
}
|
|
|
|
void to_any(
|
|
const char* str,
|
|
const size_t length,
|
|
Any& any)
|
|
{
|
|
any.set_type(Any_Type_SCALAR);
|
|
any.mutable_scalar()->set_type(Scalar_Type_V_STRING);
|
|
any.mutable_scalar()->mutable_v_string()->set_value(str, length);
|
|
}
|
|
|
|
void to_any(
|
|
const std::string& value,
|
|
Any& any)
|
|
{
|
|
to_any(value.c_str(), value.length(), any);
|
|
}
|
|
|
|
void to_any(
|
|
const util::string& value,
|
|
Any& any)
|
|
{
|
|
to_any(value.c_str(), value.length(), any);
|
|
}
|
|
|
|
void to_any(
|
|
const util::string_view& value,
|
|
Any& any)
|
|
{
|
|
to_any(value.data(), value.length(), any);
|
|
}
|
|
|
|
void to_any(
|
|
const util::zvalue& zv,
|
|
Any& any)
|
|
{
|
|
drv::zval2any(zv, any);
|
|
}
|
|
|
|
void to_any(
|
|
Object* value,
|
|
Any& any)
|
|
{
|
|
any.set_type(Any_Type_OBJECT);
|
|
any.set_allocated_obj(value);
|
|
}
|
|
|
|
void to_any(
|
|
Array* value,
|
|
Any& any)
|
|
{
|
|
any.set_type(Any_Type_ARRAY);
|
|
any.set_allocated_array(value);
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
Object* add_object_arg(Mysqlx::Sql::StmtExecute& stmt_message)
|
|
{
|
|
Any* stmt_arg{stmt_message.add_args()};
|
|
stmt_arg->set_type(Any_Type_OBJECT);
|
|
return stmt_arg->mutable_obj();
|
|
}
|
|
|
|
Array* add_array_arg(Mysqlx::Sql::StmtExecute& stmt_message)
|
|
{
|
|
Any* stmt_arg{stmt_message.add_args()};
|
|
stmt_arg->set_type(Any_Type_ARRAY);
|
|
return stmt_arg->mutable_array();
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
void verify_limit_offset(const Mysqlx::Crud::Find& message)
|
|
{
|
|
if (!message.has_limit()) return;
|
|
|
|
const Mysqlx::Crud::Limit& limit{ message.limit() };
|
|
if (!limit.has_row_count() && limit.has_offset()) {
|
|
throw util::xdevapi_exception(util::xdevapi_exception::Code::offset_without_limit_not_allowed);
|
|
}
|
|
}
|
|
|
|
} // namespace pb
|
|
|
|
} // namespace util
|
|
|
|
} // namespace mysqlx
|