SOCI / soci

Official repository of the SOCI - The C++ Database Access Library
http://soci.sourceforge.net/
Boost Software License 1.0
1.37k stars 472 forks source link

rowset_iterator offset issue #1049

Closed isbuki closed 1 year ago

isbuki commented 1 year ago

Hello,

I've created the following test based on examples provided in the documentation to show that rowset_iterator is not returning the first record of the result set.

The test was compiled using with soci source code pulled from github master on 2023-04-21 but I have the same result with source code pulled on July 2022. It was built using gcc version 10.2.1 20210130 (Red Hat 10.2.1-11) on CentOS 7

cmake3 -G "Unix Makefiles" -DCMAKE_CXX_STANDARD=17 -DWITH_BOOST=ON -DWITH_SQLITE3=ON -DSQLITE3_INCLUDE_DIR=/home/istvan/local/sqlite/include -DSQLITE3_LIBRARY=/home/istvan/local/sqlite/lib/libsqlite3.so -DBOOST_INCLUDE_DIR=/home/istvan/local/boost/include -DBOOST_LIBRARIES=/home/istvan/local/boost/lib64 -DBOOST_DATE_TIME_LIBRARY_RELEASE=/home/istvan/local/boost/lib64/libboost_date_time.so -DCMAKE_INSTALL_PREFIX=/home/istvan/local/soci-repo/4.0.3-10 ..

include <soci/boost-optional.h>

include <soci/boost-tuple.h>

include <soci/boost-fusion.h>

include <soci/soci.h>

include <soci/sqlite3/soci-sqlite3.h>

include

using namespace soci ;

int main() { session sql(soci::sqlite3, "stmt_test.db") ;

sql << "create table soci_test( id integer, name varchar, subname varchar);" ;

sql << "insert into soci_test(id,name,subname) values( 1,'john','smith')" ; sql << "insert into soci_test(id,name,subname) values( 2,'george','vals')" ; sql << "insert into soci_test(id,name,subname) values( 3,'ann','smith')" ; sql << "insert into soci_test(id,name,subname) values( 4,'john','grey')" ; sql << "insert into soci_test(id,name,subname) values( 5,'anthony','wall')" ;

row r ;

std::string query = "SELECT id, name, subname FROM soci_test" ; statement st(sql.prepare << query) ; st.define_and_bind() ; st.exchange_for_rowset(into(r)) ; st.execute(true) ;

rowset_iterator it(st, r) ; rowset_iterator end ; for (; it != end; ++it) { std::cout << it->get(0) << ", " << it->get(1) << ", " << it->get(2) << std::endl ; }

return 0 ; }

When executing this test, I get the following output:

2, george, vals 3, ann, smith 4, john, grey 5, anthony, wall

Thank you for your help.

Regards, Istvan

zann1x commented 1 year ago

The problem in the example you provided is that the call st.execute(true) fetches a row. This row is basically skipped by the iterator creation following it because the constructor of rowset_iterator fetches a row as well. By switching the execute call to st.execute(false) instead, the rowset_iterator should return the expected values, starting from the first row of the result set.

isbuki commented 1 year ago

That was exactly the problem. Issue solved.

Thanks for your support.