0

In most examples for SOCI, the caller must know the fields and types in a query and specifies them through a soci::rowset<> of boost::tuple<> or through some other means.

Is there a way to code without knowing the types and number of columns beforehand, as in a SELECT * FROM ... query?

If so, could you post a short example?

kfmfe04
  • 14,936
  • 14
  • 74
  • 140

2 Answers2

3

soci::rowset<soci::row> is exactly what you need — soci::row provides dynamic binding.

From the docs:

For certain applications it is desirable to be able to select data from arbitrarily structured tables (e.g. via "select * from ...") and format the resulting data based upon its type. SOCI supports this through the soci::row and soci::column_properties classes.

See:

http://soci.sourceforge.net/doc/3.2/exchange.html#dynamic
http://soci.sourceforge.net/doc/3.2/statements.html#rowset

for details.

Excerpt from the documentation:

For example, the code below creates an XML document from a selected row of data from an arbitrary table:

row r;
sql << "select * from some_table", into(r);

std::ostringstream doc;
doc << "<row>" << std::endl;
for(std::size_t i = 0; i != r.size(); ++i)
{
    const column_properties & props = r.get_properties(i);

    doc << '<' << props.get_name() << '>';

    switch(props.get_data_type())
    {
    case dt_string:
        doc << r.get<std::string>(i);
        break;
    case dt_double:
        doc << r.get<double>(i);
        break;
    case dt_integer:
        doc << r.get<int>(i);
        break;
    case dt_long_long:
        doc << r.get<long long>(i);
        break;
    case dt_unsigned_long_long:
        doc << r.get<unsigned long long>(i);
        break;
    case dt_date:
        std::tm when = r.get<std::tm>(i);
        doc << asctime(&when);
        break;
    }

    doc << "</" << props.get_name() << '>' << std::endl;
}
doc << "</row>";

The type T parameter that should be passed to row::get() depends on the SOCI data type that is returned from column_properties::get_data_type().

Devolus
  • 21,661
  • 13
  • 66
  • 113
vines
  • 5,160
  • 1
  • 27
  • 49
  • Even though the link is the same as the accepeted answers (which is outdated by now), it at least gives some small hint what to look for. – Devolus Feb 03 '14 at 10:47
  • I updated your post with the relevant snippet from the documentation, to prevent this happening in the future as well. I haven't tested it though, so I hope this is up to date. I found other parts of the docs which were a bit outdated itself, but this should give at least a good starting point. – Devolus Feb 03 '14 at 11:59
0

I don't believe there's a way. Likely because 'select *' is generally considered dangerous. Columns can be added, re-ordered, etc and your query is now broken. Save your future self some debugging and list the columns out.

Graham Perks
  • 23,007
  • 8
  • 61
  • 83
  • 1
    In most scenarios, I agree with you. However, it may be useful in some special cases like a GUI for editing an arbitrary table. If the functionality is available, it is possible to write a general utility that will work regardless of column ordering etc... – kfmfe04 Oct 31 '12 at 01:41