Search code examples
c++postgresqlboostboost-graphlibpqxx

error: no matching function for call to ‘get(long unsigned int*&, long unsigned int&)’ with union_set


This code

table_edges[ this_relationship ] = boost::add_edge(
    table_vertices[ string( foreign_keys[i]["parent_table"].c_str() ) ], 
    table_vertices[ string( foreign_keys[i]["child_table"].c_str() ) ], 
    this_relationship, 
    rg
).first;
ds.union_set( 
    table_vertices[ string( foreign_keys[i]["parent_table"].c_str() ) ],
    table_vertices[ string( foreign_keys[i]["child_table"].c_str() ) ] 
);

gives this error and many others regarding get

/usr/include/boost/pending/detail/disjoint_sets.hpp:59:33: error: no matching function for call to ‘get(long unsigned int*&, long unsigned int&)’

I am using bundled properties.

typedef boost::adjacency_list < 
   boost::vecS, 
   boost::vecS, 
   boost::undirectedS, 
   string, 
   foreign_key_relationship  
> relational_graph;

The rank & parent typedefs are declared globally.

How can this error be resolved?


struct foreign_key_relationship{
    string parent_table;
    string parent_column;
    string child_table;
    string child_column;

    foreign_key_relationship(){}

    foreign_key_relationship( string pt, string pc, string ct, string cc ) : parent_table( pt ), parent_column( pc ), child_table( ct ), child_column( cc ) {}

};

inline bool operator==(const foreign_key_relationship& lhs, const foreign_key_relationship& rhs)
{
    return 
        lhs.parent_table == rhs.parent_table 
        && lhs.parent_column == rhs.parent_column 
        && lhs.child_table == rhs.child_table 
        && lhs.child_column == rhs.child_column 
    ;
}

inline bool operator<(const foreign_key_relationship& lhs, const foreign_key_relationship& rhs)
{
    return 
        lhs.parent_table < rhs.parent_table 
        && lhs.parent_column < rhs.parent_column 
        && lhs.child_table < rhs.child_table 
        && lhs.child_column < rhs.child_column 
    ;
}

typedef boost::adjacency_list < boost::vecS, boost::vecS, boost::undirectedS, string, foreign_key_relationship  > relational_graph;
typedef boost::graph_traits<relational_graph>::vertex_descriptor relational_vertex;
typedef boost::graph_traits<relational_graph>::vertices_size_type relational_vertex_index;
typedef boost::graph_traits<relational_graph>::edge_descriptor relational_edge;
typedef relational_vertex_index* relational_rank;
typedef relational_vertex* relational_parent;

void libpqxx_error( const pqxx_exception &e ){
    cerr << "*** Caught pqxx_exception:\n";
    cerr << e.base().what() << "\n";
    const sql_error *s=dynamic_cast<const sql_error*>(&e.base());
    if (s) std::cerr << "Query was: " << s->query() << "\n";
}

void connect_relational_vertices( map< foreign_key_relationship, relational_edge > &table_edges, result &foreign_keys, set<string> &tables_to_connect, map< string, relational_vertex > &table_vertices, relational_graph &rg, boost::disjoint_sets<relational_rank, relational_parent> &ds ){
    for( unsigned i=0; i<foreign_keys.size(); i++ ){
        foreign_key_relationship this_relationship(
            foreign_keys[i]["parent_table"].c_str(),
            foreign_keys[i]["parent_column"].c_str(),
            foreign_keys[i]["child_table"].c_str(),
            foreign_keys[i]["child_column"].c_str()
        );
        if( !table_edges.count( this_relationship ) && tables_to_connect.count( foreign_keys[i]["parent_table"].c_str() ) && tables_to_connect.count( foreign_keys[i]["child_table"].c_str() ) ){
            table_edges[ this_relationship ] = boost::add_edge(
                table_vertices[ string( foreign_keys[i]["parent_table"].c_str() ) ], 
                table_vertices[ string( foreign_keys[i]["child_table"].c_str() ) ], 
                this_relationship, 
                rg
            ).first;
            ds.union_set( table_vertices[ string( foreign_keys[i]["parent_table"].c_str() ) ], table_vertices[ string( foreign_keys[i]["child_table"].c_str() ) ] );
        }
    }
}

