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?
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 thesoci::rowandsoci::column_propertiesclasses.
See dynamic binding and rowset and iterator 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
Tparameter that should be passed torow::get<T>()depends on the SOCI data type that is returned fromcolumn_properties::get_data_type().