summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2015-10-18 01:33:49 +0100
committerDan Goodliffe <dan@randomdan.homeip.net>2015-10-18 01:47:47 +0100
commit4c8f043f65a29bbd4ca743398950aea0126343e3 (patch)
tree56e52e05f9544915052bad967358f53ef0db8d4f
parentRestructure alias all list and add missing things (diff)
downloadslicer-4c8f043f65a29bbd4ca743398950aea0126343e3.tar.bz2
slicer-4c8f043f65a29bbd4ca743398950aea0126343e3.tar.xz
slicer-4c8f043f65a29bbd4ca743398950aea0126343e3.zip
Add insert serializers that don't insert fields marked as auto and optionally retrieve the value applied by the database back into the model
-rw-r--r--slicer/db/slicer.sql2
-rw-r--r--slicer/db/sqlInsertSerializer.cpp89
-rw-r--r--slicer/db/sqlInsertSerializer.h24
-rw-r--r--slicer/db/testInsert.cpp48
-rw-r--r--slicer/test/types.ice3
5 files changed, 153 insertions, 13 deletions
diff --git a/slicer/db/slicer.sql b/slicer/db/slicer.sql
index e526db3..9d649bb 100644
--- a/slicer/db/slicer.sql
+++ b/slicer/db/slicer.sql
@@ -15,7 +15,7 @@ CREATE TABLE builtins(
mbool boolean,
mbyte smallint,
mshort smallint,
- mint int,
+ mint serial,
mlong bigint,
mfloat numeric(5, 2),
mdouble numeric(8, 5),
diff --git a/slicer/db/sqlInsertSerializer.cpp b/slicer/db/sqlInsertSerializer.cpp
index eccc083..e8d44f5 100644
--- a/slicer/db/sqlInsertSerializer.cpp
+++ b/slicer/db/sqlInsertSerializer.cpp
@@ -3,8 +3,12 @@
#include "sqlBinder.h"
#include <buffer.h>
#include <modifycommand.h>
+#include <slicer/metadata.h>
+#include <boost/numeric/conversion/cast.hpp>
namespace Slicer {
+ const std::string md_auto = "db:auto";
+
SqlInsertSerializer::SqlInsertSerializer(DB::Connection * c, const std::string & t) :
connection(c),
tableName(t)
@@ -46,27 +50,72 @@ namespace Slicer {
}
void
- SqlInsertSerializer::bindObjectAndExecute(Slicer::ModelPartPtr cmp, DB::ModifyCommand * ins)
+ SqlInsertSerializer::bindObjectAndExecute(Slicer::ModelPartPtr cmp, DB::ModifyCommand * ins) const
{
int paramNo = 0;
- cmp->OnEachChild([&ins, &paramNo](const std::string &, ModelPartPtr cmp, HookCommonPtr) {
- cmp->GetValue(new SqlBinder(*ins, paramNo++));
- });
+ cmp->OnEachChild(boost::bind(&SqlInsertSerializer::bindObjectAndExecuteField, this, boost::ref(paramNo), ins, _2, _3));
ins->execute();
}
+ class IdSave : public Slicer::ValueSource {
+ public:
+ IdSave(DB::Connection * c) :
+ connection(c)
+ {
+ }
+
+#define NonNumType(T) \
+ void set(T &) const override { throw std::runtime_error("Can't store Id in " #T " type field"); }
+
+#define NumType(T) \
+ void set(T & v) const override { v = boost::numeric_cast<T>(connection->insertId()); }
+
+ NonNumType(bool);
+ NonNumType(std::string);
+
+ NumType(Ice::Byte);
+ NumType(Ice::Short);
+ NumType(Ice::Int);
+ NumType(Ice::Long);
+ NumType(Ice::Float);
+ NumType(Ice::Double);
+
+ private:
+ DB::Connection * connection;
+ };
+
+ void
+ SqlFetchIdInsertSerializer::bindObjectAndExecute(Slicer::ModelPartPtr cmp, DB::ModifyCommand * ins) const
+ {
+ SqlAutoIdInsertSerializer::bindObjectAndExecute(cmp, ins);
+ cmp->OnEachChild([&ins, this](const std::string &, ModelPartPtr cmp, HookCommonPtr h) {
+ if (metaDataFlagSet(h->GetMetadata(), md_auto)) {
+ cmp->SetValue(new IdSave(connection));
+ }
+ });
+ }
+
+ void
+ SqlInsertSerializer::bindObjectAndExecuteField(int & paramNo, DB::ModifyCommand * ins, Slicer::ModelPartPtr cmp, HookCommonPtr) const
+ {
+ cmp->GetValue(new SqlBinder(*ins, 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::ModifyPtr
SqlInsertSerializer::createInsert(Slicer::ModelPartPtr mp) const
{
AdHoc::Buffer insert;
insert.appendbf("INSERT INTO %s(", tableName);
int fieldNo = 0;
- mp->OnEachChild([&insert, &fieldNo]( const std::string & name, ModelPartPtr, HookCommonPtr) {
- if (fieldNo++) {
- insert.append(", ");
- }
- insert.append(name);
- });
+ mp->OnEachChild(boost::bind(&SqlInsertSerializer::createInsertField, this, boost::ref(fieldNo), boost::ref(insert), _1, _3));
insert.append(") VALUES (", AdHoc::Buffer::Use);
for (; fieldNo > 1; --fieldNo) {
insert.append("?, ");
@@ -74,5 +123,25 @@ namespace Slicer {
insert.append("?)");
return ModifyPtr(connection->newModifyCommand(insert));
}
+
+ void
+ SqlInsertSerializer::createInsertField(int & fieldNo, AdHoc::Buffer & insert, const std::string & name, HookCommonPtr) const
+ {
+ if (fieldNo++) {
+ insert.append(", ");
+ }
+ insert.append(name);
+ }
+
+ void
+ SqlAutoIdInsertSerializer::createInsertField(int & fieldNo, AdHoc::Buffer & insert, const std::string & name, HookCommonPtr h) const
+ {
+ if (metaDataFlagNotSet(h->GetMetadata(), md_auto)) {
+ if (fieldNo++) {
+ insert.append(", ");
+ }
+ insert.append(name);
+ }
+ }
}
diff --git a/slicer/db/sqlInsertSerializer.h b/slicer/db/sqlInsertSerializer.h
index 843be93..359c655 100644
--- a/slicer/db/sqlInsertSerializer.h
+++ b/slicer/db/sqlInsertSerializer.h
@@ -4,6 +4,7 @@
#include <slicer/serializer.h>
#include <connection.h>
#include <visibility.h>
+#include <buffer.h>
namespace Slicer {
class DLL_PUBLIC SqlInsertSerializer : public Slicer::Serializer {
@@ -18,11 +19,32 @@ namespace Slicer {
void SerializeObject(Slicer::ModelPartPtr) const;
void SerializeSequence(Slicer::ModelPartPtr) const;
ModifyPtr createInsert(Slicer::ModelPartPtr) const;
- static void bindObjectAndExecute(Slicer::ModelPartPtr, DB::ModifyCommand *);
+ virtual void createInsertField(int & fieldNo, AdHoc::Buffer & insert, const std::string & name, HookCommonPtr h) const;
+ virtual void bindObjectAndExecute(Slicer::ModelPartPtr, DB::ModifyCommand *) const;
+ virtual void bindObjectAndExecuteField(int & paramNo, DB::ModifyCommand *, Slicer::ModelPartPtr, HookCommonPtr) const;
DB::Connection * connection;
const std::string tableName;
};
+
+ class DLL_PUBLIC SqlAutoIdInsertSerializer : public SqlInsertSerializer {
+ public:
+ template <typename ... P>
+ SqlAutoIdInsertSerializer(const P & ... p) : SqlInsertSerializer(p...) { }
+
+ protected:
+ virtual void createInsertField(int & fieldNo, AdHoc::Buffer & insert, const std::string & name, HookCommonPtr h) const;
+ virtual void bindObjectAndExecuteField(int & paramNo, DB::ModifyCommand *, Slicer::ModelPartPtr, HookCommonPtr) const;
+ };
+
+ class DLL_PUBLIC SqlFetchIdInsertSerializer : public SqlAutoIdInsertSerializer {
+ public:
+ template <typename ... P>
+ SqlFetchIdInsertSerializer(const P & ... p) : SqlAutoIdInsertSerializer(p...) { }
+
+ protected:
+ virtual void bindObjectAndExecute(Slicer::ModelPartPtr, DB::ModifyCommand *) const;
+ };
}
#endif
diff --git a/slicer/db/testInsert.cpp b/slicer/db/testInsert.cpp
index 2a167c0..74ad537 100644
--- a/slicer/db/testInsert.cpp
+++ b/slicer/db/testInsert.cpp
@@ -66,6 +66,54 @@ BOOST_AUTO_TEST_CASE( insert_seq_builtins )
BOOST_REQUIRE_EQUAL(bis.back()->mstring, bis2.back()->mstring);
}
+BOOST_AUTO_TEST_CASE( autoinsert_seq_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"))
+ };
+ Slicer::SerializeAny<Slicer::SqlAutoIdInsertSerializer>(bis, db.get(), "builtins");
+ auto sel = SelectPtr(db->newSelectCommand("SELECT * FROM builtins WHERE mint IN (1, 2) ORDER BY mint"));
+ auto bis2 = Slicer::DeserializeAny<Slicer::SqlSelectDeserializer, TestModule::BuiltInSeq>(*sel);
+ BOOST_REQUIRE_EQUAL(2, bis2.size());
+ BOOST_REQUIRE_EQUAL(bis.front()->mint, 0);
+ BOOST_REQUIRE_EQUAL(bis.back()->mint, 0);
+ BOOST_REQUIRE_EQUAL(bis2.front()->mint, 1);
+ BOOST_REQUIRE_EQUAL(bis2.back()->mint, 2);
+ 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( fetchinsert_seq_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"))
+ };
+ Slicer::SerializeAny<Slicer::SqlFetchIdInsertSerializer>(bis, db.get(), "builtins");
+ auto sel = SelectPtr(db->newSelectCommand("SELECT * FROM builtins WHERE mint IN (3, 4) ORDER BY mint"));
+ auto bis2 = Slicer::DeserializeAny<Slicer::SqlSelectDeserializer, TestModule::BuiltInSeq>(*sel);
+ BOOST_REQUIRE_EQUAL(2, bis2.size());
+ BOOST_REQUIRE_EQUAL(bis.front()->mint, 3);
+ BOOST_REQUIRE_EQUAL(bis.back()->mint, 4);
+ BOOST_REQUIRE_EQUAL(bis2.front()->mint, 3);
+ BOOST_REQUIRE_EQUAL(bis2.back()->mint, 4);
+ 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/test/types.ice b/slicer/test/types.ice
index 4cd6531..41637a0 100644
--- a/slicer/test/types.ice
+++ b/slicer/test/types.ice
@@ -30,7 +30,8 @@ module TestModule {
bool mbool;
byte mbyte;
short mshort;
- ["slicer:db:pkey"]
+ ["slicer:db:pkey",
+ "slicer:db:auto"]
int mint;
["slicer:db:pkey"]
long mlong;