void add_possible_linking_vertex( result &foreign_keys, map< string, relational_vertex > &table_vertices, relational_graph &rg ){
    for( unsigned i=0; i<foreign_keys.size(); i++ ){
        if( !table_vertices.count( foreign_keys[i]["parent_table"].c_str() ) ){
            table_vertices[ foreign_keys[i]["parent_table"].c_str() ] = boost::add_vertex( foreign_keys[i]["parent_table"].c_str(), rg );
            break;
        }
        if( foreign_keys[i]["child_table"].c_str() ){
            table_vertices[ foreign_keys[i]["child_table"].c_str() ] = boost::add_vertex( foreign_keys[i]["child_table"].c_str(), rg );
            break;
        }
    }
}    

set< foreign_key_relationship > get_foreign_keys( transaction_base &t, set<string> tables_to_connect ){
    try{
        result foreign_keys = t.prepared("get_foreign_keys").exec();

        set< foreign_key_relationship > relational_routes;

        if( tables_to_connect.size() ){

            relational_graph rg;

            map< string, relational_vertex > table_vertices;
            for( string table: tables_to_connect )
                table_vertices[ table ] = boost::add_vertex( table, rg );

            std::vector<relational_vertex_index> rank( num_vertices(rg) );
            std::vector<relational_vertex> parent( num_vertices(rg) );

            boost::disjoint_sets<relational_rank, relational_parent> ds(&rank[0], &parent[0]);

            boost::initialize_incremental_components(rg, ds);
            boost::incremental_components(rg, ds);

            map< foreign_key_relationship, relational_edge > table_edges;
            for( unsigned i=0; i<foreign_keys.size(); i++ )
                connect_relational_vertices( table_edges, foreign_keys, tables_to_connect, table_vertices, rg, ds );

        }

        return relational_routes;
    }
    catch( const pqxx_exception &e ){
        libpqxx_error( e );
        set< foreign_key_relationship > relational_routes;
        return relational_routes;
    }
}

I am using libpqxx, and the query to find all foreign key relationships is here.


