00001 // 00002 // File: src/statement.cpp 00003 // Object: Implementation of the statement object 00004 // Project: http://www.m2osw.com/odbcpp 00005 // Author: alexis_wilke@sourceforge.net 00006 // 00007 // Copyright (C) 2008 Made to Order Software Corp. 00008 // 00009 // This program is free software: you can redistribute it and/or modify 00010 // it under the terms of the GNU General Public License as published by 00011 // the Free Software Foundation, either version 3 of the License, or 00012 // (at your option) any later version. 00013 // 00014 // This program is distributed in the hope that it will be useful, 00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 // GNU General Public License for more details. 00018 // 00019 // You should have received a copy of the GNU General Public License 00020 // along with this program. If not, see <http://www.gnu.org/licenses/> 00021 // or <http://gpl3.m2osw.com/>. 00022 // 00023 00024 #include "odbcpp/odbcpp.h" 00025 #include <iostream> 00026 00027 00028 namespace odbcpp 00029 { 00030 00031 00056 statement::statement(connection& conn) : 00057 handle(SQL_HANDLE_STMT), 00058 f_connection(&conn), 00059 f_has_data(false), 00060 f_no_direct_fetch(false) 00061 { 00062 // we right away allocate a connection 00063 // throw if it fails 00064 check(SQLAllocHandle(f_handle_type, f_connection->get_handle(), &f_handle), f_connection); 00065 } 00066 00067 00068 00079 void statement::set_attr(SQLINTEGER attr, SQLINTEGER integer) 00080 { 00081 // TODO: do we need to use the SQL_IS_[U]INTEGER types? 00082 check(SQLSetStmtAttr(f_handle, attr, int_to_ptr(integer), 0)); 00083 } 00084 00085 00097 void statement::set_attr(SQLINTEGER attr, SQLPOINTER ptr, SQLINTEGER length) 00098 { 00099 // TODO: if ptr is a pointer to a known structure, length should 00100 // be set to SQL_IS_POINTER 00101 check(SQLSetStmtAttr(f_handle, attr, ptr, length)); 00102 } 00103 00104 00105 00130 void statement::set_no_direct_fetch(bool no_direct_fetch) 00131 { 00132 f_no_direct_fetch = no_direct_fetch; 00133 } 00134 00135 00136 00156 void statement::execute(const std::string& order) 00157 { 00158 f_has_data = false; 00159 00160 check(SQLExecDirect(f_handle, 00161 const_cast<SQLCHAR *>(reinterpret_cast<const SQLCHAR *>(order.c_str())), 00162 SQL_NTS)); 00163 00164 f_has_data = true; 00165 } 00166 00167 00182 void statement::has_data() const 00183 { 00184 if(!f_has_data) { 00185 diagnostic d(odbcpp_error::ODBCPP_NO_DATA, std::string("no SQL command was executed, the statement has no data available")); 00186 throw odbcpp_error(d); 00187 } 00188 } 00189 00190 00200 void statement::begin() 00201 { 00202 execute("BEGIN"); 00203 } 00204 00205 00215 void statement::commit() 00216 { 00217 execute("COMMIT"); 00218 } 00219 00220 00230 void statement::rollback() 00231 { 00232 execute("ROLLBACK"); 00233 } 00234 00235 00250 void statement::cancel() 00251 { 00252 has_data(); 00253 f_has_data = false; 00254 00255 check(SQLCancel(f_handle)); 00256 } 00257 00258 00273 void statement::close_cursor() 00274 { 00275 has_data(); 00276 f_has_data = false; 00277 00278 check(SQLCloseCursor(f_handle)); 00279 } 00280 00281 00282 00293 SQLLEN statement::cols() const 00294 { 00295 SQLSMALLINT count; 00296 00297 has_data(); 00298 00299 check(SQLNumResultCols(const_cast<SQLHANDLE>(f_handle), &count)); 00300 00301 return static_cast<SQLLEN>(count); 00302 } 00303 00304 00305 00316 SQLLEN statement::rows() const 00317 { 00318 SQLLEN count; 00319 00320 has_data(); 00321 00322 check(SQLRowCount(const_cast<SQLHANDLE>(f_handle), &count)); 00323 00324 return count; 00325 } 00326 00327 00328 00376 bool statement::fetch(record_base& rec, SQLSMALLINT orientation, SQLLEN offset) 00377 { 00378 SQLRETURN return_code; 00379 00380 // in case the record is not bound yet, do it now 00381 rec.bind(*this); 00382 00383 // make sure we sent an SQL statement 00384 has_data(); 00385 00386 // fetch the row 00387 if(orientation == SQL_FETCH_NEXT && !f_no_direct_fetch) { 00388 return_code = SQLFetch(f_handle); 00389 } 00390 else { 00391 return_code = SQLFetchScroll(f_handle, orientation, offset); 00392 } 00393 if(return_code == SQL_NO_DATA) { 00394 return false; 00395 } 00396 00397 // 00398 // TODO: handle the case were we have a buffer truncation 00399 // 00400 // i.e. we would need to call rec.bind() again and try to 00401 // fetch again... 00402 // 00403 00404 // check the returned code, if error, throw 00405 check(return_code); 00406 00407 // some data may need to be copied... 00408 rec.finalize(); 00409 00410 // it worked! 00411 return true; 00412 } 00413 00414 00415 00416 00452 } // namespace odbcpp