1 // 2 // ODBCStatementImpl.h 3 // 4 // Library: Data/ODBC 5 // Package: ODBC 6 // Module: ODBCStatementImpl 7 // 8 // Definition of the ODBCStatementImpl class. 9 // 10 // Copyright (c) 2006, Applied Informatics Software Engineering GmbH. 11 // and Contributors. 12 // 13 // SPDX-License-Identifier: BSL-1.0 14 // 15 16 17 #ifndef Data_ODBC_ODBCStatementImpl_INCLUDED 18 #define Data_ODBC_ODBCStatementImpl_INCLUDED 19 20 21 #include "Poco/Data/ODBC/ODBC.h" 22 #include "Poco/Data/ODBC/SessionImpl.h" 23 #include "Poco/Data/ODBC/Binder.h" 24 #include "Poco/Data/ODBC/Extractor.h" 25 #include "Poco/Data/ODBC/Preparator.h" 26 #include "Poco/Data/ODBC/ODBCMetaColumn.h" 27 #include "Poco/Data/StatementImpl.h" 28 #include "Poco/Data/Column.h" 29 #include "Poco/SharedPtr.h" 30 #include "Poco/Format.h" 31 #include <sstream> 32 #ifdef POCO_OS_FAMILY_WINDOWS 33 #include <windows.h> 34 #endif 35 #include <sqltypes.h> 36 37 38 namespace Poco { 39 namespace Data { 40 namespace ODBC { 41 42 43 class ODBC_API ODBCStatementImpl: public Poco::Data::StatementImpl 44 /// Implements statement functionality needed for ODBC 45 { 46 public: 47 ODBCStatementImpl(SessionImpl& rSession); 48 /// Creates the ODBCStatementImpl. 49 50 ~ODBCStatementImpl(); 51 /// Destroys the ODBCStatementImpl. 52 53 protected: 54 std::size_t columnsReturned() const; 55 /// Returns number of columns returned by query. 56 57 int affectedRowCount() const; 58 /// Returns the number of affected rows. 59 /// Used to find out the number of rows affected by insert or update. 60 61 const MetaColumn& metaColumn(std::size_t pos) const; 62 /// Returns column meta data. 63 64 bool hasNext(); 65 /// Returns true if a call to next() will return data. 66 67 std::size_t next(); 68 /// Retrieves the next row or set of rows from the resultset. 69 /// Returns the number of rows retrieved. 70 /// Will throw, if the resultset is empty. 71 72 bool canBind() const; 73 /// Returns true if a valid statement is set and we can bind. 74 75 bool canCompile() const; 76 /// Returns true if another compile is possible. 77 78 void compileImpl(); 79 /// Compiles the statement, doesn't bind yet. 80 /// Does nothing if the statement has already been compiled. 81 82 void bindImpl(); 83 /// Binds all parameters and executes the statement. 84 85 AbstractExtraction::ExtractorPtr extractor(); 86 /// Returns the concrete extractor used by the statement. 87 88 AbstractBinding::BinderPtr binder(); 89 /// Returns the concrete binder used by the statement. 90 91 std::string nativeSQL(); 92 /// Returns the SQL string as modified by the driver. 93 94 private: 95 typedef Poco::Data::AbstractBindingVec Bindings; 96 typedef Poco::SharedPtr<Binder> BinderPtr; 97 typedef Poco::Data::AbstractExtractionVec Extractions; 98 typedef Poco::SharedPtr<Preparator> PreparatorPtr; 99 typedef std::vector<PreparatorPtr> PreparatorVec; 100 typedef Poco::SharedPtr<Extractor> ExtractorPtr; 101 typedef std::vector<ExtractorPtr> ExtractorVec; 102 typedef std::vector<ODBCMetaColumn*> ColumnPtrVec; 103 typedef std::vector<ColumnPtrVec> ColumnPtrVecVec; 104 105 static const std::string INVALID_CURSOR_STATE; 106 107 void clear(); 108 /// Closes the cursor and resets indicator variables. 109 110 void doBind(); 111 /// Binds parameters. 112 113 void makeInternalExtractors(); 114 /// Creates internal extractors if none were supplied from the user. 115 116 bool isStoredProcedure() const; 117 /// Returns true if SQL is a stored procedure call. 118 119 void doPrepare(); 120 /// Prepares placeholders for data returned by statement. 121 /// It is called during statement compilation for SQL statements 122 /// returning data. For stored procedures returning datasets, 123 /// it is called upon the first check for data availability 124 /// (see hasNext() function). 125 126 bool hasData() const; 127 /// Returns true if statement returns data. 128 129 void makeStep(); 130 /// Fetches the next row of data. 131 132 bool nextRowReady() const; 133 /// Returns true if there is a row fetched but not yet extracted. 134 135 void putData(); 136 /// Called whenever SQLExecute returns SQL_NEED_DATA. This is expected 137 /// behavior for PB_AT_EXEC binding mode. 138 139 void getData(); 140 141 void addPreparator(); 142 void fillColumns(); 143 void checkError(SQLRETURN rc, const std::string& msg=""); 144 145 const SQLHDBC& _rConnection; 146 const StatementHandle _stmt; 147 PreparatorVec _preparations; 148 BinderPtr _pBinder; 149 ExtractorVec _extractors; 150 bool _stepCalled; 151 int _nextResponse; 152 ColumnPtrVecVec _columnPtrs; 153 bool _prepared; 154 mutable std::size_t _affectedRowCount; 155 bool _canCompile; 156 }; 157 158 159 // 160 // inlines 161 // extractor()162inline AbstractExtraction::ExtractorPtr ODBCStatementImpl::extractor() 163 { 164 poco_assert_dbg (currentDataSet() < _extractors.size()); 165 poco_assert_dbg (_extractors[currentDataSet()]); 166 return _extractors[currentDataSet()]; 167 } 168 169 binder()170inline AbstractBinding::BinderPtr ODBCStatementImpl::binder() 171 { 172 poco_assert_dbg (!_pBinder.isNull()); 173 return _pBinder; 174 } 175 176 columnsReturned()177inline std::size_t ODBCStatementImpl::columnsReturned() const 178 { 179 poco_assert_dbg (currentDataSet() < _preparations.size()); 180 poco_assert_dbg (_preparations[currentDataSet()]); 181 return static_cast<std::size_t>(_preparations[currentDataSet()]->columns()); 182 } 183 184 hasData()185inline bool ODBCStatementImpl::hasData() const 186 { 187 return (columnsReturned() > 0); 188 } 189 190 nextRowReady()191inline bool ODBCStatementImpl::nextRowReady() const 192 { 193 return (!Utility::isError(_nextResponse)); 194 } 195 196 canCompile()197inline bool ODBCStatementImpl::canCompile() const 198 { 199 return _canCompile; 200 } 201 202 203 } } } // namespace Poco::Data::ODBC 204 205 206 #endif // Data_ODBC_ODBCStatementImpl_INCLUDED 207