Solution

  • I have just spent ~15 minute to add the missing bits to the sample code. I was gonna edit the question and leave a comment, "sadly I ran out of time to look at your actual question".

    However, then it struck me that the actual question was "why does it not compile"?

    Well then, it compiles for me, so maybe this will help you figure out what's different none-the-less?

    #include <boost/graph/use_mpi.hpp>
    #include <boost/graph/adjacency_list.hpp>
    #include <boost/graph/distributed/dehne_gotz_min_spanning_tree.hpp>
    #include <boost/graph/incremental_components.hpp>
    #include <iostream>
    #include <pqxx/except.hxx>
    #include <pqxx/transaction_base.hxx>
    #include <set>
    #include <map>
    #include <string>
    
    using std::string;
    using std::set;
    using std::map;
    using namespace pqxx;
    
    struct foreign_key_relationship{
        string parent_table;
        string parent_column;
        string child_table;
        string child_column;
    
        foreign_key_relationship(){}
    
        foreign_key_relationship( string pt, string pc, string ct, string cc ) : parent_table( pt ), parent_column( pc ), child_table( ct ), child_column( cc ) {}
    
    };
    
    inline bool operator==(const foreign_key_relationship& lhs, const foreign_key_relationship& rhs)
    {
        return 
            lhs.parent_table == rhs.parent_table 
            && lhs.parent_column == rhs.parent_column 
            && lhs.child_table == rhs.child_table 
            && lhs.child_column == rhs.child_column 
        ;
    }
    
    inline bool operator<(const foreign_key_relationship& lhs, const foreign_key_relationship& rhs)
    {
        return 
            lhs.parent_table < rhs.parent_table 
            && lhs.parent_column < rhs.parent_column 
            && lhs.child_table < rhs.child_table 
            && lhs.child_column < rhs.child_column 
        ;
    }
    
    typedef boost::adjacency_list < boost::vecS, boost::vecS, boost::undirectedS, string, foreign_key_relationship  > relational_graph;
    typedef boost::graph_traits<relational_graph>::vertex_descriptor relational_vertex;
    typedef boost::graph_traits<relational_graph>::vertices_size_type relational_vertex_index;
    typedef boost::graph_traits<relational_graph>::edge_descriptor relational_edge;
    typedef relational_vertex_index* relational_rank;
    typedef relational_vertex* relational_parent;
    
    void libpqxx_error( const pqxx_exception &e ){
        std::cerr << "*** Caught pqxx_exception:\n";
        std::cerr << e.base().what() << "\n";
        const sql_error *s=dynamic_cast<const sql_error*>(&e.base());
        if (s) std::cerr << "Query was: " << s->query() << "\n";
    }
    
    void connect_relational_vertices( map< foreign_key_relationship, relational_edge > &table_edges, result &foreign_keys, set<string> &tables_to_connect, map< string, relational_vertex > &table_vertices, relational_graph &rg, boost::disjoint_sets<relational_rank, relational_parent> &ds ){
        for( unsigned i=0; i<foreign_keys.size(); i++ ){
            foreign_key_relationship this_relationship(
                foreign_keys[i]["parent_table"].c_str(),
                foreign_keys[i]["parent_column"].c_str(),
                foreign_keys[i]["child_table"].c_str(),
                foreign_keys[i]["child_column"].c_str()
            );
            if( !table_edges.count( this_relationship ) && tables_to_connect.count( foreign_keys[i]["parent_table"].c_str() ) && tables_to_connect.count( foreign_keys[i]["child_table"].c_str() ) ){
                table_edges[ this_relationship ] = boost::add_edge(
                    table_vertices[ string( foreign_keys[i]["parent_table"].c_str() ) ], 
                    table_vertices[ string( foreign_keys[i]["child_table"].c_str() ) ], 
                    this_relationship, 
                    rg
                ).first;
                ds.union_set( table_vertices[ string( foreign_keys[i]["parent_table"].c_str() ) ], table_vertices[ string( foreign_keys[i]["child_table"].c_str() ) ] );
            }
        }
    }
    
    void add_possible_linking_vertex( result &foreign_keys, map< string, relational_vertex > &table_vertices, relational_graph &rg ){
        for( unsigned i=0; i<foreign_keys.size(); i++ ){
            if( !table_vertices.count( foreign_keys[i]["parent_table"].c_str() ) ){
                table_vertices[ foreign_keys[i]["parent_table"].c_str() ] = boost::add_vertex( foreign_keys[i]["parent_table"].c_str(), rg );
                break;
            }
            if( foreign_keys[i]["child_table"].c_str() ){
                table_vertices[ foreign_keys[i]["child_table"].c_str() ] = boost::add_vertex( foreign_keys[i]["child_table"].c_str(), rg );
                break;
            }
        }
    }    
    
    set< foreign_key_relationship > get_foreign_keys( transaction_base &t, set<string> tables_to_connect ){
        try{
            result foreign_keys = t.prepared("get_foreign_keys").exec();
    
            set< foreign_key_relationship > relational_routes;
    
            if( tables_to_connect.size() ){
    
                relational_graph rg;
    
                map< string, relational_vertex > table_vertices;
                for( string table: tables_to_connect )
                    table_vertices[ table ] = boost::add_vertex( table, rg );
    
                std::vector<relational_vertex_index> rank( num_vertices(rg) );
                std::vector<relational_vertex> parent( num_vertices(rg) );
    
                boost::disjoint_sets<relational_rank, relational_parent> ds(&rank[0], &parent[0]);
    
                boost::initialize_incremental_components(rg, ds);
                boost::incremental_components(rg, ds);
    
                map< foreign_key_relationship, relational_edge > table_edges;
                for( unsigned i=0; i<foreign_keys.size(); i++ )
                    connect_relational_vertices( table_edges, foreign_keys, tables_to_connect, table_vertices, rg, ds );
    
            }
    
            return relational_routes;
        }
        catch( const pqxx_exception &e ){
            libpqxx_error( e );
            set< foreign_key_relationship > relational_routes;
            return relational_routes;
        }
    }
    
    int main()
    {
        relational_graph rg;
        map<foreign_key_relationship, relational_edge> table_edges;
        pqxx::result data;
        set<string> tables { "foo", "bar" };
        map<string, relational_vertex> table_vertices;
        boost::disjoint_sets<relational_rank, relational_parent> ds(relational_rank{}, relational_parent{});
    
        connect_relational_vertices(table_edges, data, tables, table_vertices, rg, ds);
    }
    

    I compiled with

    • gcc 4.8, 4.9, clang 3.5-1
    • boost 1_56_0
    • command line:

      g++ -std=c++0x -Wall -pedantic -lpthread -g -O0 -isystem ~/custom/boost/ -isystem /usr/include/mpi test.cpp -o test -lmpich -lpqxx