diff options
| -rw-r--r-- | slicer/db/Jamfile.jam | 16 | ||||
| -rw-r--r-- | slicer/db/sqlTablePatchSerializer.cpp | 64 | ||||
| -rw-r--r-- | slicer/db/sqlTablePatchSerializer.h | 25 | ||||
| -rw-r--r-- | slicer/db/testPatch.cpp | 47 | 
4 files changed, 152 insertions, 0 deletions
diff --git a/slicer/db/Jamfile.jam b/slicer/db/Jamfile.jam index ea394ff..ad15a6c 100644 --- a/slicer/db/Jamfile.jam +++ b/slicer/db/Jamfile.jam @@ -67,6 +67,22 @@ run testInsert.cpp  	testInsert  	; +run testPatch.cpp +	: : : +	<define>BOOST_TEST_DYN_LINK +	<library>slicer-db +	<library>dbpp-postgresql +	<library>boost_system +	<library>boost_filesystem +	<library>boost_utf +	<library>../test//types +	<library>../test//common +	<library>../slicer//slicer +	<implicit-dependency>../slicer//slicer +	<include>.. +	<dependency>slicer.sql +	; +  run testUpdate.cpp  	: : :  	<define>BOOST_TEST_DYN_LINK diff --git a/slicer/db/sqlTablePatchSerializer.cpp b/slicer/db/sqlTablePatchSerializer.cpp new file mode 100644 index 0000000..20b0d82 --- /dev/null +++ b/slicer/db/sqlTablePatchSerializer.cpp @@ -0,0 +1,64 @@ +#include "sqlTablePatchSerializer.h" +#include "sqlInsertSerializer.h" +#include <slicer/metadata.h> +#include <compileTimeFormatter.h> +#include <scopeExit.h> + +namespace Slicer { +	const std::string md_pkey = "db:pkey"; +	const std::string ignore = "ignore"; + +	AdHocFormatter(ttname, "slicer_tmp_%?"); +	SqlTablePatchSerializer::SqlTablePatchSerializer(DB::Connection * db, DB::TablePatch & tp) : +		db(db), +		tablePatch(tp) +	{ +		tablePatch.src = ttname::get(this); +	} + +	SqlTablePatchSerializer::~SqlTablePatchSerializer() +	{ +	} + +	void +	SqlTablePatchSerializer::Serialize(Slicer::ModelPartForRootPtr mpr) +	{ +		tablePatch.pk.clear(); +		tablePatch.cols.clear(); + +		createTemporaryTable(); +		AdHoc::ScopeExit tidy(boost::bind(&SqlTablePatchSerializer::dropTemporaryTable, this)); + +		SqlInsertSerializer ins(db, tablePatch.src); +		ins.Serialize(mpr); + +		auto mp = mpr->GetContainedModelPart(); +		mp->OnEachChild([this](const auto & name, const auto &, const auto & h) { +			if (metaDataFlagSet(h->GetMetadata(), md_pkey)) { +				tablePatch.pk.insert(name); +			} +		}); +		mp->OnEachChild([this](const auto & name, const auto &, const auto & h) { +			if (metaDataFlagNotSet(h->GetMetadata(), ignore)) { +				tablePatch.cols.insert(name); +			} +		}); + +		db->patchTable(&tablePatch); +	} + +	AdHocFormatter(createTmpTable, "CREATE TEMPORARY TABLE %? AS SELECT * FROM %? WHERE 1 = 0"); +	void +	SqlTablePatchSerializer::createTemporaryTable() +	{ +		db->execute(createTmpTable::get(tablePatch.src, tablePatch.dest)); +	} + +	AdHocFormatter(dropTmpTable, "DROP TABLE %?"); +	void +	SqlTablePatchSerializer::dropTemporaryTable() +	{ +		db->execute(dropTmpTable::get(tablePatch.src)); +	} +} + diff --git a/slicer/db/sqlTablePatchSerializer.h b/slicer/db/sqlTablePatchSerializer.h new file mode 100644 index 0000000..9aad96c --- /dev/null +++ b/slicer/db/sqlTablePatchSerializer.h @@ -0,0 +1,25 @@ +#ifndef SLICER_DB_SQLTABLEPATCHSERIALIZER_H +#define SLICER_DB_SQLTABLEPATCHSERIALIZER_H + +#include <slicer/serializer.h> +#include <tablepatch.h> + +namespace Slicer { +	class DLL_PUBLIC SqlTablePatchSerializer : public Slicer::Serializer { +		public: +			SqlTablePatchSerializer(DB::Connection *, DB::TablePatch &); +			~SqlTablePatchSerializer(); + +			virtual void Serialize(Slicer::ModelPartForRootPtr) override; + +		private: +			void createTemporaryTable(); +			void dropTemporaryTable(); + +			DB::Connection * db; +			DB::TablePatch & tablePatch; +	}; +} + +#endif + diff --git a/slicer/db/testPatch.cpp b/slicer/db/testPatch.cpp new file mode 100644 index 0000000..bb7979b --- /dev/null +++ b/slicer/db/testPatch.cpp @@ -0,0 +1,47 @@ +#define BOOST_TEST_MODULE db_patch +#include <boost/test/unit_test.hpp> +#include <boost/date_time/posix_time/posix_time_io.hpp> +#include <pq-mock.h> +#include <slicer/slicer.h> +#include <definedDirs.h> +#include "sqlTablePatchSerializer.h" +#include "sqlSelectDeserializer.h" +#include <types.h> +#include <common.h> +#include <db.h> + +// LCOV_EXCL_START +BOOST_TEST_DONT_PRINT_LOG_VALUE(TestModule::DateTime); +BOOST_TEST_DONT_PRINT_LOG_VALUE(TestModule::IsoDate); +BOOST_TEST_DONT_PRINT_LOG_VALUE(TestDatabase::Timespan); +// LCOV_EXCL_STOP + +class StandardMockDatabase : public PQ::Mock { +	public: +		StandardMockDatabase() : PQ::Mock("user=postgres dbname=postgres", "pqmock", { +				rootDir.parent_path() / "db" / "slicer.sql" }) +		{ +		} +}; + +BOOST_GLOBAL_FIXTURE( StandardMockDatabase ); + +typedef boost::shared_ptr<DB::Connection> DBPtr; +typedef boost::shared_ptr<DB::SelectCommand> SelectPtr; + +BOOST_AUTO_TEST_CASE( insert_builtins ) +{ +	auto db = DBPtr(DB::MockDatabase::openConnectionTo("pqmock")); +	TestModule::BuiltInSeq bis = { +		TestModule::BuiltInsPtr(new TestModule::BuiltIns(true, 5, 17, 0, 129, 2.3, 4.5, "more text")), +		TestModule::BuiltInsPtr(new TestModule::BuiltIns(true, 6, 18, 0, 130, 3.4, 5.6, "even more text")) +	}; +	DB::TablePatch tp; +	DB::TransactionScope tx(db.get()); +	tp.dest = "builtins"; +	Slicer::SerializeAny<Slicer::SqlTablePatchSerializer>(bis, db.get(), tp); +	auto cmd = db->select("SELECT COUNT(*) FROM builtins"); +	auto c = Slicer::DeserializeAny<Slicer::SqlSelectDeserializer, int>(*cmd); +	BOOST_REQUIRE_EQUAL(2, c); +} +  | 
