polardbxengine/unittest/gunit/xplugin/xpl/update_statement_builder_t.cc

756 lines
31 KiB
C++

/*
* Copyright (c) 2015, 2018, 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, 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.
*
* 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
*/
#include <gtest/gtest.h>
#include "mysqld_error.h"
#include "plugin/x/src/update_statement_builder.h"
#include "unittest/gunit/xplugin/xpl/mysqlx_pb_wrapper.h"
namespace xpl {
namespace test {
class Update_statement_builder_stub : public Update_statement_builder {
public:
explicit Update_statement_builder_stub(Expression_generator *gen)
: Update_statement_builder(*gen) {}
using Update_statement_builder::add_document_operation;
using Update_statement_builder::add_document_operation_item;
using Update_statement_builder::add_operation;
using Update_statement_builder::add_table_operation;
using Update_statement_builder::Operation_list;
};
class Update_statement_builder_test : public ::testing::Test {
public:
Update_statement_builder_stub &builder() {
expr_gen.reset(new Expression_generator(&query, args, schema,
is_table_data_model(msg)));
stub.reset(new Update_statement_builder_stub(expr_gen.get()));
return *stub;
}
Update_statement_builder::Update msg;
Expression_generator::Arg_list &args = *msg.mutable_args();
Query_string_builder query;
std::string schema;
std::unique_ptr<Expression_generator> expr_gen;
std::unique_ptr<Update_statement_builder_stub> stub;
Update_operation::Update_type operation_id =
Update_operation::Base::ITEM_REMOVE;
enum { DM_DOCUMENT = 0, DM_TABLE = 1 };
void fill_table_msg(const Limit &limit) {
msg = Update({"xtable", "xschema"}, Mysqlx::Crud::TABLE)
.operation({Update_operation::Base::SET,
Column_identifier{"yfield"}, Scalar{"booom"}})
.criteria(Operator(">", Column_identifier{"xfield"}, Scalar{1.0}))
.order({Column_identifier("xfield"), Order::Base::DESC})
.limit(limit);
}
}; // namespace test
TEST_F(Update_statement_builder_test, add_operation_empty_list) {
EXPECT_THROW(builder().add_operation(Operation_list(), DM_TABLE),
ngs::Error_code);
}
TEST_F(Update_statement_builder_test, add_table_operation_one_item) {
EXPECT_NO_THROW(builder().add_table_operation(
Operation_list{{Update_operation::Base::SET, Column_identifier("xfield"),
Scalar(1.0)}}));
EXPECT_STREQ("`xfield`=1", query.get().c_str());
}
TEST_F(Update_statement_builder_test, add_table_operation_two_items) {
EXPECT_NO_THROW(builder().add_table_operation(Operation_list{
{Update_operation::Base::SET, Column_identifier("xfield"), Scalar(1.0)},
{Update_operation::Base::SET, Column_identifier("yfield"),
Scalar("two")}}));
EXPECT_STREQ("`xfield`=1,`yfield`='two'", query.get().c_str());
}
TEST_F(Update_statement_builder_test,
add_table_operation_two_items_same_source) {
EXPECT_NO_THROW(builder().add_table_operation(Operation_list{
{Update_operation::Base::SET, Column_identifier("xfield"), Scalar(1.0)},
{Update_operation::Base::SET, Column_identifier("xfield"),
Scalar("two")}}));
EXPECT_STREQ("`xfield`=1,`xfield`='two'", query.get().c_str());
}
TEST_F(Update_statement_builder_test,
add_table_operation_two_items_placeholder) {
args = Expression_list{2.2};
EXPECT_NO_THROW(builder().add_table_operation(Operation_list{
{Update_operation::Base::SET, Column_identifier("xfield"), Scalar(1.0)},
{Update_operation::Base::SET, Column_identifier("yfield"),
Placeholder(0)}}));
EXPECT_STREQ("`xfield`=1,`yfield`=2.2", query.get().c_str());
}
TEST_F(Update_statement_builder_test, add_table_operation_empty_name) {
EXPECT_THROW(
builder().add_table_operation(Operation_list{
{Update_operation::Base::SET, Column_identifier(""), Scalar(1.0)}}),
ngs::Error_code);
}
TEST_F(Update_statement_builder_test,
add_table_operation_item_name_with_table) {
EXPECT_THROW(builder().add_table_operation(Operation_list{
{Update_operation::Base::SET,
Column_identifier("xfield", "xtable"), Scalar(1.0)}}),
ngs::Error_code);
}
TEST_F(Update_statement_builder_test,
add_table_operation_item_name_with_table_and_schema) {
EXPECT_THROW(
builder().add_table_operation(Operation_list{
{Update_operation::Base::SET,
Column_identifier("xfield", "xtable", "xschema"), Scalar(1.0)}}),
ngs::Error_code);
}
TEST_F(Update_statement_builder_test, add_operation_one_item_for_table) {
EXPECT_NO_THROW(builder().add_operation(
Operation_list{{Update_operation::Base::SET, Column_identifier("xfield"),
Scalar(1.0)}},
DM_TABLE));
EXPECT_STREQ(" SET `xfield`=1", query.get().c_str());
}
TEST_F(Update_statement_builder_test, build_update_for_table) {
fill_table_msg(Limit(2));
EXPECT_NO_THROW(builder().build(msg));
EXPECT_STREQ(
"UPDATE `xschema`.`xtable`"
" SET `yfield`='booom'"
" WHERE (`xfield` > 1)"
" ORDER BY `xfield` DESC"
" LIMIT 2",
query.get().c_str());
}
TEST_F(Update_statement_builder_test,
build_update_for_table_forrbiden_offset_in_limit) {
fill_table_msg(Limit(2, 5));
EXPECT_THROW(builder().build(msg), ngs::Error_code);
}
TEST_F(Update_statement_builder_test, add_document_operation_not_allowed_set) {
EXPECT_THROW(
builder().add_document_operation(Operation_list{
{Update_operation::Base::SET, Document_path{"first"}, Scalar(1.0)}}),
ngs::Error_code);
}
TEST_F(Update_statement_builder_test, add_document_operation_remove) {
EXPECT_NO_THROW(builder().add_document_operation(Operation_list{
{Update_operation::Base::ITEM_REMOVE, Document_path{"first"}}}));
EXPECT_STREQ(
"doc=JSON_SET(JSON_REMOVE(doc,'$.first'),'$._id',"
"JSON_EXTRACT(`doc`,'$._id'))",
query.get().c_str());
}
TEST_F(Update_statement_builder_test, add_document_operation_remove_value) {
EXPECT_THROW(
builder().add_document_operation(Operation_list{
{Update_operation::Base::ITEM_REMOVE, Document_path{"first"}, 666}}),
ngs::Error_code);
}
TEST_F(Update_statement_builder_test, add_document_operation_set) {
EXPECT_NO_THROW(builder().add_document_operation(
Operation_list{{Update_operation::Base::ITEM_SET, Document_path{"first"},
Scalar(1.0)}}));
EXPECT_STREQ(
"doc=JSON_SET(JSON_SET(doc,'$.first',1),'$._id',"
"JSON_EXTRACT(`doc`,'$._id'))",
query.get().c_str());
}
TEST_F(Update_statement_builder_test, add_document_operation_replace) {
EXPECT_NO_THROW(builder().add_document_operation(
Operation_list{{Update_operation::Base::ITEM_REPLACE,
Document_path{"first"}, Scalar(1.0)}}));
EXPECT_STREQ(
"doc=JSON_SET(JSON_REPLACE(doc,'$.first',1),'$._id',"
"JSON_EXTRACT(`doc`,'$._id'))",
query.get().c_str());
}
TEST_F(Update_statement_builder_test, add_document_operation_array_insert) {
EXPECT_NO_THROW(builder().add_document_operation(
Operation_list{{Update_operation::Base::ARRAY_INSERT,
Document_path{"first", 0}, Scalar(1.0)}}));
EXPECT_STREQ(
"doc=JSON_SET(JSON_ARRAY_INSERT(doc,'$.first[0]',1),'$._id',"
"JSON_EXTRACT(`doc`,'$._id'))",
query.get().c_str());
}
TEST_F(Update_statement_builder_test, add_document_operation_array_append) {
EXPECT_NO_THROW(builder().add_document_operation(
Operation_list{{Update_operation::Base::ARRAY_APPEND,
Document_path{"first"}, Scalar(1.0)}}));
EXPECT_STREQ(
"doc=JSON_SET(JSON_ARRAY_APPEND(doc,'$.first',1),'$._id',"
"JSON_EXTRACT(`doc`,'$._id'))",
query.get().c_str());
}
TEST_F(Update_statement_builder_test,
add_document_operation_array_append_twice) {
EXPECT_NO_THROW(builder().add_document_operation(
Operation_list{{Update_operation::Base::ARRAY_APPEND,
Document_path{"first"}, Scalar(1.0)},
{Update_operation::Base::ARRAY_APPEND,
Document_path{"first"}, Scalar("two")}}));
EXPECT_STREQ(
"doc=JSON_SET(JSON_ARRAY_APPEND(doc,'$.first',1,'$.first','two'),'$._id',"
"JSON_EXTRACT(`doc`,'$._id'))",
query.get().c_str());
}
TEST_F(Update_statement_builder_test, add_document_operation_remove_twice) {
EXPECT_NO_THROW(builder().add_document_operation(Operation_list{
{Update_operation::Base::ITEM_REMOVE, Document_path{"first"}},
{Update_operation::Base::ITEM_REMOVE, Document_path{"second"}}}));
EXPECT_STREQ(
"doc=JSON_SET(JSON_REMOVE(doc,'$.first','$.second'),'$._id',"
"JSON_EXTRACT(`doc`,'$._id'))",
query.get().c_str());
}
TEST_F(Update_statement_builder_test, add_document_operation_set_twice) {
EXPECT_NO_THROW(builder().add_document_operation(Operation_list{
{Update_operation::Base::ITEM_SET, Document_path{"first"}, Scalar(1.0)},
{Update_operation::Base::ITEM_SET, Document_path{"second"},
Scalar("two")}}));
EXPECT_STREQ(
"doc=JSON_SET(JSON_SET(doc,'$.first',1,'$.second','two'),'$._id',"
"JSON_EXTRACT(`doc`,'$._id'))",
query.get().c_str());
}
TEST_F(Update_statement_builder_test,
add_document_operation_set_twice_placeholder) {
args = Expression_list{2.2};
EXPECT_NO_THROW(builder().add_document_operation(Operation_list{
{Update_operation::Base::ITEM_SET, Document_path{"first"}, Scalar(1.0)},
{Update_operation::Base::ITEM_SET, Document_path{"second"},
Placeholder(0)}}));
EXPECT_STREQ(
"doc=JSON_SET(JSON_SET(doc,'$.first',1,'$.second',2.2),'$._id',"
"JSON_EXTRACT(`doc`,'$._id'))",
query.get().c_str());
}
TEST_F(Update_statement_builder_test,
add_document_operation_merge_no_empty_path) {
EXPECT_THROW(builder().add_document_operation(Operation_list{
{Update_operation::Base::ITEM_MERGE, Document_path{"first"},
Scalar("{\"two\": 2.0}")}}),
ngs::Error_code);
}
TEST_F(Update_statement_builder_test, add_document_operation_merge_to_array) {
EXPECT_THROW(builder().add_document_operation(Operation_list{
{Update_operation::Base::ITEM_MERGE,
Document_path{"first", 3}, Scalar("{\"two\": 2.0}")}}),
ngs::Error_code);
}
TEST_F(Update_statement_builder_test, add_document_operation_remove_set) {
EXPECT_NO_THROW(builder().add_document_operation(Operation_list{
{Update_operation::Base::ITEM_REMOVE, Document_path{"first"}},
{Update_operation::Base::ITEM_SET, Document_path{"second"},
Scalar("two")}}));
EXPECT_STREQ(
"doc=JSON_SET(JSON_SET(JSON_REMOVE(doc,'$.first'),'$.second','two'),"
"'$._id',JSON_EXTRACT(`doc`,'$._id'))",
query.get().c_str());
}
TEST_F(Update_statement_builder_test, add_document_operation_remove_twice_set) {
EXPECT_NO_THROW(builder().add_document_operation(Operation_list{
{Update_operation::Base::ITEM_REMOVE, Document_path{"first"}},
{Update_operation::Base::ITEM_REMOVE, Document_path{"second"}},
{Update_operation::Base::ITEM_SET, Document_path{"third"}, Scalar(-3)}}));
EXPECT_STREQ(
"doc=JSON_SET(JSON_SET(JSON_REMOVE(doc,'$.first','$.second'),"
"'$.third',-3),'$._id',JSON_EXTRACT(`doc`,'$._id'))",
query.get().c_str());
}
TEST_F(Update_statement_builder_test, add_document_operation_set_remove_set) {
EXPECT_NO_THROW(builder().add_document_operation(Operation_list{
{Update_operation::Base::ITEM_SET, Document_path{"first"}, Scalar(1.0)},
{Update_operation::Base::ITEM_REMOVE, Document_path{"second"}},
{Update_operation::Base::ITEM_SET, Document_path{"third"}, Scalar(-3)}}));
EXPECT_STREQ(
"doc=JSON_SET(JSON_SET(JSON_REMOVE(JSON_SET(doc,'$.first',1),'$.second'),"
"'$.third',-3),'$._id',JSON_EXTRACT(`doc`,'$._id'))",
query.get().c_str());
}
TEST_F(Update_statement_builder_test,
add_document_operation_item_forbiden_column) {
ASSERT_THROW(builder().add_document_operation_item(
Update_operation(Update_operation::Base::ITEM_SET,
Column_identifier("xcolumn"), Scalar(-3)),
&operation_id),
ngs::Error_code);
ASSERT_EQ(Update_operation::Base::ITEM_SET, operation_id);
}
TEST_F(Update_statement_builder_test,
add_document_operation_item_forbiden_schema) {
ASSERT_THROW(
builder().add_document_operation_item(
Update_operation(Update_operation::Base::ITEM_SET,
Column_identifier("", "", "xschema"), Scalar(-3)),
&operation_id),
ngs::Error_code);
ASSERT_EQ(Update_operation::Base::ITEM_SET, operation_id);
}
TEST_F(Update_statement_builder_test,
add_document_operation_item_forbiden_table) {
ASSERT_THROW(
builder().add_document_operation_item(
Update_operation(Update_operation::Base::ITEM_SET,
Column_identifier("", "xtable"), Scalar(-3)),
&operation_id),
ngs::Error_code);
ASSERT_EQ(Update_operation::Base::ITEM_SET, operation_id);
}
TEST_F(Update_statement_builder_test,
add_document_operation_item_forbiden_id_change) {
ASSERT_THROW(builder().add_document_operation_item(
Update_operation(Update_operation::Base::ITEM_SET,
Document_path{"_id"}, Scalar(-3)),
&operation_id),
ngs::Error_code);
ASSERT_EQ(Update_operation::Base::ITEM_SET, operation_id);
}
TEST_F(Update_statement_builder_test,
add_document_operation_item_empty_document_path) {
operation_id = Update_operation::Base::ITEM_SET;
ASSERT_NO_THROW(builder().add_document_operation_item(
Update_operation(Update_operation::Base::ITEM_SET, Column_identifier(),
Scalar(-3)),
&operation_id));
ASSERT_EQ(Update_operation::Base::ITEM_SET, operation_id);
EXPECT_STREQ(",'$',-3", query.get().c_str());
}
TEST_F(Update_statement_builder_test, add_document_operation_item_root_path) {
ASSERT_NO_THROW(builder().add_document_operation_item(
Update_operation(Update_operation::Base::ITEM_SET, Document_path(),
Scalar(-3)),
&operation_id));
ASSERT_EQ(Update_operation::Base::ITEM_SET, operation_id);
}
TEST_F(Update_statement_builder_test,
add_document_operation_item_empty_member) {
ASSERT_THROW(builder().add_document_operation_item(
Update_operation(Update_operation::Base::ITEM_SET,
Document_path{"first", ""}, Scalar(-3)),
&operation_id),
xpl::Expression_generator::Error);
ASSERT_EQ(Update_operation::Base::ITEM_SET, operation_id);
}
TEST_F(Update_statement_builder_test,
add_document_operation_item_empty_member_reverse) {
ASSERT_THROW(builder().add_document_operation_item(
Update_operation(Update_operation::Base::ITEM_SET,
Document_path{"", "first"}, Scalar(-3)),
&operation_id),
xpl::Expression_generator::Error);
ASSERT_EQ(Update_operation::Base::ITEM_SET, operation_id);
}
TEST_F(Update_statement_builder_test,
add_document_operation_item_root_as_array) {
ASSERT_THROW(builder().add_document_operation_item(
Update_operation(Update_operation::Base::ITEM_SET,
Document_path{0}, Scalar(-3)),
&operation_id),
ngs::Error_code);
ASSERT_EQ(Update_operation::Base::ITEM_SET, operation_id);
}
TEST_F(Update_statement_builder_test,
add_document_operation_item_root_as_array_asterisk) {
ASSERT_THROW(
builder().add_document_operation_item(
Update_operation(
Update_operation::Base::ITEM_SET,
Document_path{Document_path_item::Base::ARRAY_INDEX_ASTERISK},
Scalar(-3)),
&operation_id),
ngs::Error_code);
ASSERT_EQ(Update_operation::Base::ITEM_SET, operation_id);
}
TEST_F(Update_statement_builder_test,
add_document_operation_item_root_double_asterisk) {
ASSERT_THROW(builder().add_document_operation_item(
Update_operation(
Update_operation::Base::ITEM_SET,
Document_path{Document_path_item::Base::DOUBLE_ASTERISK},
Scalar(-3)),
&operation_id),
ngs::Error_code);
ASSERT_EQ(Update_operation::Base::ITEM_SET, operation_id);
}
TEST_F(Update_statement_builder_test, add_operation_one_item_for_document) {
ASSERT_NO_THROW(builder().add_operation(
Operation_list{{Update_operation::Base::ITEM_SET, Document_path{"first"},
Scalar(1.0)}},
DM_DOCUMENT));
EXPECT_STREQ(
" SET doc=JSON_SET(JSON_SET(doc,'$.first',1),'$._id',"
"JSON_EXTRACT(`doc`,'$._id'))",
query.get().c_str());
}
TEST_F(Update_statement_builder_test, build_update_for_document) {
msg =
Update({"xtable", "xschema"}, Mysqlx::Crud::DOCUMENT)
.operation({Update_operation::Base::ITEM_SET, Document_path{"first"},
Scalar(1.0)})
.criteria(Operator(">", Column_identifier{Document_path{"second"}},
Scalar{1.0}))
.order({Column_identifier{Document_path{"third"}}, Order::Base::DESC})
.limit({2});
EXPECT_NO_THROW(builder().build(msg));
EXPECT_STREQ(
"UPDATE `xschema`.`xtable`"
" SET doc=JSON_SET(JSON_SET(doc,'$.first',1),"
"'$._id',JSON_EXTRACT(`doc`,'$._id'))"
" WHERE (JSON_EXTRACT(doc,'$.second') > 1)"
" ORDER BY JSON_EXTRACT(doc,'$.third')"
" DESC LIMIT 2",
query.get().c_str());
}
TEST_F(Update_statement_builder_test, add_document_operation_set_whole_doc) {
ASSERT_NO_THROW(builder().add_document_operation(Operation_list{
{Update_operation::Base::ITEM_SET, Document_path{""}, Scalar("two")}}));
EXPECT_STREQ(
"doc=JSON_SET(JSON_SET(doc,'$','two'),'$._id',"
"JSON_EXTRACT(`doc`,'$._id'))",
query.get().c_str());
}
TEST_F(Update_statement_builder_test,
add_table_operation_set_needless_doc_path) {
ASSERT_THROW(
builder().add_table_operation(Operation_list{
{Update_operation::Base::SET,
Column_identifier(Document_path{"first"}, "xfield"), Scalar(1.0)}}),
ngs::Error_code);
}
TEST_F(Update_statement_builder_test,
add_table_operation_item_set_missing_doc_path) {
ASSERT_THROW(builder().add_table_operation(
Operation_list{{Update_operation::Base::ITEM_SET,
Column_identifier("xfield"), Scalar(1.0)}}),
ngs::Error_code);
}
TEST_F(Update_statement_builder_test, add_table_operation_item_set) {
ASSERT_NO_THROW(builder().add_table_operation(Operation_list{
{Update_operation::Base::ITEM_SET,
Column_identifier(Document_path{"first"}, "xfield"), Scalar(1.0)}}));
EXPECT_STREQ("`xfield`=JSON_SET(`xfield`,'$.first',1)", query.get().c_str());
}
TEST_F(Update_statement_builder_test, add_table_operation_item_set_twice) {
ASSERT_NO_THROW(builder().add_table_operation(Operation_list{
{Update_operation::Base::ITEM_SET,
Column_identifier(Document_path{"first"}, "xfield"), Scalar(1.0)},
{Update_operation::Base::ITEM_SET,
Column_identifier(Document_path{"second"}, "xfield"), Scalar("two")}}));
EXPECT_STREQ("`xfield`=JSON_SET(`xfield`,'$.first',1,'$.second','two')",
query.get().c_str());
}
TEST_F(Update_statement_builder_test,
add_table_operation_item_set_twice_but_different) {
ASSERT_NO_THROW(builder().add_table_operation(Operation_list{
{Update_operation::Base::ITEM_SET,
Column_identifier(Document_path{"first"}, "xfield"), Scalar(1.0)},
{Update_operation::Base::ITEM_SET,
Column_identifier(Document_path{"second"}, "yfield"), Scalar("two")}}));
EXPECT_STREQ(
"`xfield`=JSON_SET(`xfield`,'$.first',1),"
"`yfield`=JSON_SET(`yfield`,'$.second','two')",
query.get().c_str());
}
TEST_F(Update_statement_builder_test, add_table_operation_item_set_triple) {
ASSERT_NO_THROW(builder().add_table_operation(Operation_list{
{Update_operation::Base::ITEM_SET,
Column_identifier(Document_path{"first"}, "xfield"), Scalar(1.0)},
{Update_operation::Base::ITEM_SET,
Column_identifier(Document_path{"second"}, "xfield"), Scalar("two")},
{Update_operation::Base::ITEM_SET,
Column_identifier(Document_path{"third"}, "xfield"), Scalar(-3)}}));
EXPECT_STREQ(
"`xfield`=JSON_SET(`xfield`,'$.first',1,'$.second','two','$.third',-3)",
query.get().c_str());
}
TEST_F(Update_statement_builder_test, add_table_operation_item_set_mix_first) {
ASSERT_NO_THROW(builder().add_table_operation(Operation_list{
{Update_operation::Base::SET, Column_identifier("xfield"), Scalar(1.0)},
{Update_operation::Base::ITEM_SET,
Column_identifier(Document_path{"second"}, "xfield"), Scalar("two")},
{Update_operation::Base::ITEM_SET,
Column_identifier(Document_path{"third"}, "xfield"), Scalar(-3)}}));
EXPECT_STREQ(
"`xfield`=1,"
"`xfield`=JSON_SET(`xfield`,'$.second','two','$.third',-3)",
query.get().c_str());
}
TEST_F(Update_statement_builder_test, add_table_operation_item_set_mix_last) {
ASSERT_NO_THROW(builder().add_table_operation(Operation_list{
{Update_operation::Base::ITEM_SET,
Column_identifier(Document_path{"second"}, "xfield"), Scalar("two")},
{Update_operation::Base::ITEM_SET,
Column_identifier(Document_path{"third"}, "xfield"), Scalar(-3)},
{Update_operation::Base::SET, Column_identifier("xfield"),
Scalar(1.0)}}));
EXPECT_STREQ(
"`xfield`=JSON_SET(`xfield`,'$.second','two','$.third',-3),"
"`xfield`=1",
query.get().c_str());
}
TEST_F(Update_statement_builder_test, add_table_operation_item_set_mix_middle) {
ASSERT_NO_THROW(builder().add_table_operation(Operation_list{
{Update_operation::Base::ITEM_SET,
Column_identifier(Document_path{"second"}, "xfield"), Scalar("two")},
{Update_operation::Base::SET, Column_identifier("xfield"), Scalar(1.0)},
{Update_operation::Base::ITEM_SET,
Column_identifier(Document_path{"third"}, "xfield"), Scalar(-3)}}));
EXPECT_STREQ(
"`xfield`=JSON_SET(`xfield`,'$.second','two'),"
"`xfield`=1,"
"`xfield`=JSON_SET(`xfield`,'$.third',-3)",
query.get().c_str());
}
TEST_F(Update_statement_builder_test, add_table_operation_item_set_fourth) {
ASSERT_NO_THROW(builder().add_table_operation(Operation_list{
{Update_operation::Base::ITEM_SET,
Column_identifier(Document_path{"first"}, "xfield"), Scalar(1.0)},
{Update_operation::Base::ITEM_SET,
Column_identifier(Document_path{"second"}, "xfield"), Scalar("two")},
{Update_operation::Base::ITEM_SET,
Column_identifier(Document_path{"first"}, "yfield"), Scalar(1.0)},
{Update_operation::Base::ITEM_SET,
Column_identifier(Document_path{"second"}, "yfield"), Scalar("two")}}));
EXPECT_STREQ(
"`xfield`=JSON_SET(`xfield`,'$.first',1,'$.second','two'),"
"`yfield`=JSON_SET(`yfield`,'$.first',1,'$.second','two')",
query.get().c_str());
}
TEST_F(Update_statement_builder_test, add_table_operation_item_remove_one) {
ASSERT_NO_THROW(builder().add_table_operation(
Operation_list{{Update_operation::Base::ITEM_REMOVE,
Column_identifier(Document_path{"first"}, "xfield")}}));
EXPECT_STREQ("`xfield`=JSON_REMOVE(`xfield`,'$.first')", query.get().c_str());
}
TEST_F(Update_statement_builder_test, add_table_operation_item_remove_twice) {
ASSERT_NO_THROW(builder().add_table_operation(
Operation_list{{Update_operation::Base::ITEM_REMOVE,
Column_identifier(Document_path{"first"}, "xfield")},
{Update_operation::Base::ITEM_REMOVE,
Column_identifier(Document_path{"second"}, "xfield")}}));
EXPECT_STREQ("`xfield`=JSON_REMOVE(`xfield`,'$.first','$.second')",
query.get().c_str());
}
TEST_F(Update_statement_builder_test, add_table_operation_item_replace_one) {
ASSERT_NO_THROW(builder().add_table_operation(Operation_list{
{Update_operation::Base::ITEM_REPLACE,
Column_identifier(Document_path{"first"}, "xfield"), Scalar(1.0)}}));
EXPECT_STREQ("`xfield`=JSON_REPLACE(`xfield`,'$.first',1)",
query.get().c_str());
}
TEST_F(Update_statement_builder_test, add_table_operation_item_replace_twice) {
ASSERT_NO_THROW(builder().add_table_operation(Operation_list{
{Update_operation::Base::ITEM_REPLACE,
Column_identifier(Document_path{"first"}, "xfield"), Scalar(1.0)},
{Update_operation::Base::ITEM_REPLACE,
Column_identifier(Document_path{"second"}, "xfield"), Scalar("two")}}));
EXPECT_STREQ("`xfield`=JSON_REPLACE(`xfield`,'$.first',1,'$.second','two')",
query.get().c_str());
}
TEST_F(Update_statement_builder_test, add_table_operation_array_insert_one) {
ASSERT_NO_THROW(builder().add_table_operation(Operation_list{
{Update_operation::Base::ARRAY_INSERT,
Column_identifier(Document_path{0}, "xfield"), Scalar(1.0)}}));
EXPECT_STREQ("`xfield`=JSON_ARRAY_INSERT(`xfield`,'$[0]',1)",
query.get().c_str());
}
TEST_F(Update_statement_builder_test, add_table_operation_array_insert_twice) {
ASSERT_NO_THROW(builder().add_table_operation(Operation_list{
{Update_operation::Base::ARRAY_INSERT,
Column_identifier(Document_path{0}, "xfield"), Scalar(1.0)},
{Update_operation::Base::ARRAY_INSERT,
Column_identifier(Document_path{1}, "xfield"), Scalar("two")}}));
EXPECT_STREQ("`xfield`=JSON_ARRAY_INSERT(`xfield`,'$[0]',1,'$[1]','two')",
query.get().c_str());
}
TEST_F(Update_statement_builder_test, add_table_operation_array_append_one) {
ASSERT_NO_THROW(builder().add_table_operation(Operation_list{
{Update_operation::Base::ARRAY_APPEND,
Column_identifier(Document_path{"first"}, "xfield"), Scalar(1.0)}}));
EXPECT_STREQ("`xfield`=JSON_ARRAY_APPEND(`xfield`,'$.first',1)",
query.get().c_str());
}
TEST_F(Update_statement_builder_test, add_table_operation_array_append_twice) {
ASSERT_NO_THROW(builder().add_table_operation(Operation_list{
{Update_operation::Base::ARRAY_APPEND,
Column_identifier(Document_path{"first"}, "xfield"), Scalar(1.0)},
{Update_operation::Base::ARRAY_APPEND,
Column_identifier(Document_path{"second"}, "xfield"), Scalar("two")}}));
EXPECT_STREQ(
"`xfield`=JSON_ARRAY_APPEND(`xfield`,'$.first',1,'$.second','two')",
query.get().c_str());
}
TEST_F(Update_statement_builder_test,
add_table_operation_array_append_twice_placeholder) {
args = Expression_list{2.2};
ASSERT_NO_THROW(builder().add_table_operation(Operation_list{
{Update_operation::Base::ARRAY_APPEND,
Column_identifier(Document_path{"first"}, "xfield"), Scalar(1.0)},
{Update_operation::Base::ARRAY_APPEND,
Column_identifier(Document_path{"second"}, "xfield"), Placeholder(0)}}));
EXPECT_STREQ(
"`xfield`=JSON_ARRAY_APPEND(`xfield`,'$.first',1,'$.second',2.2)",
query.get().c_str());
}
class Merge_param {
public:
Merge_param(const Update_operation::Update_type type,
const std::string &function)
: m_type(type), m_function(function) {}
const Update_operation::Update_type m_type;
const std::string m_function;
};
class Update_statement_builder_op_merge_test
: public Update_statement_builder_test,
public ::testing::WithParamInterface<Merge_param> {};
TEST_P(Update_statement_builder_op_merge_test,
add_document_operation_merge_twice) {
EXPECT_NO_THROW(builder().add_document_operation(Operation_list{
{GetParam().m_type, Document_path{""}, Scalar("{\"two\": 2.0}")},
{GetParam().m_type, Document_path{""}, Scalar("{\"three\": 3.0}")}}));
EXPECT_EQ("doc=JSON_SET(" + GetParam().m_function +
"(doc,'{\\\"two\\\": 2.0}',"
"'{\\\"three\\\": 3.0}'),'$._id',"
"JSON_EXTRACT(`doc`,'$._id'))",
query.get().c_str());
}
TEST_P(Update_statement_builder_op_merge_test,
add_document_operation_set_merge) {
EXPECT_NO_THROW(builder().add_document_operation(Operation_list{
{Update_operation::Base::ITEM_SET, Document_path{"first"}, Scalar(1.0)},
{GetParam().m_type, Column_identifier(), Scalar("{\"three\": 3.0}")}}));
EXPECT_EQ("doc=JSON_SET(" + GetParam().m_function +
"(JSON_SET(doc,'$.first',1),"
"'{\\\"three\\\": 3.0}'),'$._id',JSON_EXTRACT(`doc`,'$._id'))",
query.get().c_str());
}
TEST_P(Update_statement_builder_op_merge_test, add_document_operation_merge) {
EXPECT_NO_THROW(builder().add_document_operation(Operation_list{
{GetParam().m_type, Document_path{""}, Scalar("{\"two\": 2.0}")}}));
EXPECT_EQ("doc=JSON_SET(" + GetParam().m_function +
"(doc,'{\\\"two\\\": 2.0}'),'$._id',"
"JSON_EXTRACT(`doc`,'$._id'))",
query.get().c_str());
}
TEST_P(Update_statement_builder_op_merge_test,
add_table_operation_item_merge_twice) {
ASSERT_NO_THROW(builder().add_table_operation(Operation_list{
{GetParam().m_type, Column_identifier(Document_path{"first"}, "xfield"),
Scalar(1.0)},
{GetParam().m_type, Column_identifier(Document_path{"second"}, "xfield"),
Scalar("two")}}));
EXPECT_EQ("`xfield`=" + GetParam().m_function + "(`xfield`,1,'two')",
query.get().c_str());
}
TEST_P(Update_statement_builder_op_merge_test,
add_table_operation_item_merge_one) {
ASSERT_NO_THROW(builder().add_table_operation(Operation_list{
{GetParam().m_type, Column_identifier(Document_path{"first"}, "xfield"),
Scalar(1.0)}}));
EXPECT_EQ("`xfield`=" + GetParam().m_function + "(`xfield`,1)",
query.get().c_str());
}
INSTANTIATE_TEST_CASE_P(
AllMerge_functions, Update_statement_builder_op_merge_test,
::testing::Values(
Merge_param(Update_operation::Base::ITEM_MERGE, "JSON_MERGE_PRESERVE"),
Merge_param(Update_operation::Base::MERGE_PATCH, "JSON_MERGE_PATCH")));
} // namespace test
} // namespace xpl