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()162 inline 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()170 inline AbstractBinding::BinderPtr ODBCStatementImpl::binder()
171 {
172 	poco_assert_dbg (!_pBinder.isNull());
173 	return _pBinder;
174 }
175 
176 
columnsReturned()177 inline 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()185 inline bool ODBCStatementImpl::hasData() const
186 {
187 	return (columnsReturned() > 0);
188 }
189 
190 
nextRowReady()191 inline bool ODBCStatementImpl::nextRowReady() const
192 {
193 	return (!Utility::isError(_nextResponse));
194 }
195 
196 
canCompile()197 inline 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