Thread: [Cppcms-users] statement::bind can be deceptive/dangerous
Brought to you by:
artyom-beilis
From: <ele...@ex...> - 2012-05-07 06:28:05
|
I was trying to figure out why st.prepare(....) .... st.bind(5, r.get<string>("date_action")); .... st.exec() in my code produces unpredictable behaviour untill I read in the documentation that - Note: the reference to the string MUST remain valid until the statement is queried or executed! In my code im copying some old rows into new rows and r.get<string>("date_action") returns the letter "R" but after it got binded to the new statement it was showing "l" which puzzled me to no-end as to why, but if I did string wtf = r.get<string>("date_action"); st.bind(5, wtf); it worked fine. Should statement::bind be using value instead of reference semantics? Petr |
From: Artyom B. <art...@ya...> - 2012-05-07 06:37:40
|
----- Original Message ----- > From: "ele...@ex..." <ele...@ex...> > > I was trying to figure out why > > st.prepare(....) > .... > st.bind(5, r.get<string>("date_action")); > .... > st.exec() > > in my code produces unpredictable behaviour untill I read in the > documentation that - > > Note: the reference to the string MUST remain valid until the statement is > queried or executed! > > [ snip ] > > Should statement::bind be using value instead of reference semantics? > No, this is a very important performance optimization. Consider the string of size of 50k - like article or some other data. Copying `std::string` would require both memory allocation and memory copy. More than that when you work with multiple strings each such copy semantics triggers a memory allocation that costs a lot, at least with C++11 string semantics were Copy-On-Write is forbidden. That is why you should keep the reference valid. BTW: You can do all this in one line sql << "INSERT ..." << ... << r.get<string>("date_action")) << ... << cppdb::exec; This would be valid as the return value remains withing the statement. Artyom Beilis. |
From: <ele...@ex...> - 2012-05-07 07:57:43
|
> sql << "INSERT ..." << ... << r.get<string>("date_action")) << ... << > cppdb::exec; > > This would be valid as the return value remains withing the statement. > > Artyom Beilis. I understand that however what if you need to do something like this - cppdb::statement st; st = sql.prepare(...) st << one << two; if (condition is true) st << three << four else st << five << six end st.exec() In this case do I have to store all the variables on the function stack before passing them to statement? Petr |
From: Marcel H. <ke...@co...> - 2012-05-07 08:02:37
|
Am 07.05.2012 09:57, schrieb ele...@ex...: > > sql<< "INSERT ..."<< ...<< r.get<string>("date_action"))<< ...<< >> cppdb::exec; >> >> This would be valid as the return value remains withing the statement. >> >> Artyom Beilis. > I understand that however what if you need to do something like this - > > cppdb::statement st; > st = sql.prepare(...) > > st<< one<< two; > > if (condition is true) > st<< three<< four > else > st<< five<< six > end > > st.exec() > > In this case do I have to store all the variables on the function stack > before passing them to statement? if you have your elements in a vector/array/json::array(is a vector itself) you can do this: http://cppcms.com/sql/cppdb/stat.html#stat_reset > Petr > > > ------------------------------------------------------------------------------ > Live Security Virtual Conference > Exclusive live event will cover all the ways today's security and > threat landscape has changed and how IT managers can respond. Discussions > will include endpoint security, mobile security and the latest in malware > threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ > _______________________________________________ > Cppcms-users mailing list > Cpp...@li... > https://lists.sourceforge.net/lists/listinfo/cppcms-users |
From: <ele...@ex...> - 2012-05-07 08:47:38
|
>> In this case do I have to store all the variables on the function stack >> before passing them to statement? > if you have your elements in a vector/array/json::array(is a vector > itself) you can do this: > http://cppcms.com/sql/cppdb/stat.html#stat_reset This actually brings up another question about transactions. I understand transactions work this way - cppdb::transaction tr(sql) sql << "INSERT INTO ......" << cppdb::exec sql << "INSERT INTO ......" << cppdb::exec tr.commit() What if you can't use the syntatic sugar but have to deal with statements directly? Ive tried cppdb::transaction tr(sql) cppdb::statement st = sql.prepare("..."); st.bind(...) st.bind(...) st.exec() cppdb::statement st2 = sql.prepare("...") st.bind(...) st.exec() tr.commit() This throws an exception saying sqlite3:cannot rollback transaction - SQL statements in progress What's the proper way? |