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