1 //
2 // Statement.h
3 //
4 // Library: Data
5 // Package: DataCore
6 // Module:  Statement
7 //
8 // Definition of the Statement 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_Statement_INCLUDED
18 #define Data_Statement_INCLUDED
19 
20 
21 #include "Poco/Data/Data.h"
22 #include "Poco/Data/StatementImpl.h"
23 #include "Poco/Data/Binding.h"
24 #include "Poco/Data/Range.h"
25 #include "Poco/Data/Bulk.h"
26 #include "Poco/Data/Row.h"
27 #include "Poco/Data/SimpleRowFormatter.h"
28 #include "Poco/SharedPtr.h"
29 #include "Poco/Mutex.h"
30 #include "Poco/ActiveMethod.h"
31 #include "Poco/ActiveResult.h"
32 #include "Poco/Format.h"
33 #include <algorithm>
34 
35 
36 namespace Poco {
37 namespace Data {
38 
39 
40 class AbstractBinding;
41 class AbstractExtraction;
42 class Session;
43 class Limit;
44 
45 
46 class Data_API Statement
47 	/// A Statement is used to execute SQL statements.
48 	/// It does not contain code of its own.
49 	/// Its main purpose is to forward calls to the concrete StatementImpl stored inside.
50 	/// Statement execution can be synchronous or asynchronous.
51 	/// Synchronous ececution is achieved through execute() call, while asynchronous is
52 	/// achieved through executeAsync() method call.
53 	/// An asynchronously executing statement should not be copied during the execution.
54 	///
55 	/// Note:
56 	///
57 	/// Once set as asynchronous through 'async' manipulator, statement remains
58 	/// asynchronous for all subsequent execution calls, both execute() and executeAsync().
59 	/// However, calling executAsync() on a synchronous statement shall execute
60 	/// asynchronously but without altering the underlying statement's synchronous nature.
61 	///
62 	/// Once asynchronous, a statement can be reverted back to synchronous state in two ways:
63 	///
64 	///   1) By calling setAsync(false)
65 	///   2) By means of 'sync' or 'reset' manipulators
66 	///
67 	/// See individual functions documentation for more details.
68 	///
69 	/// Statement owns the RowFormatter, which can be provided externaly through setFormatter()
70 	/// member function.
71 	/// If no formatter is externally supplied to the statement, the SimpleRowFormatter is lazy
72 	/// created and used.
73 {
74 public:
75 	typedef void (*Manipulator)(Statement&);
76 
77 	using Result = ActiveResult<std::size_t>;
78 	using ResultPtr = SharedPtr<Result>;
79 	using AsyncExecMethod = ActiveMethod<std::size_t, bool, StatementImpl>;
80 	using AsyncExecMethodPtr = SharedPtr<AsyncExecMethod>;
81 
82 	static const int WAIT_FOREVER = -1;
83 
84 	enum Storage
85 	{
86 		STORAGE_DEQUE   = StatementImpl::STORAGE_DEQUE_IMPL,
87 		STORAGE_VECTOR  = StatementImpl::STORAGE_VECTOR_IMPL,
88 		STORAGE_LIST    = StatementImpl::STORAGE_LIST_IMPL,
89 		STORAGE_UNKNOWN = StatementImpl::STORAGE_UNKNOWN_IMPL
90 	};
91 
92 	Statement(StatementImpl::Ptr pImpl);
93 		/// Creates the Statement.
94 
95 	explicit Statement(Session& session);
96 		/// Creates the Statement for the given Session.
97 		///
98 		/// The following:
99 		///
100 		///     Statement stmt(sess);
101 		///     stmt << "SELECT * FROM Table", ...
102 		///
103 		/// is equivalent to:
104 		///
105 		///     Statement stmt(sess << "SELECT * FROM Table", ...);
106 		///
107 		/// but in some cases better readable.
108 
109 	~Statement();
110 		/// Destroys the Statement.
111 
112 	Statement(const Statement& stmt);
113 		/// Copy constructor.
114 		/// If the statement has been executed asynchronously and has not been
115 		/// synchronized prior to copy operation (i.e. is copied while executing),
116 		/// this constructor shall synchronize it.
117 
118 	Statement(Statement&& other) noexcept;
119 		/// Move constructor.
120 
121 	Statement& operator = (const Statement& stmt);
122 		/// Assignment operator.
123 
124 	Statement& operator = (Statement&& stmt) noexcept;
125 		/// Move assignment.
126 
127 	void swap(Statement& other);
128 		/// Swaps the statement with another one.
129 
130 	template <typename T>
131 	Statement& operator << (const T& t)
132 		/// Concatenates data with the SQL statement string.
133 	{
134 		_pImpl->add(t);
135 		return *this;
136 	}
137 
138 	Statement& operator , (Manipulator manip);
139 		/// Handles manipulators, such as now, async, etc.
140 
141 	Statement& operator , (AbstractBinding::Ptr pBind);
142 		/// Registers the Binding with the Statement by calling addBind().
143 
144 	Statement& addBind(AbstractBinding::Ptr pBind);
145 		/// Registers a single binding with the statement.
146 
147 	void removeBind(const std::string& name);
148 		/// Removes the all the bindings with specified name from the statement.
149 
150 	Statement& operator , (AbstractBindingVec& bindVec);
151 		/// Registers the Binding vector with the Statement.
152 
153 	template <typename C>
addBinding(C & bindingCont,bool reset)154 	Statement& addBinding(C& bindingCont, bool reset)
155 		/// Registers binding container with the Statement.
156 	{
157 		if (reset) _pImpl->resetBinding();
158 		typename C::iterator itAB = bindingCont.begin();
159 		typename C::iterator itABEnd = bindingCont.end();
160 		for (; itAB != itABEnd; ++itAB) addBind(*itAB);
161 		return *this;
162 	}
163 
164 	template <typename C>
bind(const C & value)165 	Statement& bind(const C& value)
166 		/// Adds a binding to the Statement. This can be used to implement
167 		/// generic binding mechanisms and is a nicer syntax for:
168 		///
169 		///     statement , bind(value);
170 	{
171 		(*this) , Keywords::bind(value);
172 		return *this;
173 	}
174 
175 	Statement& operator , (AbstractExtraction::Ptr extract);
176 		/// Registers objects used for extracting data with the Statement by
177 		/// calling addExtract().
178 
179 	Statement& operator , (AbstractExtractionVec& extVec);
180 		/// Registers the extraction vector with the Statement.
181 		/// The vector is registered at position 0 (i.e. for the first returned data set).
182 
183 	Statement& operator , (AbstractExtractionVecVec& extVecVec);
184 		/// Registers the vector of extraction vectors with the Statement.
185 
186 	template <typename C>
addExtraction(C & val,bool reset)187 	Statement& addExtraction(C& val, bool reset)
188 		/// Registers extraction container with the Statement.
189 	{
190 		if (reset) _pImpl->resetExtraction();
191 		typename C::iterator itAE = val.begin();
192 		typename C::iterator itAEEnd = val.end();
193 		for (; itAE != itAEEnd; ++itAE) addExtract(*itAE);
194 		return *this;
195 	}
196 
197 	template <typename C>
addExtractions(C & val)198 	Statement& addExtractions(C& val)
199 		/// Registers container of extraction containers with the Statement.
200 	{
201 		_pImpl->resetExtraction();
202 		typename C::iterator itAEV = val.begin();
203 		typename C::iterator itAEVEnd = val.end();
204 		for (; itAEV != itAEVEnd; ++itAEV) addExtraction(*itAEV, false);
205 		return *this;
206 	}
207 
208 	Statement& addExtract(AbstractExtraction::Ptr pExtract);
209 		/// Registers a single extraction with the statement.
210 
211 	Statement& operator , (const Bulk& bulk);
212 		/// Sets the bulk execution mode (both binding and extraction) for this
213 		/// statement.Statement must not have any extractors or binders set at the
214 		/// time when this operator is applied.
215 		/// Failure to adhere to the above constraint shall result in
216 		/// InvalidAccessException.
217 
218 	Statement& operator , (BulkFnType);
219 		/// Sets the bulk execution mode (both binding and extraction) for this
220 		/// statement.Statement must not have any extractors or binders set at the
221 		/// time when this operator is applied.
222 		/// Additionally, this function requires limit to be set in order to
223 		/// determine the bulk size.
224 		/// Failure to adhere to the above constraints shall result in
225 		/// InvalidAccessException.
226 
227 	Statement& operator , (const Limit& extrLimit);
228 		/// Sets a limit on the maximum number of rows a select is allowed to return.
229 		///
230 		/// Set per default to zero to Limit::LIMIT_UNLIMITED, which disables the limit.
231 
232 	Statement& operator , (RowFormatter::Ptr pRowFformatter);
233 		/// Sets the row formatter for the statement.
234 
235 	Statement& operator , (const Range& extrRange);
236 		/// Sets a an extraction range for the maximum number of rows a select is allowed to return.
237 		///
238 		/// Set per default to Limit::LIMIT_UNLIMITED which disables the range.
239 
240 	Statement& operator , (char value);
241 		/// Adds the value to the list of values to be supplied to the SQL string formatting function.
242 
243 	Statement& operator , (Poco::UInt8 value);
244 		/// Adds the value to the list of values to be supplied to the SQL string formatting function.
245 
246 	Statement& operator , (Poco::Int8 value);
247 		/// Adds the value to the list of values to be supplied to the SQL string formatting function.
248 
249 	Statement& operator , (Poco::UInt16 value);
250 		/// Adds the value to the list of values to be supplied to the SQL string formatting function.
251 
252 	Statement& operator , (Poco::Int16 value);
253 		/// Adds the value to the list of values to be supplied to the SQL string formatting function.
254 
255 	Statement& operator , (Poco::UInt32 value);
256 		/// Adds the value to the list of values to be supplied to the SQL string formatting function.
257 
258 	Statement& operator , (Poco::Int32 value);
259 		/// Adds the value to the list of values to be supplied to the SQL string formatting function.
260 
261 #ifndef POCO_INT64_IS_LONG
262 	Statement& operator , (long value);
263 		/// Adds the value to the list of values to be supplied to the SQL string formatting function.
264 
265 	Statement& operator , (unsigned long value);
266 		/// Adds the value to the list of values to be supplied to the SQL string formatting function.
267 #endif
268 
269 	Statement& operator , (Poco::UInt64 value);
270 		/// Adds the value to the list of values to be supplied to the SQL string formatting function.
271 
272 	Statement& operator , (Poco::Int64 value);
273 		/// Adds the value to the list of values to be supplied to the SQL string formatting function.
274 
275 	Statement& operator , (double value);
276 		/// Adds the value to the list of values to be supplied to the SQL string formatting function.
277 
278 	Statement& operator , (float value);
279 		/// Adds the value to the list of values to be supplied to the SQL string formatting function.
280 
281 	Statement& operator , (bool value);
282 		/// Adds the value to the list of values to be supplied to the SQL string formatting function.
283 
284 	Statement& operator , (const std::string& value);
285 		/// Adds the value to the list of values to be supplied to the SQL string formatting function.
286 
287 	Statement& operator , (const char* value);
288 		/// Adds the value to the list of values to be supplied to the SQL string formatting function.
289 
290 	const std::string& toString() const;
291 		/// Creates a string from the accumulated SQL statement.
292 
293 	std::size_t execute(bool reset = true);
294 		/// Executes the statement synchronously or asynchronously.
295 		/// Stops when either a limit is hit or the whole statement was executed.
296 		/// Returns the number of rows extracted from the database (for statements
297 		/// returning data) or number of rows affected (for all other statements).
298 		/// If reset is true (default), associated storage is reset and reused.
299 		/// Otherwise, the results from this execution step are appended.
300 		/// Reset argument has no meaning for unlimited statements that return all rows.
301 		/// If isAsync() returns  true, the statement is executed asynchronously
302 		/// and the return value from this function is zero.
303 		/// The result of execution (i.e. number of returned or affected rows) can be
304 		/// obtained by calling wait() on the statement at a later point in time.
305 
306 	const Result& executeAsync(bool reset = true);
307 		/// Executes the statement asynchronously.
308 		/// Stops when either a limit is hit or the whole statement was executed.
309 		/// Returns immediately. Calling wait() (on either the result returned from this
310 		/// call or the statement itself) returns the number of rows extracted or number
311 		/// of rows affected by the statement execution.
312 		/// When executed on a synchronous statement, this method does not alter the
313 		/// statement's synchronous nature.
314 
315 	void setAsync(bool async = true);
316 		/// Sets the asynchronous flag. If this flag is true, executeAsync() is called
317 		/// from the now() manipulator. This setting does not affect the statement's
318 		/// capability to be executed synchronously by directly calling execute().
319 
320 	bool isAsync() const;
321 		/// Returns true if statement was marked for asynchronous execution.
322 
323 	std::size_t wait(long milliseconds = WAIT_FOREVER);
324 		/// Waits for the execution completion for asynchronous statements or
325 		/// returns immediately for synchronous ones. The return value for
326 		/// asynchronous statement is the execution result (i.e. number of
327 		/// rows retrieved). For synchronous statements, the return value is zero.
328 
329 	bool initialized();
330 		/// Returns true if the statement was initialized (i.e. not executed yet).
331 
332 	bool paused();
333 		/// Returns true if the statement was paused (a range limit stopped it
334 		/// and there is more work to do).
335 
336 	bool done();
337 		/// Returns true if the statement was completely executed or false if a range limit stopped it
338 		/// and there is more work to do. When no limit is set, it will always return true after calling execute().
339 
340 	Statement& reset(Session& session);
341 		/// Resets the Statement so that it can be filled with a new SQL command.
342 
343 	bool canModifyStorage();
344 		/// Returns true if statement is in a state that allows the internal storage to be modified.
345 
346 	Storage storage() const;
347 		/// Returns the internal storage type for the statement.
348 
349 	void setStorage(const std::string& storage);
350 		/// Sets the internal storage type for the statement.
351 
352 	const std::string& getStorage() const;
353 		/// Returns the internal storage type for the statement.
354 
355 	std::size_t columnsExtracted(int dataSet = StatementImpl::USE_CURRENT_DATA_SET) const;
356 		/// Returns the number of columns returned for current data set.
357 		/// Default value indicates current data set (if any).
358 
359 	std::size_t rowsExtracted(int dataSet = StatementImpl::USE_CURRENT_DATA_SET) const;
360 		/// Returns the number of rows returned for current data set during last statement
361 		/// execution. Default value indicates current data set (if any).
362 
363 	std::size_t subTotalRowCount(int dataSet = StatementImpl::USE_CURRENT_DATA_SET) const;
364 		/// Returns the number of rows extracted so far for the data set.
365 		/// Default value indicates current data set (if any).
366 
367 	std::size_t extractionCount() const;
368 		/// Returns the number of extraction storage buffers associated
369 		/// with the current data set.
370 
371 	std::size_t dataSetCount() const;
372 		/// Returns the number of data sets associated with the statement.
373 
374 	std::size_t nextDataSet();
375 		/// Returns the index of the next data set.
376 
377 	std::size_t previousDataSet();
378 		/// Returns the index of the previous data set.
379 
380 	bool hasMoreDataSets() const;
381 		/// Returns false if the current data set index points to the last
382 		/// data set. Otherwise, it returns true.
383 
384 	void setRowFormatter(RowFormatter::Ptr pRowFormatter);
385 		/// Sets the row formatter for this statement.
386 		/// Statement takes the ownership of the formatter.
387 
388 protected:
389 	using ImplPtr = StatementImpl::Ptr;
390 
391 	const AbstractExtractionVec& extractions() const;
392 		/// Returns the extractions vector.
393 
394 	const MetaColumn& metaColumn(std::size_t pos) const;
395 		/// Returns the type for the column at specified position.
396 
397 	const MetaColumn& metaColumn(const std::string& name) const;
398 		/// Returns the type for the column with specified name.
399 
400 	 bool isNull(std::size_t col, std::size_t row) const;
401 		/// Returns true if the current row value at column pos is null.
402 
403 	 bool isBulkExtraction() const;
404 		/// Returns true if this statement extracts data in bulk.
405 
406 	ImplPtr impl() const;
407 		/// Returns pointer to statement implementation.
408 
409 	const RowFormatter::Ptr& getRowFormatter();
410 		/// Returns the row formatter for this statement.
411 
412 	Session session();
413 		/// Returns the underlying session.
414 
415 private:
416 	const Result& doAsyncExec(bool reset = true);
417 		/// Asynchronously executes the statement.
418 
419 	template <typename T>
commaPODImpl(const T & val)420 	Statement& commaPODImpl(const T& val)
421 	{
422 		_arguments.push_back(val);
423 		return *this;
424 	}
425 
426 	StatementImpl::Ptr _pImpl;
427 
428 	// asynchronous execution related members
429 	bool                _async;
430 	mutable ResultPtr   _pResult;
431 	Mutex               _mutex;
432 	AsyncExecMethodPtr  _pAsyncExec;
433 	std::vector<Any>    _arguments;
434 	RowFormatter::Ptr   _pRowFormatter;
435 	mutable std::string _stmtString;
436 };
437 
438 //
439 // inlines
440 
subTotalRowCount(int dataSet)441 inline std::size_t Statement::subTotalRowCount(int dataSet) const
442 {
443 	return _pImpl->subTotalRowCount(dataSet);
444 }
445 
446 
447 namespace Keywords {
448 
449 
450 //
451 // Manipulators
452 //
453 
now(Statement & statement)454 inline void Data_API now(Statement& statement)
455 	/// Enforces immediate execution of the statement.
456 	/// If _isAsync flag has been set, execution is invoked asynchronously.
457 {
458 	statement.execute();
459 }
460 
461 
sync(Statement & statement)462 inline void Data_API sync(Statement& statement)
463 	/// Sets the _isAsync flag to false, signalling synchronous execution.
464 	/// Synchronous execution is default, so specifying this manipulator
465 	/// only makes sense if async() was called for the statement before.
466 {
467 	statement.setAsync(false);
468 }
469 
470 
async(Statement & statement)471 inline void Data_API async(Statement& statement)
472 	/// Sets the _async flag to true, signalling asynchronous execution.
473 {
474 	statement.setAsync(true);
475 }
476 
477 
deque(Statement & statement)478 inline void Data_API deque(Statement& statement)
479 	/// Sets the internal storage to std::deque.
480 	/// std::deque is default storage, so specifying this manipulator
481 	/// only makes sense if list() or deque() were called for the statement before.
482 {
483 	if (!statement.canModifyStorage())
484 		throw InvalidAccessException("Storage not modifiable.");
485 
486 	statement.setStorage("deque");
487 }
488 
489 
vector(Statement & statement)490 inline void Data_API vector(Statement& statement)
491 	/// Sets the internal storage to std::vector.
492 {
493 	if (!statement.canModifyStorage())
494 		throw InvalidAccessException("Storage not modifiable.");
495 
496 	statement.setStorage("vector");
497 }
498 
499 
list(Statement & statement)500 inline void Data_API list(Statement& statement)
501 	/// Sets the internal storage to std::list.
502 {
503 	if (!statement.canModifyStorage())
504 		throw InvalidAccessException("Storage not modifiable.");
505 
506 	statement.setStorage("list");
507 }
508 
509 
reset(Statement & statement)510 inline void Data_API reset(Statement& statement)
511 	/// Sets all internal settings to their respective default values.
512 {
513 	if (!statement.canModifyStorage())
514 		throw InvalidAccessException("Storage not modifiable.");
515 
516 	statement.setStorage("deque");
517 	statement.setAsync(false);
518 }
519 
520 
521 } // namespace Keywords
522 
523 
524 //
525 // inlines
526 //
527 
528 inline Statement& Statement::operator , (RowFormatter::Ptr pRowFformatter)
529 {
530 	_pRowFormatter = pRowFformatter;
531 	return *this;
532 }
533 
534 
535 inline Statement& Statement::operator , (char value)
536 {
537 	return commaPODImpl(value);
538 }
539 
540 
541 inline Statement& Statement::operator , (Poco::UInt8 value)
542 {
543 	return commaPODImpl(value);
544 }
545 
546 
547 inline Statement& Statement::operator , (Poco::Int8 value)
548 {
549 	return commaPODImpl(value);
550 }
551 
552 
553 inline Statement& Statement::operator , (Poco::UInt16 value)
554 {
555 	return commaPODImpl(value);
556 }
557 
558 
559 inline Statement& Statement::operator , (Poco::Int16 value)
560 {
561 	return commaPODImpl(value);
562 }
563 
564 
565 inline Statement& Statement::operator , (Poco::UInt32 value)
566 {
567 	return commaPODImpl(value);
568 }
569 
570 
571 inline Statement& Statement::operator , (Poco::Int32 value)
572 {
573 	return commaPODImpl(value);
574 }
575 
576 
577 #ifndef POCO_INT64_IS_LONG
578 inline Statement& Statement::operator , (long value)
579 {
580 	return commaPODImpl(value);
581 }
582 
583 
584 inline Statement& Statement::operator , (unsigned long value)
585 {
586 	return commaPODImpl(value);
587 }
588 #endif
589 
590 
591 inline Statement& Statement::operator , (Poco::UInt64 value)
592 {
593 	return commaPODImpl(value);
594 }
595 
596 
597 inline Statement& Statement::operator , (Poco::Int64 value)
598 {
599 	return commaPODImpl(value);
600 }
601 
602 
603 inline Statement& Statement::operator , (double value)
604 {
605 	return commaPODImpl(value);
606 }
607 
608 
609 inline Statement& Statement::operator , (float value)
610 {
611 	return commaPODImpl(value);
612 }
613 
614 
615 inline Statement& Statement::operator , (bool value)
616 {
617 	return commaPODImpl(value);
618 }
619 
620 
621 inline Statement& Statement::operator , (const std::string& value)
622 {
623 	return commaPODImpl(value);
624 }
625 
626 
627 inline Statement& Statement::operator , (const char* value)
628 {
629 	return commaPODImpl(std::string(value));
630 }
631 
632 
removeBind(const std::string & name)633 inline void Statement::removeBind(const std::string& name)
634 {
635 	_pImpl->removeBind(name);
636 }
637 
638 
639 inline Statement& Statement::operator , (AbstractBinding::Ptr pBind)
640 {
641 	return addBind(pBind);
642 }
643 
644 
645 inline Statement& Statement::operator , (AbstractBindingVec& bindVec)
646 {
647 	return addBinding(bindVec, false);
648 }
649 
650 
651 inline Statement& Statement::operator , (AbstractExtraction::Ptr pExtract)
652 {
653 	return addExtract(pExtract);
654 }
655 
656 
657 inline Statement& Statement::operator , (AbstractExtractionVec& extVec)
658 {
659 	return addExtraction(extVec, false);
660 }
661 
662 
663 inline Statement& Statement::operator , (AbstractExtractionVecVec& extVecVec)
664 {
665 	return addExtractions(extVecVec);
666 }
667 
668 
impl()669 inline Statement::ImplPtr Statement::impl() const
670 {
671 	return _pImpl;
672 }
673 
674 
toString()675 inline const std::string& Statement::toString() const
676 {
677 	return _stmtString = _pImpl->toString();
678 }
679 
extractions()680 inline const AbstractExtractionVec& Statement::extractions() const
681 {
682 	return _pImpl->extractions();
683 }
684 
685 
metaColumn(std::size_t pos)686 inline const MetaColumn& Statement::metaColumn(std::size_t pos) const
687 {
688 	return _pImpl->metaColumn(pos);
689 }
690 
691 
metaColumn(const std::string & name)692 inline const MetaColumn& Statement::metaColumn(const std::string& name) const
693 {
694 	return _pImpl->metaColumn(name);
695 }
696 
697 
setStorage(const std::string & storage)698 inline void Statement::setStorage(const std::string& storage)
699 {
700 	_pImpl->setStorage(storage);
701 }
702 
703 
extractionCount()704 inline std::size_t Statement::extractionCount() const
705 {
706 	return _pImpl->extractionCount();
707 }
708 
709 
columnsExtracted(int dataSet)710 inline std::size_t Statement::columnsExtracted(int dataSet) const
711 {
712 	return _pImpl->columnsExtracted(dataSet);
713 }
714 
715 
rowsExtracted(int dataSet)716 inline std::size_t Statement::rowsExtracted(int dataSet) const
717 {
718 	return _pImpl->rowsExtracted(dataSet);
719 }
720 
721 
dataSetCount()722 inline std::size_t Statement::dataSetCount() const
723 {
724 	return _pImpl->dataSetCount();
725 }
726 
727 
nextDataSet()728 inline std::size_t Statement::nextDataSet()
729 {
730 	return _pImpl->activateNextDataSet();
731 }
732 
733 
previousDataSet()734 inline std::size_t Statement::previousDataSet()
735 {
736 	return _pImpl->activatePreviousDataSet();
737 }
738 
739 
hasMoreDataSets()740 inline bool Statement::hasMoreDataSets() const
741 {
742 	return _pImpl->hasMoreDataSets();
743 }
744 
745 
storage()746 inline Statement::Storage Statement::storage() const
747 {
748 	return static_cast<Storage>(_pImpl->getStorage());
749 }
750 
751 
canModifyStorage()752 inline bool Statement::canModifyStorage()
753 {
754 	return (0 == extractionCount()) && (initialized() || done());
755 }
756 
757 
initialized()758 inline bool Statement::initialized()
759 {
760 	return _pImpl->getState() == StatementImpl::ST_INITIALIZED;
761 }
762 
763 
paused()764 inline bool Statement::paused()
765 {
766 	return _pImpl->getState() == StatementImpl::ST_PAUSED;
767 }
768 
769 
done()770 inline bool Statement::done()
771 {
772 	return _pImpl->getState() == StatementImpl::ST_DONE;
773 }
774 
775 
isNull(std::size_t col,std::size_t row)776 inline bool Statement::isNull(std::size_t col, std::size_t row) const
777 {
778 	return _pImpl->isNull(col, row);
779 }
780 
781 
isBulkExtraction()782 inline bool Statement::isBulkExtraction() const
783 {
784 	return _pImpl->isBulkExtraction();
785 }
786 
787 
isAsync()788 inline bool Statement::isAsync() const
789 {
790 	return _async;
791 }
792 
793 
setRowFormatter(RowFormatter::Ptr pRowFormatter)794 inline void Statement::setRowFormatter(RowFormatter::Ptr pRowFormatter)
795 {
796 	_pRowFormatter = pRowFormatter;
797 }
798 
799 
getRowFormatter()800 inline const RowFormatter::Ptr& Statement::getRowFormatter()
801 {
802 	if (!_pRowFormatter) _pRowFormatter = new SimpleRowFormatter;
803 	return _pRowFormatter;
804 }
805 
806 
swap(Statement & s1,Statement & s2)807 inline void swap(Statement& s1, Statement& s2)
808 {
809 	s1.swap(s2);
810 }
811 
812 
813 } } // namespace Poco::Data
814 
815 
816 namespace std
817 {
818 	template<>
819 	inline void swap<Poco::Data::Statement>(Poco::Data::Statement& s1, Poco::Data::Statement& s2) noexcept
820 		/// Full template specalization of std:::swap for Statement
821 	{
822 		s1.swap(s2);
823 	}
824 }
825 
826 
827 #endif // Data_Statement_INCLUDED
828