Search code examples
c++postgresqlsmart-pointersscopinglibpqxx

C++ pqxx postgresql discrete connection classes, scoping class pointer


I have a class, DBProc, which makes a connection to PostgreSQL, and allows user to submit queries/retrieve results.

Functionally, everything works.

The DBProc::connect() function takes an optional argument for connection type. The 3 variants are: direct, lazy, asynchronous.

I have code that instantiates the correct connection class according to user's choice. I initialize 3 unique_ptr<> beforehand, one for each possible connection class, then use an switch statement to choose the selected class type.

This all works fine...but

My preference would be to have ONE class var that holds a reference to the connection class

(all the classes have the exact same functionality), but I see no easy way to do this. 'auto& currentConnection = lazyConnection' works fine in the switch statement, but of course goes out of scope after the code block.

If there was a way to create a var within a block and allow it to be seen outside the block, without 1st declaring it, that would work, but I don't believe that's possible in c++.

I can't declare it first because all these classes require initialization upon declaration. So...c++atch 22 ;-)

So, every time I need to use the connection, I need a switch statement to select the right pointer.

I've looked at templates, unions, extern, and don't see a way to do it with any of these.

If anyone knows if there is a way to do this, please describe.

Here's a code snippet of class func:

bool DBProc::connect(ConnectionType type) {

...

unique_ptr<pqxx::connection> connect;
unique_ptr<pqxx::lazyconnection> lzy_connect;
unique_ptr<pqxx::asyncconnection> async_connect;

try
{
    switch (type) {
        case ConnectionType::direct : {
            connect =  make_unique<pqxx::connection>(connOpts);
            break;
        }
        case ConnectionType::lazy : {
            lzy_connect =  make_unique<pqxx::lazyconnection>(connOpts);
            break;
        }
        case ConnectionType::async : {
            async_connect =  make_unique<pqxx::asyncconnection>(connOpts);
            break;
        }
} catch
    ...
}

Solution

  • Working answer provided in comment by 'some programmer dude'

    Why not have a std::unique_ptr to pqxx::connection_base which is the common base class for all connection types? – Some programmer dude

    Simplified code:

    unique_ptr<pqxx::connection_base> base_connect;
    
    try
    {
        switch (type) {
            case ConnectionType::direct : {
                base_connect = make_unique<pqxx::connection>(connOpts);
                break;
            }
            case ConnectionType::lazy : {
                base_connect = make_unique<pqxx::lazyconnection>(connOpts);
                break;
            }
            case ConnectionType::async : {
                base_connect =  make_unique<pqxx::asyncconnection>(connOpts);
                break;
            }
            default:
                error += "No valid connection type supplied (direct | lazy | async)";
                return false;
                break;
        }