From cfdee6882b920c0d32ddf3d8a4fe625e003ef1f4 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sat, 24 Oct 2015 01:59:08 +0100 Subject: Handle nulls in models when updating and inserting --- slicer/db/sqlInsertSerializer.cpp | 9 +++++++-- slicer/db/sqlUpdateSerializer.cpp | 7 ++++++- slicer/db/testInsert.cpp | 24 ++++++++++++++++++++++++ slicer/db/testUpdate.cpp | 33 ++++++++++++++++++++++++++------- slicer/test/preprocessor.cpp | 2 +- slicer/test/types.ice | 14 ++++++++++++++ 6 files changed, 78 insertions(+), 11 deletions(-) diff --git a/slicer/db/sqlInsertSerializer.cpp b/slicer/db/sqlInsertSerializer.cpp index 2c2a0d5..fea4bd6 100644 --- a/slicer/db/sqlInsertSerializer.cpp +++ b/slicer/db/sqlInsertSerializer.cpp @@ -98,14 +98,19 @@ namespace Slicer { void SqlInsertSerializer::bindObjectAndExecuteField(int & paramNo, DB::ModifyCommand * ins, Slicer::ModelPartPtr cmp, HookCommonPtr) const { - cmp->GetValue(new SqlBinder(*ins, paramNo++)); + if (cmp) { + cmp->GetValue(new SqlBinder(*ins, paramNo++)); + } + else { + ins->bindNull(paramNo++); + } } void SqlAutoIdInsertSerializer::bindObjectAndExecuteField(int & paramNo, DB::ModifyCommand * ins, Slicer::ModelPartPtr cmp, HookCommonPtr h) const { if (metaDataFlagNotSet(h->GetMetadata(), md_auto)) { - cmp->GetValue(new SqlBinder(*ins, paramNo++)); + SqlInsertSerializer::bindObjectAndExecuteField(paramNo, ins, cmp, h); } } diff --git a/slicer/db/sqlUpdateSerializer.cpp b/slicer/db/sqlUpdateSerializer.cpp index f59e8ff..1787a84 100644 --- a/slicer/db/sqlUpdateSerializer.cpp +++ b/slicer/db/sqlUpdateSerializer.cpp @@ -56,7 +56,12 @@ namespace Slicer { int paramNo = 0; cmp->OnEachChild([&upd, ¶mNo](const std::string &, ModelPartPtr cmp, HookCommonPtr h) { if (metaDataFlagNotSet(h->GetMetadata(), md_pkey)) { - cmp->GetValue(new SqlBinder(*upd, paramNo++)); + if (cmp) { + cmp->GetValue(new SqlBinder(*upd, paramNo++)); + } + else { + upd->bindNull(paramNo++); + } } }); cmp->OnEachChild([&upd, ¶mNo](const std::string &, ModelPartPtr cmp, HookCommonPtr h) { diff --git a/slicer/db/testInsert.cpp b/slicer/db/testInsert.cpp index 74ad537..b1be25f 100644 --- a/slicer/db/testInsert.cpp +++ b/slicer/db/testInsert.cpp @@ -114,6 +114,30 @@ BOOST_AUTO_TEST_CASE( fetchinsert_seq_builtins ) BOOST_REQUIRE_EQUAL(bis.back()->mstring, bis2.back()->mstring); } +BOOST_AUTO_TEST_CASE( fetchinsert_seq_builtinsWithNulls ) +{ + auto db = DBPtr(DB::MockDatabase::openConnectionTo("pqmock")); + DB::BuiltInSeq bis = { + DB::BuiltInsPtr(new DB::BuiltIns(true, IceUtil::Optional(), 17, 0, 129, 2.3, 4.5, "more text")), + DB::BuiltInsPtr(new DB::BuiltIns(true, 6, 18, 0, 130, 3.4, IceUtil::Optional(), "even more text")) + }; + Slicer::SerializeAny(bis, db.get(), "builtins"); + auto sel = SelectPtr(db->newSelectCommand("SELECT * FROM builtins WHERE mint IN (5, 6) ORDER BY mint")); + auto bis2 = Slicer::DeserializeAny(*sel); + BOOST_REQUIRE_EQUAL(2, bis2.size()); + BOOST_REQUIRE_EQUAL(bis.front()->mint, 5); + BOOST_REQUIRE_EQUAL(bis.back()->mint, 6); + BOOST_REQUIRE_EQUAL(bis2.front()->mint, 5); + BOOST_REQUIRE_EQUAL(bis2.back()->mint, 6); + BOOST_REQUIRE_EQUAL(bis.back()->mbool, bis2.back()->mbool); + BOOST_REQUIRE_EQUAL(bis.back()->mbyte, bis2.back()->mbyte); + BOOST_REQUIRE_EQUAL(bis.back()->mshort, bis2.back()->mshort); + BOOST_REQUIRE_EQUAL(bis.back()->mlong, bis2.back()->mlong); + BOOST_REQUIRE_EQUAL(bis.back()->mfloat, bis2.back()->mfloat); + BOOST_REQUIRE_EQUAL(bis.back()->mdouble, bis2.back()->mdouble); + BOOST_REQUIRE_EQUAL(bis.back()->mstring, bis2.back()->mstring); +} + BOOST_AUTO_TEST_CASE( insert_converted ) { auto db = DBPtr(DB::MockDatabase::openConnectionTo("pqmock")); diff --git a/slicer/db/testUpdate.cpp b/slicer/db/testUpdate.cpp index 11ddf2c..7c2d11d 100644 --- a/slicer/db/testUpdate.cpp +++ b/slicer/db/testUpdate.cpp @@ -65,12 +65,6 @@ BOOST_AUTO_TEST_CASE( update_builtins ) BOOST_AUTO_TEST_CASE( update_builtins_seq ) { auto db = DBPtr(DB::MockDatabase::openConnectionTo("pqmock")); - TestModule::BuiltInSeq bis { - TestModule::BuiltInsPtr(new TestModule::BuiltIns(true, 4, 16, 64, 128, 1.2, 3.4, "text1")), - TestModule::BuiltInsPtr(new TestModule::BuiltIns(true, 3, 15, 63, 127, 5.2, 5.4, "text2")), - }; - Slicer::SerializeAny(bis, db.get(), "builtins"); - TestModule::BuiltInSeq ubis { TestModule::BuiltInsPtr(new TestModule::BuiltIns(false, 5, 17, 64, 128, -1.2, -1.4, "string")), TestModule::BuiltInsPtr(new TestModule::BuiltIns(false, 5, 21, 63, 127, -4.2, -5.4, "string updated")) @@ -79,7 +73,7 @@ BOOST_AUTO_TEST_CASE( update_builtins_seq ) auto sel = SelectPtr(db->newSelectCommand("SELECT * FROM builtins ORDER BY mint")); auto ubis2 = Slicer::DeserializeAny(*sel); - BOOST_REQUIRE_EQUAL(2, bis.size()); + BOOST_REQUIRE_EQUAL(2, ubis2.size()); BOOST_REQUIRE_EQUAL(ubis.front()->mbool, ubis2.back()->mbool); BOOST_REQUIRE_EQUAL(ubis.front()->mbyte, ubis2.back()->mbyte); BOOST_REQUIRE_EQUAL(ubis.front()->mshort, ubis2.back()->mshort); @@ -98,6 +92,31 @@ BOOST_AUTO_TEST_CASE( update_builtins_seq ) BOOST_REQUIRE_EQUAL(ubis.back()->mstring, ubis2.front()->mstring); } +BOOST_AUTO_TEST_CASE( update_withNulls ) +{ + auto db = DBPtr(DB::MockDatabase::openConnectionTo("pqmock")); + auto sel = SelectPtr(db->newSelectCommand("SELECT * FROM builtins ORDER BY mint")); + auto bis = Slicer::DeserializeAny(*sel); + BOOST_REQUIRE_EQUAL(2, bis.size()); + BOOST_REQUIRE_EQUAL("string updated", *bis[0]->mstring); + BOOST_REQUIRE_EQUAL("string", *bis[1]->mstring); + bis[0]->mstring = "not null"; + bis[1]->mstring = IceUtil::Optional(); + bis[0]->mfloat = IceUtil::Optional(); + bis[1]->mbyte = IceUtil::Optional(); + bis[0]->mshort = IceUtil::Optional(); + bis[1]->mdouble = IceUtil::Optional(); + BOOST_CHECKPOINT("Do update"); + Slicer::SerializeAny(bis, db.get(), "builtins"); + auto bis2 = Slicer::DeserializeAny(*sel); + BOOST_REQUIRE(bis2[0]->mstring); + BOOST_REQUIRE(!bis2[1]->mstring); + BOOST_REQUIRE(bis2[0]->mbyte); + BOOST_REQUIRE(!bis2[1]->mbyte); + BOOST_REQUIRE(!bis2[0]->mfloat); + BOOST_REQUIRE(bis2[1]->mfloat); +} + BOOST_AUTO_TEST_CASE( update_unsupportedModel ) { auto db = DBPtr(DB::MockDatabase::openConnectionTo("pqmock")); diff --git a/slicer/test/preprocessor.cpp b/slicer/test/preprocessor.cpp index 9a02456..a55cdb2 100644 --- a/slicer/test/preprocessor.cpp +++ b/slicer/test/preprocessor.cpp @@ -13,7 +13,7 @@ namespace fs = boost::filesystem; -const unsigned int COMPONENTS_IN_TEST_ICE = 33; +const unsigned int COMPONENTS_IN_TEST_ICE = 35; BOOST_FIXTURE_TEST_SUITE ( preprocessor, FileStructure ); diff --git a/slicer/test/types.ice b/slicer/test/types.ice index 41637a0..3766342 100644 --- a/slicer/test/types.ice +++ b/slicer/test/types.ice @@ -149,5 +149,19 @@ module DB { class SpecificTypes extends TestModule::DateTimeContainer { Timespan ts; }; + class BuiltIns { + optional(1) bool mbool; + optional(2) byte mbyte; + optional(3) short mshort; + ["slicer:db:pkey", + "slicer:db:auto"] + int mint; + ["slicer:db:pkey"] + long mlong; + optional(4) float mfloat; + optional(5) double mdouble; + optional(6) string mstring; + }; + sequence BuiltInSeq; }; -- cgit v1.2.3