Support #13147
openpass a unique_ptr parameter with custom deleter to Session's setConnection method
0%
Description
Hi,
Is it possible in your opinion to pass a unique_ptr parameter with custom deleter to dbo Session's setConnection method? If so, how do I properly convert the parameter before passing it to the function? I want to call my custom deleter instead of the default when I go out of scope.
Thank you in advance,
Giovanni
Files
Updated by Matthias Van Ceulebroeck about 2 months ago
- Status changed from New to Feedback
- Assignee set to Giovanni Ferranti
Hello Giovanni,
it is not possible to add a custom Deleter
to the unique_ptr
, since that would be regarded as a different type to the default deleter. When calling setConnection
, the conversion from your custom Deleter to the std::default_delete<Wt::Dbo::SqlConnection>>
would fail.
Now, what IS possible, is to create a wrapper around your connection object. A small example would look like this:
class ConnectionWrapper : public Wt::Dbo::backend::Sqlite3
{
public:
ConnectionWrapper(const std::string& location)
: Wt::Dbo::backend::Sqlite3(location)
{
}
~ConnectionWrapper()
{
Wt::log("==========") << "DO DESTRUCTION";
}
};
It can be created like any other backend, and then set as the session's connection:
ConnectionWrapper *sqlite3 = new ConnectionWrapper(appRoot() + "database.db");
auto connection = std::unique_ptr<Wt::Dbo::SqlConnection>(sqlite3);
session_.setConnection(std::move(connection));
Note that I took Sqlite3 as the example here, but it ought to work for any backend.
Updated by Giovanni Ferranti about 2 months ago
Hi Matthias, thank you very much for your reply. Unfortunately I need to avoid the connection deletion. I managed to independently recompile the wt library and in particular the wtdbo project. Do you think I can replace the declaration
std::unique_ptr<SqlConnection, nop> connection_;
with
std::unique_ptr<SqlConnection> connection_;
where nop is defined as:
#ifndef NOP_HPP
#define NOP_HPP
class SqlConnection;
struct nop
{
void operator() (SqlConnection* c) const noexcept { }
};
#endif // NOP_HPP
What is the most transparent way to do it?
I tried but if I include nop.h in Transaction.h it gives me error C3646: 'limitQueryMethod_': unknown override specifier in Session.h
Thank you,
Giovanni
Updated by Matthias Van Ceulebroeck about 2 months ago
- File sqldeleter.patch sqldeleter.patch added
Hello Giovanni,
that is because you would need to change all occurrences of the SqlConnection
unique_ptr
instances. I have created a quick patch to allow you to do this:
Updated by Giovanni Ferranti about 2 months ago
Hello Matthias.
sorry for the delay in replying but I have been abroad. Thank you very much, I have already successfully recompiled the wtdbo library using a custom deleter that does nothing. It works but I will have to manage other things to make everything work correctly.
It is a bit challenging because I am working on a scripting language based on Chaiscript engine which, among other things, incorporates most of the wt, including dbo. wt part works pretty well (I succesfully recreated the whole simplechat example) but I've some troubles with dbo, maybe because of external dll generation.
Basically I can do something like this:
// this script will generate a dynamic library called DbModule.dll with all relative dbo methods exposed by script engine
import("cg")
var dbObj = DbObject("TabMaterial")
dbObj.SetTypes(["string", "string", "string", "string", "string", "string"])
dbObj.SetNames(["description", "net_weight_V", "uom", "old_material_code_s", "type_S", "SETUP_GROUP"])
dbObj.SetDefaults(["", "", "", "", "", ""])
dbObj.SetNaturalPrimaryKey("part_number", "string", "part_number", 64)
dbObj.DisableVersionField(true)
cg.AddDatabaseObject(dbObj)
cg.Commit()
cg.Compile() // compiles the .dll
and this:
load_module("DbModule")
var web = WebServer("./restApi.wt", 8081)
var resource = WResource(fun(req, res) {
if(req.Method != "POST") {
res.Out << "Error! Only Post Method is allowed!"
return
}
var conn = SQLServer(CONNECTION_STRING)
var session = Session()
session.MapClassTabMaterial("TAB_MATERIAL_SOURCE")
session.SetConnection(conn)
session.CreateTables()
var body = ""
var len = req.ContentLength
var read = 0
var chunck = ""
while(read < len) {
req.In >> chunck
read += chunck.size
body += chunck
}
var part_number = body.from_json["materialCode"]
var description = body.from_json["materialDescription"]
var netWeight = body.from_json["netWeight"]["value"]
var uom = body.from_json["netWeight"]["unit"]
var oldMaterialCode = body.from_json["oldMaterialCode"]
var materialType = body.from_json["materialType"]
var t = Transaction(session)
var tabMaterial = TabMaterial()
try {
tabMaterial.part_number = part_number
tabMaterial.description = description
tabMaterial.net_weight_V = to_string(netWeight)
tabMaterial.uom = uom
tabMaterial.old_material_code_s = oldMaterialCode
tabMaterial.type_S = materialType
tabMaterial.SETUP_GROUP = ""
session.AddTabMaterial(tabMaterial)
}
catch(e) {
t.Rollback
res.Out << "Db Error!" + e.what()
return
}
t.Commit
res.Out << "Success!"
})
var f = fun(app) {
print("Web Api Server started!")
}
web.Run(f)
web.AddResource(resource, "/api")
it works but I have some collateral effects because of MSSQLServer and Session objects declared inside a chaiscript function. if declared outside it works fine. I guess it could be a Chaiscript bug but it is actually too complex for me trying to fix the engine source code. So I will try to adjust wtdbo for my needs :) :)
Thanks again for your availability and kindness
Updated by Matthias Van Ceulebroeck about 2 months ago
Hello Giovanni,
I suspect that the server (and its connection) should stay alive. All data is stored in a session, and if that object is destructed, so would its contents. Used as an API, though, the connection is likely fine to be destructed. But I'd be careful with session up too many connections.
It's not a use-case I have seen before. But generally, since it's an API, you way want to take a look at a connection pool? That can ensure their is not much overhead from setting up new connections each time. A suggestion, and I am also not sure if it fits with your needs.
Best of luck, and let me know should there be anything else!