[v3][Dbo] How to read from a Set Returning Function (SRF) aka "table functions".
Added by Vincenzo Romano about 5 years ago
I am in the process of replacing my own DB access library with Dbo.
I am on v3.3.12
with g++ (GCC) 8.2.1 20181127
.
I have recompiled the whole Wt library myself with no errors.
I have a number of SRFs I need to read data from.
It seems I need to write code like this:
struct ConfigEntry {
std::string k;
std::string v;
template<class Action> void persist( Action& a ) {
Wt::Dbo::field( a,k,"k");
Wt::Dbo::field( a,v,"v");
}
};
...
Wt::Dbo::backend::Postgres dbBackEnd;
Wt::Dbo::Session dbSession;
...
void aFunction() {
dbBackEnd.connect( std::string( dbconn ) );
dbSession.setConnection( dbBackEnd );
...
dbSession.mapClass<ConfigEntry>( "session_configuration()" );
auto conf = dbSession.find<ConfigEntry>();
...
}
Is this correct? If not, what's the problem?
Anyway, this code fails at linkage time (I have -lwtdbo -lwtdbopostgres -lwt -lwthttp
) with these messages:
/usr/bin/ld: /tmp/ccpHUsWJ.o: in function `setEntryPoints()':
init.cpp:(.text+0xfa): undefined reference to `void Wt::Dbo::Session::mapClass<ConfigEntry>(char const*)'
/usr/bin/ld: init.cpp:(.text+0x128): undefined reference to `Wt::Dbo::Query<Wt::Dbo::ptr<ConfigEntry>, Wt::Dbo::DynamicBinding> Wt::Dbo::Session::find<ConfigEntry, Wt::Dbo::DynamicBinding>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
/usr/bin/ld: init.cpp:(.text+0x143): undefined reference to `Wt::Dbo::Query<Wt::Dbo::ptr<ConfigEntry>, Wt::Dbo::DynamicBinding>::~Query()'
I am pretty sure this isn't a bug but something I am missing.
One thing that comes to my mind is that my compiler defaults to the "gnu+1\" which should be the 2014 ISO C+ standard plus amendments plus the GNU enhancements.
In the error I read "__cxx11
\".
I have no way at the moment to test with a different compiler.
Any idea?
Replies (6)
RE: [v3][Dbo] How to read from a Set Returning Function (SRF) aka "table functions". - Added by lm at about 5 years ago
I don't use Wt 3, but given the information you gave, I created the following example in Wt 4:
#include <iostream>
#include <Wt/Dbo/Dbo.h>
#include <Wt/Dbo/backend/Postgres.h>
struct ConfigEntry
{
std::string k, v;
template <class A>
void persist (A& a)
{
Wt::Dbo::field(a,k,"k");
Wt::Dbo::field(a,v,"v");
}
};
Wt::Dbo::Session session;
int main()
{
auto backend {std::make_unique<Wt::Dbo::backend::Postgres>()};
backend->connect("dbcon");
session.setConnection(std::move(backend));
session.mapClass<ConfigEntry>("config()");
auto conf = session.find<ConfigEntry>();
return 0;
}
It's built using
g++ -I/usr/local/include/ src/main.cpp -L/usr/local/lib -lwtdbopostgres -lwtdbo
Let me know if you think there's something I can add that might recreate the linker problem.
RE: [v3][Dbo] How to read from a Set Returning Function (SRF) aka "table functions". - Added by Roel Standaert about 5 years ago
lm at: wow, does that work?
I don't know if I can necessarily guarantee that this will always work:
session.mapClass<ConfigEntry>("config()");
Dbo treats what's between double quotes as the name of a table, so if it works then that's neat, I guess, but I think a view would probably work better. You can of course always turn a function call with no arguments or arguments that are known beforehand into a view.
Another thing you should probably do is disable the id and version field using dbo_traits
, see the Wt::Dbo tutorial about customizing the mapping: https://www.webtoolkit.eu/wt/wt3/doc/tutorial/dbo.html#customizing
RE: [v3][Dbo] How to read from a Set Returning Function (SRF) aka "table functions". - Added by lm at about 5 years ago
It compiles and links.
RE: [v3][Dbo] How to read from a Set Returning Function (SRF) aka "table functions". - Added by Vincenzo Romano about 5 years ago
Thanks again lm.
-Wall@ so any type mismatch would pop up as a warning.
Unluckily I need time to prepare a v4 environment to test which I don't have right now.
The point for me is that syntax is (seems to be) OK: I am always compiling with
The SQL function session_configuration()
returns a set of records, though, while your example would pull 1 or 0 records.
My minimal code is:
// Wt
#include <Wt/Dbo/backend/Postgres>
#include <Wt/Dbo/Session>
#include <Wt/Dbo/collection>
// C++
#include <cstdio>
// C
Wt::Dbo::backend::Postgres dbBackEnd;
Wt::Dbo::Session dbSession;
struct ConfigEntry {
std::string k;
std::string v;
template<class Action> void persist( Action& a ) {
Wt::Dbo::field( a,k,"k");
Wt::Dbo::field( a,v,"v");
}
};
int main() {
const char* dbconn = "dbname=tmp1";
dbBackEnd.connect( std::string( dbconn ) );
dbSession.setConnection( dbBackEnd );
dbSession.mapClass<ConfigEntry>( "session_configuration()" );
auto conf = dbSession.find<ConfigEntry>();
return 0;
}
My command line compilation (with g v8) is:
g++ -Wall p.cpp -lwtdbo -lwtdbopostgres
(On my system /usr/local/lib
is among the default directories where the linker looks for the shared objects.)
The link errors are:
/usr/bin/ld: /tmp/ccF2vEMb.o: in function `main':
p.cpp:(.text+0xae): undefined reference to `void Wt::Dbo::Session::mapClass<ConfigEntry>(char const*)'
/usr/bin/ld: p.cpp:(.text+0xfd): undefined reference to `Wt::Dbo::Query<Wt::Dbo::ptr<ConfigEntry>, Wt::Dbo::DynamicBinding>::~Query()'
/usr/bin/ld: /tmp/ccF2vEMb.o: in function `Wt::Dbo::Query<Wt::Dbo::ptr<ConfigEntry>, Wt::Dbo::DynamicBinding> Wt::Dbo::Session::find<ConfigEntry>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)':
p.cpp:(.text._ZN2Wt3Dbo7Session4findI11ConfigEntryEENS0_5QueryINS0_3ptrIT_EENS0_14DynamicBindingEEERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE[_ZN2Wt3Dbo7Session4findI11ConfigEntryEENS0_5QueryINS0_3ptrIT_EENS0_14DynamicBindingEEERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE]+0x36): undefined reference to `Wt::Dbo::Query<Wt::Dbo::ptr<ConfigEntry>, Wt::Dbo::DynamicBinding> Wt::Dbo::Session::find<ConfigEntry, Wt::Dbo::DynamicBinding>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
collect2: error: ld returned 1 exit status
I successfully recompiled wt-3.3.12 and checked the libraries were readable, the directory tree accessible.
I have also placed the proper type instead of auto
Wt::Dbo::Query<Wt::Dbo::ptr<ConfigEntry>, Wt::Dbo::DynamicBinding> conf = dbSession.find<ConfigEntry>();
The error is still there.
If this is fixed in v4, then it must be a bug. Isn't it?
RE: [v3][Dbo] How to read from a Set Returning Function (SRF) aka "table functions". - Added by lm at about 5 years ago
I was able to reproduce the link error using Wt4. I added #include <Wt/Dbo/Dbo.h>
to the top, and it links just fine. I'm not sure which header you're missing exactly, but Dbo.h
includes everything you're likely to need.
RE: [v3][Dbo] How to read from a Set Returning Function (SRF) aka "table functions". - Added by Vincenzo Romano about 5 years ago
C O R R E C T !
I think this is a bug in the header #include
policies: that file should be automatically included with any Dbo-related header file!
Thanks a lot!