Browse Source

* improved update method in mariadb driver

* improved unit test CMakefile
master
bergmann 5 years ago
parent
commit
48e3a3a7a6
4 changed files with 161 additions and 2 deletions
  1. +5
    -0
      include/cpphibernate/driver/mariadb/schema/table.h
  2. +60
    -1
      src/cpphibernate/driver/mariadb/schema/table.cpp
  3. +2
    -1
      test/CMakeLists.txt
  4. +94
    -0
      test/cpphibernate_update.cpp

+ 5
- 0
include/cpphibernate/driver/mariadb/schema/table.h View File

@@ -98,6 +98,7 @@ beg_namespace_cpphibernate_driver_mariadb
using map_key = std::tuple<size_t, const field_t*>;
using statement_map = std::map<map_key, ::cppmariadb::statement>;

mutable statement_ptr _statement_key_from_base;
mutable statement_ptr _statement_create_table;
mutable statement_ptr _statement_alter_table;
mutable statement_ptr _statement_insert_into;
@@ -107,6 +108,7 @@ beg_namespace_cpphibernate_driver_mariadb
mutable statement_ptr _statement_foreign_many_delete;
mutable statement_ptr _statement_delete;

::cppmariadb::statement& get_statement_key_from_base() const;
::cppmariadb::statement& get_statement_create_table() const;
::cppmariadb::statement* get_statement_alter_table() const;
::cppmariadb::statement& get_statement_insert_into() const;
@@ -121,6 +123,9 @@ beg_namespace_cpphibernate_driver_mariadb
const create_update_context& context,
::cppmariadb::statement& statement) const;

std::string get_primary_key(const data_context& context) const;
std::string get_key_from_base(const data_context& context) const;

virtual std::string create_update_base(const create_update_context& context) const;

protected:


+ 60
- 1
src/cpphibernate/driver/mariadb/schema/table.cpp View File

@@ -1125,7 +1125,7 @@ std::string table_t::execute_create_update(
}
else
{
primary_key = *primary_key_field->get(context);
primary_key = get_primary_key(context);
}

/* base_key */
@@ -1397,6 +1397,34 @@ std::string table_t::get_where_primary_key(const data_context& context) const
std::string table_t::build_delete_query(const std::string* where) const
{ return delete_query_builder_t(*this)(where); }

::cppmariadb::statement& table_t::get_statement_key_from_base() const
{
if (!_statement_key_from_base)
{
if (!base_table)
throw exception(std::string("table has no base table: ") + table_name);
assert(primary_key_field);
assert(base_table);
assert(base_table->primary_key_field);
auto& key_info = *primary_key_field;
auto& base_key = *base_table->primary_key_field;
std::ostringstream os;
os << "SELECT `"
<< key_info.table_name
<< "`.`"
<< key_info.field_name
<< "` FROM `"
<< key_info.table_name
<< "` WHERE `"
<< key_info.table_name
<< "`.`"
<< base_key.table_name
<< "_id`=?\?";
_statement_key_from_base.reset(new ::cppmariadb::statement(os.str()));
}
return *_statement_key_from_base;
}

::cppmariadb::statement& table_t::get_statement_create_table() const
{
if (_statement_create_table)
@@ -1501,6 +1529,37 @@ void table_t::execute_foreign_many_delete(const base_context& context) const
connection.execute(statement);
}

std::string table_t::get_primary_key(const data_context& context) const
{
assert(primary_key_field);
if (primary_key_field->is_default(context))
{
auto key = get_key_from_base(context);
primary_key_field->set(context, key);
return key;
}
else
{
return *primary_key_field->get(context);
}
}

std::string table_t::get_key_from_base(const data_context& context) const
{
if (!base_table)
throw exception(std::string("table has no base table: ") + table_name);
auto& statement = get_statement_key_from_base();
auto base_key = base_table->get_primary_key(context);
statement.set(0, base_key);
auto result = context.connection.execute_stored(statement);
if (!result)
throw exception("unable to fetch key from database: unable to execute query!");
auto row = result->next();
if (!row)
throw exception("unable to fetch key from database: result set is empty!");
return row->at(0).get<std::string>();
}

