Server IP : 104.21.38.3 / Your IP : 108.162.226.215 Web Server : Apache System : Linux krdc-ubuntu-s-2vcpu-4gb-amd-blr1-01.localdomain 5.15.0-142-generic #152-Ubuntu SMP Mon May 19 10:54:31 UTC 2025 x86_64 User : www ( 1000) PHP Version : 7.4.33 Disable Function : passthru,exec,system,putenv,chroot,chgrp,chown,shell_exec,popen,proc_open,pcntl_exec,ini_alter,ini_restore,dl,openlog,syslog,readlink,symlink,popepassthru,pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,imap_open,apache_setenv MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : ON Directory : /www/server/mysql/src/rapid/unittest/gunit/xplugin/ |
Upload File : |
/* * Copyright (c) 2015, 2023, 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. * * 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 "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