mysql5/mysql-5.7.27/rapid/unittest/gunit/xplugin/update_statement_builder_t.cc

858 lines
30 KiB
C++

/*
* Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; version 2 of the License.
*
* 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 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
*/
#include "update_statement_builder.h"
#include "mysqld_error.h"
#include "ngs_common/protocol_protobuf.h"
#include <gtest/gtest.h>
namespace xpl
{
namespace test
{
class Update_statement_builder_impl: public Update_statement_builder
{
public:
Update_statement_builder_impl(Expression_generator &gen) : Update_statement_builder(gen) {}
using Update_statement_builder::add_operation;
using Update_statement_builder::add_table_operation;
using Update_statement_builder::add_document_operation;
using Update_statement_builder::add_document_operation_item;
using Update_statement_builder::Operation_list;
using Update_statement_builder::Operation_item;
using Update_statement_builder::Generator;
};
class Update_statement_builder_test : public ::testing::Test
{
public:
Update_statement_builder_test()
: args(*msg.mutable_args()),
expr_gen(query, args, schema, true),
builder(expr_gen),
oper(-1)
{}
Update_statement_builder::Update msg;
Expression_generator::Args &args;
Query_string_builder query;
std::string schema;
Expression_generator expr_gen;
Update_statement_builder_impl builder;
int oper;
enum {DM_DOCUMENT = 0, DM_TABLE = 1};
typedef ::Mysqlx::Crud::UpdateOperation UpdateOperation;
};
namespace
{
void operator<< (::google::protobuf::Message &msg, const std::string& txt)
{
ASSERT_TRUE(::google::protobuf::TextFormat::ParseFromString(txt, &msg));
}
const std::string value_ = "value: {type: LITERAL literal {type: ";
const std::string value_1 = value_ + "V_DOUBLE v_double: 1.0}}";
const std::string value_2 = value_ + "V_STRING v_string: {value: 'two'}}}";
const std::string value_3 = value_ + "V_SINT v_signed_int: -3}}";
const std::string placeholder_0 = "value: {type: PLACEHOLDER position: 0}";
} // namespace
TEST_F(Update_statement_builder_test, add_operation_empty_list)
{
Update_statement_builder_impl::Operation_list operation;
EXPECT_THROW(builder.add_operation(operation, DM_TABLE), ngs::Error_code);
}
TEST_F(Update_statement_builder_test, add_table_operation_one_item)
{
Update_statement_builder_impl::Operation_list operation;
*operation.Add() << "source {name: 'xfield'}"
"operation: SET " + value_1;
EXPECT_NO_THROW(builder.add_table_operation(operation));
EXPECT_EQ("`xfield`=1", query.get());
}
TEST_F(Update_statement_builder_test, add_table_operation_two_items)
{
Update_statement_builder_impl::Operation_list operation;
*operation.Add() << "source {name: 'xfield'}"
"operation: SET " + value_1;;
*operation.Add() << "source {name: 'yfield'}"
"operation: SET " + value_2;
EXPECT_NO_THROW(builder.add_table_operation(operation));
EXPECT_EQ("`xfield`=1,`yfield`='two'", query.get());
}
TEST_F(Update_statement_builder_test, add_table_operation_two_items_same_source)
{
Update_statement_builder_impl::Operation_list operation;
*operation.Add() << "source {name: 'xfield'}"
"operation: SET " + value_1;;
*operation.Add() << "source {name: 'xfield'}"
"operation: SET " + value_2;
EXPECT_NO_THROW(builder.add_table_operation(operation));
EXPECT_EQ("`xfield`=1,`xfield`='two'", query.get());
}
TEST_F(Update_statement_builder_test, add_table_operation_two_items_placeholder)
{
*args.Add() << "type: V_DOUBLE v_double: 2.2";
Update_statement_builder_impl::Operation_list operation;
*operation.Add() << "source {name: 'xfield'}"
"operation: SET " + value_1;;
*operation.Add() << "source {name: 'yfield'}"
"operation: SET " + placeholder_0;
EXPECT_NO_THROW(builder.add_table_operation(operation));
EXPECT_EQ("`xfield`=1,`yfield`=2.2", query.get());
}
TEST_F(Update_statement_builder_test, add_table_operation_empty_name)
{
Update_statement_builder_impl::Operation_list operation;
*operation.Add() << "source {} operation: SET " + value_1;;
EXPECT_THROW(builder.add_table_operation(operation), ngs::Error_code);
}
TEST_F(Update_statement_builder_test, add_table_operation_item_name_with_table)
{
Update_statement_builder_impl::Operation_list operation;
*operation.Add() << "source {name: 'xfield' table_name: 'xtable'}"
"operation: SET " + value_1;
EXPECT_THROW(builder.add_table_operation(operation), ngs::Error_code);
}
TEST_F(Update_statement_builder_test, add_table_operation_item_name_with_table_and_schema)
{
Update_statement_builder_impl::Operation_list operation;
*operation.Add() << "source {name: 'xfield' table_name: 'xtable' schema_name: 'xschema'}"
"operation: SET " + value_1;
EXPECT_THROW(builder.add_table_operation(operation), ngs::Error_code);
}
TEST_F(Update_statement_builder_test, add_operation_one_item_for_table)
{
Update_statement_builder_impl::Operation_list operation;
*operation.Add() << "source {name: 'xfield'}"
"operation: SET " + value_1;
EXPECT_NO_THROW(builder.add_operation(operation, DM_TABLE));
EXPECT_EQ(" SET `xfield`=1", query.get());
}
namespace
{
const std::string table_full_message(
"collection {name: 'xtable' schema: 'xschema'}"
"data_model: TABLE "
"operation {source {name: 'yfield'}"
" operation: SET"
" value {type: LITERAL literal {type: V_OCTETS"
" v_octets {value: 'booom'}}}}"
"criteria {type: OPERATOR "
" operator {name: '>' "
" param {type: IDENT identifier {name: 'xfield'}}"
" param {type: LITERAL literal {type: V_DOUBLE"
" v_double: 1.0}}}}"
"order {expr {type: IDENT identifier {name: 'xfield'}}"
" direction: DESC}");
} // namespace
TEST_F(Update_statement_builder_test, build_update_for_table)
{
msg << table_full_message + "limit {row_count: 2}";
EXPECT_NO_THROW(builder.build(msg));
EXPECT_EQ("UPDATE `xschema`.`xtable`"
" SET `yfield`='booom'"
" WHERE (`xfield` > 1)"
" ORDER BY `xfield` DESC"
" LIMIT 2", query.get());
}
TEST_F(Update_statement_builder_test, build_update_for_table_forrbiden_offset_in_limit)
{
msg << table_full_message + "limit {row_count: 2 offset: 5}";
EXPECT_THROW(builder.build(msg), ngs::Error_code);
}
namespace
{
const std::string source_ = "source {document_path {type: MEMBER value: ";
const std::string source_index_ = "source {document_path {type: ARRAY_INDEX index: ";
const std::string source_first = source_ + "'first'}}";
const std::string source_second = source_ + "'second'}}";
const std::string source_third = source_ + "'third'}}";
const std::string source_index_first_0 = source_ + "'first'} document_path {type:ARRAY_INDEX index: 0}}";
const std::string source_index_0 = source_index_ + " 0}}";
const std::string source_index_1 = source_index_ + " 1}}";
const std::string document_full_message(
"collection {name: 'xtable' schema: 'xschema'}"
"data_model: DOCUMENT "
"operation {source {document_path {type: MEMBER value: 'first'}}"
" operation: ITEM_SET"
" value: {type: LITERAL literal {type: V_DOUBLE v_double: 1.0}}}"
"criteria {type: OPERATOR "
" operator {name: '>' "
" param {type: IDENT identifier {document_path {type: MEMBER value: 'second'}}}"
" param {type: LITERAL literal {type: V_DOUBLE"
" v_double: 1.0}}}}"
"order {expr {type: IDENT identifier {document_path {type: MEMBER value: 'third'}}}"
" direction: DESC}");
} // namespace
TEST_F(Update_statement_builder_test, add_document_operation_not_allowed_set)
{
Update_statement_builder_impl::Operation_list operation;
*operation.Add() << source_first + "operation: SET " + value_1;
EXPECT_THROW(builder.add_document_operation(operation), ngs::Error_code);
}
TEST_F(Update_statement_builder_test, add_document_operation_remove)
{
Update_statement_builder_impl::Operation_list operation;
*operation.Add() << source_first + "operation: ITEM_REMOVE ";
EXPECT_NO_THROW(builder.add_document_operation(operation));
EXPECT_EQ("doc=JSON_REMOVE(doc,'$.first')", query.get());
}
TEST_F(Update_statement_builder_test, add_document_operation_set)
{
Update_statement_builder_impl::Operation_list operation;
*operation.Add() << source_first + "operation: ITEM_SET " + value_1;
EXPECT_NO_THROW(builder.add_document_operation(operation));
EXPECT_EQ("doc=JSON_SET(doc,'$.first',1)",
query.get());
}
TEST_F(Update_statement_builder_test, add_document_operation_replace)
{
Update_statement_builder_impl::Operation_list operation;
*operation.Add() << source_first + "operation: ITEM_REPLACE " + value_1;
EXPECT_NO_THROW(builder.add_document_operation(operation));
EXPECT_EQ("doc=JSON_REPLACE(doc,'$.first',1)",
query.get());
}
TEST_F(Update_statement_builder_test, add_document_operation_merge)
{
Update_statement_builder_impl::Operation_list operation;
*operation.Add() << source_first +
"operation: ITEM_MERGE "
"value {type: LITERAL literal {type: V_OCTETS v_octets {value: '{\\\"two\\\": 2.0}'}}}";
ASSERT_NO_THROW(builder.add_document_operation(operation));
EXPECT_EQ(
"doc=JSON_MERGE(doc,IF(JSON_TYPE('{\\\"two\\\": 2.0}')='OBJECT',"
"JSON_REMOVE('{\\\"two\\\": 2.0}','$._id'),'_ERROR_'))",
query.get());
}
TEST_F(Update_statement_builder_test, add_document_operation_array_insert)
{
Update_statement_builder_impl::Operation_list operation;
*operation.Add() << source_index_first_0 + "operation: ARRAY_INSERT " + value_1;
EXPECT_NO_THROW(builder.add_document_operation(operation));
EXPECT_EQ("doc=JSON_ARRAY_INSERT(doc,'$.first[0]',1)",
query.get());
}
TEST_F(Update_statement_builder_test, add_document_operation_array_append)
{
Update_statement_builder_impl::Operation_list operation;
*operation.Add() << source_first + "operation: ARRAY_APPEND " + value_1;
EXPECT_NO_THROW(builder.add_document_operation(operation));
EXPECT_EQ("doc=JSON_ARRAY_APPEND(doc,'$.first',1)",
query.get());
}
TEST_F(Update_statement_builder_test, add_document_operation_array_append_twice)
{
Update_statement_builder_impl::Operation_list operation;
*operation.Add() << source_first + "operation: ARRAY_APPEND " + value_1;
*operation.Add() << source_first + "operation: ARRAY_APPEND " + value_2;
EXPECT_NO_THROW(builder.add_document_operation(operation));
EXPECT_EQ("doc=JSON_ARRAY_APPEND(doc,'$.first',1,'$.first','two')",
query.get());
}
TEST_F(Update_statement_builder_test, add_document_operation_remove_twice)
{
Update_statement_builder_impl::Operation_list operation;
*operation.Add() << source_first + "operation: ITEM_REMOVE ";
*operation.Add() << source_second + "operation: ITEM_REMOVE ";
EXPECT_NO_THROW(builder.add_document_operation(operation));
EXPECT_EQ("doc=JSON_REMOVE(doc,'$.first','$.second')",
query.get());
}
TEST_F(Update_statement_builder_test, add_document_operation_set_twice)
{
Update_statement_builder_impl::Operation_list operation;
*operation.Add() << source_first + "operation: ITEM_SET " + value_1;
*operation.Add() << source_second + "operation: ITEM_SET " + value_2;
EXPECT_NO_THROW(builder.add_document_operation(operation));
EXPECT_EQ("doc=JSON_SET(doc,'$.first',1,'$.second','two')",
query.get());
}
TEST_F(Update_statement_builder_test, add_document_operation_set_twice_placeholder)
{
*args.Add() << "type: V_DOUBLE v_double: 2.2";
*args.Add() << "type: V_OCTETS v_octets {value: '$.second'}";
Update_statement_builder_impl::Operation_list operation;
*operation.Add() << source_first + "operation: ITEM_SET " + value_1;
*operation.Add() << source_second + "operation: ITEM_SET " + placeholder_0;
EXPECT_NO_THROW(builder.add_document_operation(operation));
EXPECT_EQ("doc=JSON_SET(doc,'$.first',1,'$.second',2.2)",
query.get());
}
TEST_F(Update_statement_builder_test, add_document_operation_merge_twice)
{
Update_statement_builder_impl::Operation_list operation;
*operation.Add() << "source {} operation: ITEM_MERGE "
"value {type: LITERAL literal {type: V_OCTETS v_octets {value: '{\\\"two\\\": 2.0}'}}}";
*operation.Add() << "source {} operation: ITEM_MERGE "
"value {type: LITERAL literal {type: V_OCTETS v_octets {value: '{\\\"three\\\": 3.0}'}}}";
ASSERT_NO_THROW(builder.add_document_operation(operation));
EXPECT_EQ(
"doc=JSON_MERGE(doc,IF(JSON_TYPE('{\\\"two\\\": 2.0}')='OBJECT',"
"JSON_REMOVE('{\\\"two\\\": 2.0}','$._id'),'_ERROR_'),"
"IF(JSON_TYPE('{\\\"three\\\": 3.0}')='OBJECT',"
"JSON_REMOVE('{\\\"three\\\": 3.0}','$._id'),'_ERROR_'))",
query.get());
}
TEST_F(Update_statement_builder_test, add_document_operation_remove_set)
{
Update_statement_builder_impl::Operation_list operation;
*operation.Add() << source_first + "operation: ITEM_REMOVE ";
*operation.Add() << source_second + "operation: ITEM_SET " + value_2;
EXPECT_NO_THROW(builder.add_document_operation(operation));
EXPECT_EQ("doc=JSON_SET(JSON_REMOVE(doc,'$.first'),'$.second','two')",
query.get());
}
TEST_F(Update_statement_builder_test, add_document_operation_remove_twice_set)
{
Update_statement_builder_impl::Operation_list operation;
*operation.Add() << source_first + "operation: ITEM_REMOVE ";
*operation.Add() << source_second + "operation: ITEM_REMOVE ";
*operation.Add() << source_third + "operation: ITEM_SET " + value_3;
EXPECT_NO_THROW(builder.add_document_operation(operation));
EXPECT_EQ("doc=JSON_SET(JSON_REMOVE(doc,'$.first','$.second'),'$.third',-3)",
query.get());
}
TEST_F(Update_statement_builder_test, add_document_operation_set_remove_set)
{
Update_statement_builder_impl::Operation_list operation;
*operation.Add() << source_first + "operation: ITEM_SET " + value_1;
*operation.Add() << source_second + "operation: ITEM_REMOVE ";
*operation.Add() << source_third + "operation: ITEM_SET " + value_3;
EXPECT_NO_THROW(builder.add_document_operation(operation));
EXPECT_EQ("doc=JSON_SET(JSON_REMOVE("
"JSON_SET(doc,'$.first',1),'$.second'),'$.third',-3)",
query.get());
}
TEST_F(Update_statement_builder_test, add_document_operation_set_merge)
{
Update_statement_builder_impl::Operation_list operation;
*operation.Add() << source_first + "operation: ITEM_SET " + value_1;
*operation.Add() << "source {} operation: ITEM_MERGE "
"value {type: LITERAL literal {type: V_OCTETS v_octets {value: '{\\\"three\\\": 3.0}'}}}";
ASSERT_NO_THROW(builder.add_document_operation(operation));
EXPECT_EQ(
"doc=JSON_MERGE(JSON_SET(doc,'$.first',1),"
"IF(JSON_TYPE('{\\\"three\\\": 3.0}')='OBJECT',"
"JSON_REMOVE('{\\\"three\\\": 3.0}','$._id'),'_ERROR_'))",
query.get());
}
TEST_F(Update_statement_builder_test, add_document_operation_item_forbiden_column)
{
Update_statement_builder_impl::Operation_item operation;
operation << "source {name: 'xcolumn'} operation: ITEM_SET " + value_3;
ASSERT_THROW(builder.add_document_operation_item(operation, oper),
ngs::Error_code);
ASSERT_EQ(UpdateOperation::ITEM_SET, oper);
}
TEST_F(Update_statement_builder_test, add_document_operation_item_forbiden_schema)
{
Update_statement_builder_impl::Operation_item operation;
operation << "source {schema_name: 'xschema'} operation: ITEM_SET "
+ value_3;
ASSERT_THROW(builder.add_document_operation_item(operation, oper),
ngs::Error_code);
ASSERT_EQ(UpdateOperation::ITEM_SET, oper);
}
TEST_F(Update_statement_builder_test, add_document_operation_item_forbiden_table)
{
Update_statement_builder_impl::Operation_item operation;
operation << "source {table_name: 'xtable'} operation: ITEM_SET "
+ value_3;
ASSERT_THROW(builder.add_document_operation_item(operation, oper),
ngs::Error_code);
ASSERT_EQ(UpdateOperation::ITEM_SET, oper);
}
TEST_F(Update_statement_builder_test, add_document_operation_item_forbiden_id_change)
{
Update_statement_builder_impl::Operation_item operation;
operation << "source {document_path {type: MEMBER value: '_id'}} operation: ITEM_SET "
+ value_3;
ASSERT_THROW(builder.add_document_operation_item(operation, oper),
ngs::Error_code);
ASSERT_EQ(UpdateOperation::ITEM_SET, oper);
}
TEST_F(Update_statement_builder_test, add_document_operation_item_empty_document_path)
{
Update_statement_builder_impl::Operation_item operation;
operation << "source {} operation: ITEM_SET " + value_3;
ASSERT_THROW(builder.add_document_operation_item(operation, oper),
ngs::Error_code);
ASSERT_EQ(UpdateOperation::ITEM_SET, oper);
}
TEST_F(Update_statement_builder_test, add_document_operation_item_root_path)
{
Update_statement_builder_impl::Operation_item operation;
operation << "source {document_path {type: MEMBER value: ''}} operation: ITEM_SET " + value_3;
ASSERT_NO_THROW(builder.add_document_operation_item(operation, oper));
ASSERT_EQ(UpdateOperation::ITEM_SET, oper);
}
TEST_F(Update_statement_builder_test, add_document_operation_item_empty_member)
{
Update_statement_builder_impl::Operation_item operation;
operation << "source {document_path {type: MEMBER value: 'first'} "
"document_path {type: MEMBER value: ''}} "
"operation: ITEM_SET " + value_3;
ASSERT_THROW(builder.add_document_operation_item(operation, oper),
xpl::Expression_generator::Error);
ASSERT_EQ(UpdateOperation::ITEM_SET, oper);
}
TEST_F(Update_statement_builder_test, add_document_operation_item_empty_member_reverse)
{
Update_statement_builder_impl::Operation_item operation;
operation << "source {document_path {type: MEMBER value: ''} "
"document_path {type: MEMBER value: 'first'}} "
"operation: ITEM_SET " + value_3;
ASSERT_THROW(builder.add_document_operation_item(operation, oper),
xpl::Expression_generator::Error);
ASSERT_EQ(UpdateOperation::ITEM_SET, oper);
}
TEST_F(Update_statement_builder_test, add_document_operation_item_root_as_array)
{
Update_statement_builder_impl::Operation_item operation;
operation << source_index_0 + "operation: ITEM_SET " + value_3;
ASSERT_THROW(builder.add_document_operation_item(operation, oper),
ngs::Error_code);
ASSERT_EQ(UpdateOperation::ITEM_SET, oper);
}
TEST_F(Update_statement_builder_test, add_document_operation_item_root_as_array_asterisk)
{
Update_statement_builder_impl::Operation_item operation;
operation << "source {document_path {type: ARRAY_INDEX_ASTERISK}} "
"operation: ITEM_SET " + value_3;
ASSERT_THROW(builder.add_document_operation_item(operation, oper),
ngs::Error_code);
ASSERT_EQ(UpdateOperation::ITEM_SET, oper);
}
TEST_F(Update_statement_builder_test, add_document_operation_item_root_double_asterisk)
{
Update_statement_builder_impl::Operation_item operation;
operation << "source {document_path {type: DOUBLE_ASTERISK}} "
"operation: ITEM_SET " + value_3;
ASSERT_THROW(builder.add_document_operation_item(operation, oper),
ngs::Error_code);
ASSERT_EQ(UpdateOperation::ITEM_SET, oper);
}
TEST_F(Update_statement_builder_test, add_operation_one_item_for_document)
{
Update_statement_builder_impl::Operation_list operation;
*operation.Add() << source_first + "operation: ITEM_SET " + value_1;
EXPECT_NO_THROW(builder.add_operation(operation, DM_DOCUMENT));
EXPECT_EQ(" SET doc=JSON_SET(doc,'$.first',1)",
query.get());
}
TEST_F(Update_statement_builder_test, build_update_for_document)
{
msg << document_full_message + "limit {row_count: 2}";
EXPECT_NO_THROW(builder.build(msg));
EXPECT_EQ("UPDATE `xschema`.`xtable` "
"SET doc=JSON_SET(doc,'$.first',1) "
"WHERE (JSON_EXTRACT(doc,'$.second') > 1) "
"ORDER BY JSON_EXTRACT(doc,'$.third') "
"DESC LIMIT 2",
query.get());
}
namespace
{
std::string get_operation(const std::string &name, const std::string &member,
const std::string &oper, const std::string &value)
{
std::string str("source {");
if (!name.empty())
str += "name: '" + name + "' ";
if (!member.empty())
{
str += "document_path {type: ";
if (isdigit(member[0]))
{
str += "ARRAY_INDEX index: " + member;
}
else
{
str += "MEMBER ";
if (member != "$")
str += "value: '" + member + "' ";
}
str += "}";
}
str += "} operation: " + oper;
if (!value.empty())
str += " " + value;
return str;
}
} // namespace
TEST_F(Update_statement_builder_test, add_document_operation_set_whole_doc)
{
Update_statement_builder_impl::Operation_list operation;
*operation.Add() << get_operation("", "$", "ITEM_SET", value_2);
EXPECT_NO_THROW(builder.add_document_operation(operation));
EXPECT_EQ("doc=JSON_SET(doc,'$','two')",
query.get());
}
TEST_F(Update_statement_builder_test, add_table_operation_set_needless_doc_path)
{
Update_statement_builder_impl::Operation_list operation;
*operation.Add() << get_operation("xfield", "first", "SET", value_1);
EXPECT_THROW(builder.add_table_operation(operation), ngs::Error_code);
}
TEST_F(Update_statement_builder_test, add_table_operation_item_set_missing_doc_path)
{
Update_statement_builder_impl::Operation_list operation;
*operation.Add() << get_operation("xfield", "", "ITEM_SET", value_1);
EXPECT_THROW(builder.add_table_operation(operation), ngs::Error_code);
}
TEST_F(Update_statement_builder_test, add_table_operation_item_set)
{
Update_statement_builder_impl::Operation_list operation;
*operation.Add() << get_operation("xfield", "first", "ITEM_SET", value_1);
ASSERT_NO_THROW(builder.add_table_operation(operation));
EXPECT_EQ("`xfield`=JSON_SET(`xfield`,'$.first',1)",
query.get());
}
TEST_F(Update_statement_builder_test, add_table_operation_item_set_twice)
{
Update_statement_builder_impl::Operation_list operation;
*operation.Add() << get_operation("xfield", "first", "ITEM_SET", value_1);
*operation.Add() << get_operation("xfield", "second", "ITEM_SET", value_2);
ASSERT_NO_THROW(builder.add_table_operation(operation));
EXPECT_EQ(
"`xfield`=JSON_SET(`xfield`,'$.first',1,'$.second','two')",
query.get());
}
TEST_F(Update_statement_builder_test, add_table_operation_item_set_twice_but_different)
{
Update_statement_builder_impl::Operation_list operation;
*operation.Add() << get_operation("xfield", "first", "ITEM_SET", value_1);
*operation.Add() << get_operation("yfield", "second", "ITEM_SET", value_2);
ASSERT_NO_THROW(builder.add_table_operation(operation));
EXPECT_EQ(
"`xfield`=JSON_SET(`xfield`,'$.first',1),"
"`yfield`=JSON_SET(`yfield`,'$.second','two')",
query.get());
}
TEST_F(Update_statement_builder_test, add_table_operation_item_set_triple)
{
Update_statement_builder_impl::Operation_list operation;
*operation.Add() << get_operation("xfield", "first", "ITEM_SET", value_1);
*operation.Add() << get_operation("xfield", "second", "ITEM_SET", value_2);
*operation.Add() << get_operation("xfield", "third", "ITEM_SET", value_3);
ASSERT_NO_THROW(builder.add_table_operation(operation));
EXPECT_EQ(
"`xfield`=JSON_SET(`xfield`,'$.first',1,'$.second','two','$.third',-3)",
query.get());
}
TEST_F(Update_statement_builder_test, add_table_operation_item_set_mix_first)
{
Update_statement_builder_impl::Operation_list operation;
*operation.Add() << get_operation("xfield", "", "SET", value_1);
*operation.Add() << get_operation("xfield", "second", "ITEM_SET", value_2);
*operation.Add() << get_operation("xfield", "third", "ITEM_SET", value_3);
ASSERT_NO_THROW(builder.add_table_operation(operation));
EXPECT_EQ(
"`xfield`=1,"
"`xfield`=JSON_SET(`xfield`,'$.second','two','$.third',-3)",
query.get());
}
TEST_F(Update_statement_builder_test, add_table_operation_item_set_mix_last)
{
Update_statement_builder_impl::Operation_list operation;
*operation.Add() << get_operation("xfield", "second", "ITEM_SET", value_2);
*operation.Add() << get_operation("xfield", "third", "ITEM_SET", value_3);
*operation.Add() << get_operation("xfield", "", "SET", value_1);
ASSERT_NO_THROW(builder.add_table_operation(operation));
EXPECT_EQ(
"`xfield`=JSON_SET(`xfield`,'$.second','two','$.third',-3),"
"`xfield`=1",
query.get());
}
TEST_F(Update_statement_builder_test, add_table_operation_item_set_mix_middle)
{
Update_statement_builder_impl::Operation_list operation;
*operation.Add() << get_operation("xfield", "second", "ITEM_SET", value_2);
*operation.Add() << get_operation("xfield", "", "SET", value_1);
*operation.Add() << get_operation("xfield", "third", "ITEM_SET", value_3);
ASSERT_NO_THROW(builder.add_table_operation(operation));
EXPECT_EQ(
"`xfield`=JSON_SET(`xfield`,'$.second','two'),"
"`xfield`=1,"
"`xfield`=JSON_SET(`xfield`,'$.third',-3)",
query.get());
}
TEST_F(Update_statement_builder_test, add_table_operation_item_set_fourth)
{
Update_statement_builder_impl::Operation_list operation;
*operation.Add() << get_operation("xfield", "first", "ITEM_SET", value_1);
*operation.Add() << get_operation("xfield", "second", "ITEM_SET", value_2);
*operation.Add() << get_operation("yfield", "first", "ITEM_SET", value_1);
*operation.Add() << get_operation("yfield", "second", "ITEM_SET", value_2);
ASSERT_NO_THROW(builder.add_table_operation(operation));
EXPECT_EQ(
"`xfield`=JSON_SET(`xfield`,'$.first',1,'$.second','two'),"
"`yfield`=JSON_SET(`yfield`,'$.first',1,'$.second','two')",
query.get());
}
TEST_F(Update_statement_builder_test, add_table_operation_item_remove_one)
{
Update_statement_builder_impl::Operation_list operation;
*operation.Add() << get_operation("xfield", "first", "ITEM_REMOVE", "");
ASSERT_NO_THROW(builder.add_table_operation(operation));
EXPECT_EQ(
"`xfield`=JSON_REMOVE(`xfield`,'$.first')",
query.get());
}
TEST_F(Update_statement_builder_test, add_table_operation_item_remove_twice)
{
Update_statement_builder_impl::Operation_list operation;
*operation.Add() << get_operation("xfield", "first", "ITEM_REMOVE", "");
*operation.Add() << get_operation("xfield", "second", "ITEM_REMOVE", "");
ASSERT_NO_THROW(builder.add_table_operation(operation));
EXPECT_EQ(
"`xfield`=JSON_REMOVE(`xfield`,'$.first','$.second')",
query.get());
}
TEST_F(Update_statement_builder_test, add_table_operation_item_replace_one)
{
Update_statement_builder_impl::Operation_list operation;
*operation.Add() << get_operation("xfield", "first", "ITEM_REPLACE", value_1);
ASSERT_NO_THROW(builder.add_table_operation(operation));
EXPECT_EQ(
"`xfield`=JSON_REPLACE(`xfield`,'$.first',1)",
query.get());
}
TEST_F(Update_statement_builder_test, add_table_operation_item_replace_twice)
{
Update_statement_builder_impl::Operation_list operation;
*operation.Add() << get_operation("xfield", "first", "ITEM_REPLACE", value_1);
*operation.Add() << get_operation("xfield", "second", "ITEM_REPLACE", value_2);
ASSERT_NO_THROW(builder.add_table_operation(operation));
EXPECT_EQ(
"`xfield`=JSON_REPLACE(`xfield`,'$.first',1,'$.second','two')",
query.get());
}
TEST_F(Update_statement_builder_test, add_table_operation_item_merge_one)
{
Update_statement_builder_impl::Operation_list operation;
*operation.Add() << get_operation("xfield", "first", "ITEM_MERGE", value_1);
ASSERT_NO_THROW(builder.add_table_operation(operation));
EXPECT_EQ(
"`xfield`=JSON_MERGE(`xfield`,1)",
query.get());
}
TEST_F(Update_statement_builder_test, add_table_operation_item_merge_twice)
{
Update_statement_builder_impl::Operation_list operation;
*operation.Add() << get_operation("xfield", "first", "ITEM_MERGE", value_1);
*operation.Add() << get_operation("xfield", "second", "ITEM_MERGE", value_2);
ASSERT_NO_THROW(builder.add_table_operation(operation));
EXPECT_EQ(
"`xfield`=JSON_MERGE(`xfield`,1,'two')",
query.get());
}
TEST_F(Update_statement_builder_test, add_table_operation_array_insert_one)
{
Update_statement_builder_impl::Operation_list operation;
*operation.Add() << get_operation("xfield", "0", "ARRAY_INSERT", value_1);
ASSERT_NO_THROW(builder.add_table_operation(operation));
EXPECT_EQ(
"`xfield`=JSON_ARRAY_INSERT(`xfield`,'$[0]',1)",
query.get());
}
TEST_F(Update_statement_builder_test, add_table_operation_array_insert_twice)
{
Update_statement_builder_impl::Operation_list operation;
*operation.Add() << get_operation("xfield", "0", "ARRAY_INSERT", value_1);
*operation.Add() << get_operation("xfield", "1", "ARRAY_INSERT", value_2);
ASSERT_NO_THROW(builder.add_table_operation(operation));
EXPECT_EQ(
"`xfield`=JSON_ARRAY_INSERT(`xfield`,'$[0]',1,'$[1]','two')",
query.get());
}
TEST_F(Update_statement_builder_test, add_table_operation_array_append_one)
{
Update_statement_builder_impl::Operation_list operation;
*operation.Add() << get_operation("xfield", "first", "ARRAY_APPEND", value_1);
ASSERT_NO_THROW(builder.add_table_operation(operation));
EXPECT_EQ(
"`xfield`=JSON_ARRAY_APPEND(`xfield`,'$.first',1)",
query.get());
}
TEST_F(Update_statement_builder_test, add_table_operation_array_append_twice)
{
Update_statement_builder_impl::Operation_list operation;
*operation.Add() << get_operation("xfield", "first", "ARRAY_APPEND", value_1);
*operation.Add() << get_operation("xfield", "second", "ARRAY_APPEND", value_2);
ASSERT_NO_THROW(builder.add_table_operation(operation));
EXPECT_EQ(
"`xfield`=JSON_ARRAY_APPEND(`xfield`,'$.first',1,'$.second','two')",
query.get());
}
TEST_F(Update_statement_builder_test, add_table_operation_array_append_twice_placeholder)
{
*args.Add() << "type: V_DOUBLE v_double: 2.2";
Update_statement_builder_impl::Operation_list operation;
*operation.Add() << get_operation("xfield", "first", "ARRAY_APPEND", value_1);
*operation.Add() << get_operation("xfield", "second", "ARRAY_APPEND", placeholder_0);
ASSERT_NO_THROW(builder.add_table_operation(operation));
EXPECT_EQ(
"`xfield`=JSON_ARRAY_APPEND(`xfield`,'$.first',1,'$.second',2.2)",
query.get());
}
} // namespace test
} // namespace xpl