std::string table_t::create_update_base(const create_update_context& context) const
{
throw misc::hibernate_exception(static_cast<std::ostringstream&>(std::ostringstream { }


+ 2
- 1
test/CMakeLists.txt View File

@@ -26,5 +26,6 @@ If ( __COTIRE_INCLUDED )
Cotire ( test_cpphibernate )
EndIf ( )
If ( __CMAKE_TESTS_INCLUDED )
Add_CMake_Test ( cpphibernate test_cpphibernate )
Add_CMake_Test ( NAME cpphibernate
TARGET test_cpphibernate )
EndIf ( )

+ 94
- 0
test/cpphibernate_update.cpp View File

@@ -540,4 +540,98 @@ TEST(CppHibernateTests, update_derived3)
::cppmariadb::connection connection(reinterpret_cast<MYSQL*>(0x1111));
auto context = make_context<driver::mariadb>(test_schema, connection);
context.update(static_cast<derived2&>(d3));
}

TEST(CppHibernateTests, update_dynamic_base)
{
StrictMock<mariadb_mock> mock;

expect_query(mock, "START TRANSACTION");
expect_query(mock, "SELECT "
"`tbl_derived2`.`tbl_derived2_id` "
"FROM "
"`tbl_derived2` "
"WHERE "
"`tbl_derived2`.`tbl_base_id`='Xf9f13c08-c6e2-11e8-a8d5-f2801f1b9fd1X'",
result_stored({
{ "ae0e7888-c6e6-11e8-a8d5-f2801f1b9fd1" }
}));
expect_query(mock, "UPDATE "
"`tbl_base` "
"SET "
"`name`='Xdynamic derived 1X' "
"WHERE "
"`tbl_base_id`=UuidToBin('Xf9f13c08-c6e2-11e8-a8d5-f2801f1b9fd1X')",
result_affected_rows(1));
expect_query(mock, "DELETE "
"`tbl_test2` "
"FROM "
"`tbl_test2` "
"WHERE "
"`tbl_test2_id` IN ("
"SELECT "
"`tbl_test2_id_test2_nullable` "
"FROM "
"`tbl_derived2` "
"WHERE "
"`tbl_derived2_id`=UuidToBin('Xae0e7888-c6e6-11e8-a8d5-f2801f1b9fd1X')"
")");
expect_query(mock, "DELETE "
"`tbl_test2` "
"FROM "
"`tbl_test2` "
"WHERE "
"`tbl_test2_id` IN ("
"SELECT "
"`tbl_test2_id_test2_ptr_u` "
"FROM "
"`tbl_derived2` "
"WHERE "
"`tbl_derived2_id`=UuidToBin('Xae0e7888-c6e6-11e8-a8d5-f2801f1b9fd1X')"
")");
expect_query(mock, "DELETE "
"`tbl_test2` "
"FROM "
"`tbl_test2` "
"WHERE "
"`tbl_test2_id` IN ("
"SELECT "
"`tbl_test2_id_test2_ptr_s` "
"FROM "
"`tbl_derived2` "
"WHERE "
"`tbl_derived2_id`=UuidToBin('Xae0e7888-c6e6-11e8-a8d5-f2801f1b9fd1X')"
")");
expect_query(mock, "UPDATE "
"`tbl_derived2` "
"SET "
"`tbl_base_id`=UuidToBin('Xf9f13c08-c6e2-11e8-a8d5-f2801f1b9fd1X'), "
"`tbl_test2_id_test2_nullable`=UuidToBin(null), "
"`tbl_test2_id_test2_ptr_u`=UuidToBin(null), "
"`tbl_test2_id_test2_ptr_s`=UuidToBin(null) "
"WHERE "
"`tbl_derived2_id`=UuidToBin('Xae0e7888-c6e6-11e8-a8d5-f2801f1b9fd1X')",
result_affected_rows(1));
expect_query(mock, "COMMIT");

EXPECT_CALL(
mock,
mysql_real_escape_string(reinterpret_cast<MYSQL*>(0x1111), _, _, _))
.Times(AnyNumber())
.WillRepeatedly(WithArgs<1, 2, 3>(EscapeString()));

EXPECT_CALL(
mock,
mysql_close(
reinterpret_cast<MYSQL*>(0x1111)));

std::unique_ptr<base> b;
b.reset(new derived2());
auto& d2 = *dynamic_cast<derived2*>(b.get());
d2.id = uuid("f9f13c08-c6e2-11e8-a8d5-f2801f1b9fd1");
d2.name = "dynamic derived 1";

::cppmariadb::connection connection(reinterpret_cast<MYSQL*>(0x1111));
auto context = make_context<driver::mariadb>(test_schema, connection);
context.update(b);
}

Loading…
Cancel
Save