/usr/include/Poco/Data/StatementImpl.h is in libpoco-dev 1.8.0.1-1ubuntu4.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 | //
// StatementImpl.h
//
// Library: Data
// Package: DataCore
// Module: StatementImpl
//
// Definition of the StatementImpl class.
//
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#ifndef Data_StatementImpl_INCLUDED
#define Data_StatementImpl_INCLUDED
#include "Poco/Data/Data.h"
#include "Poco/Data/AbstractBinding.h"
#include "Poco/Data/AbstractExtraction.h"
#include "Poco/Data/Range.h"
#include "Poco/Data/Bulk.h"
#include "Poco/Data/Column.h"
#include "Poco/Data/Extraction.h"
#include "Poco/Data/BulkExtraction.h"
#include "Poco/Data/SessionImpl.h"
#include "Poco/RefCountedObject.h"
#include "Poco/String.h"
#include "Poco/Format.h"
#include "Poco/Exception.h"
#include <vector>
#include <list>
#include <deque>
#include <string>
#include <sstream>
namespace Poco {
namespace Data {
class Data_API StatementImpl
/// StatementImpl interface that subclasses must implement to define database dependent query execution.
///
/// StatementImpl's are noncopyable.
{
public:
typedef Poco::SharedPtr<StatementImpl> Ptr;
enum State
{
ST_INITIALIZED,
ST_COMPILED,
ST_BOUND,
ST_PAUSED,
ST_DONE,
ST_RESET
};
enum Storage
{
STORAGE_DEQUE_IMPL,
STORAGE_VECTOR_IMPL,
STORAGE_LIST_IMPL,
STORAGE_UNKNOWN_IMPL
};
enum BulkType
{
BULK_UNDEFINED,
/// Bulk mode not defined yet.
BULK_BINDING,
/// Binding in bulk mode.
/// If extraction is present in the same statement,
/// it must also be bulk.
BULK_EXTRACTION,
/// Extraction in bulk mode.
/// If binding is present in the same statement,
/// it must also be bulk.
BULK_FORBIDDEN
/// Bulk forbidden.
/// Happens when the statement has already been
/// configured as non-bulk.
};
static const std::string DEQUE;
static const std::string VECTOR;
static const std::string LIST;
static const std::string UNKNOWN;
static const int USE_CURRENT_DATA_SET = -1;
StatementImpl(SessionImpl& rSession);
/// Creates the StatementImpl.
virtual ~StatementImpl();
/// Destroys the StatementImpl.
template <typename T>
void add(const T& t)
/// Appends SQL statement (fragments).
{
_ostr << t;
}
void addBind(AbstractBinding::Ptr pBinding);
/// Registers the Binding with the StatementImpl.
void removeBind(const std::string& name);
/// Unregisters all the bindings having specified name with the StatementImpl.
/// Bindings are released and, if this class was the sole owner, deleted.
void addExtract(AbstractExtraction::Ptr pExtraction);
/// Registers objects used for extracting data with the StatementImpl.
void setExtractionLimit(const Limit& extrLimit);
/// Changes the extractionLimit to extrLimit.
/// Per default no limit (EXTRACT_UNLIMITED) is set.
std::string toString() const;
/// Create a string version of the SQL statement.
std::size_t execute(const bool& reset = true);
/// Executes a statement. Returns the number of rows
/// extracted for statements returning data or number of rows
/// affected for all other statements (insert, update, delete).
/// If reset is true (default), the underlying bound storage is
/// reset and reused. In case of containers, this means they are
/// cleared and resized to accomodate the number of rows returned by
/// this execution step. When reset is false, data is appended to the
/// bound containers during multiple execute calls.
void reset();
/// Resets the statement, so that we can reuse all bindings and re-execute again.
State getState() const;
/// Returns the state of the Statement.
void setStorage(Storage storage);
/// Sets the storage type for this statement;
void setStorage(const std::string& storage);
/// Sets the storage type for this statement;
Storage getStorage() const;
/// Returns the storage type for this statement.
std::size_t extractionCount() const;
/// Returns the number of extraction storage buffers associated
/// with the statement.
std::size_t dataSetCount() const;
/// Returns the number of data sets associated with the statement.
protected:
virtual std::size_t columnsReturned() const = 0;
/// Returns number of columns returned by query.
virtual int affectedRowCount() const = 0;
/// Returns the number of affected rows.
/// Used to find out the number of rows affected by insert, delete or update.
///
/// Some back-ends may return a negative number in certain circumstances (e.g.
/// some ODBC drivers when this function is called after a select statement
/// execution).
virtual const MetaColumn& metaColumn(std::size_t pos) const = 0;
/// Returns column meta data.
const MetaColumn& metaColumn(const std::string& name) const;
/// Returns column meta data.
virtual bool hasNext() = 0;
/// Returns true if a call to next() will return data.
///
/// Note that the implementation must support
/// several consecutive calls to hasNext without data getting lost,
/// ie. hasNext(); hasNext(); next() must be equal to hasNext(); next();
virtual std::size_t next() = 0;
/// Retrieves the next row or set of rows from the resultset and
/// returns the number of rows retreved.
///
/// Will throw, if the resultset is empty.
/// Expects the statement to be compiled and bound.
virtual bool canBind() const = 0;
/// Returns true if another bind is possible.
virtual bool canCompile() const = 0;
/// Returns true if another compile is possible.
virtual void compileImpl() = 0;
/// Compiles the statement, doesn't bind yet.
virtual void bindImpl() = 0;
/// Binds parameters.
virtual AbstractExtraction::ExtractorPtr extractor() = 0;
/// Returns the concrete extractor used by the statement.
const AbstractExtractionVec& extractions() const;
/// Returns the const reference to extractions vector.
AbstractExtractionVec& extractions();
/// Returns the reference to extractions vector.
void fixupExtraction();
/// Sets the AbstractExtractor at the extractors.
Limit::SizeT getExtractionLimit();
/// Returns the extraction limit value.
const Limit& extractionLimit() const;
/// Returns the extraction limit.
std::size_t columnsExtracted(int dataSet = USE_CURRENT_DATA_SET) const;
/// Returns the number of columns that the extractors handle.
std::size_t rowsExtracted(int dataSet = USE_CURRENT_DATA_SET) const;
/// Returns the number of rows extracted for current data set.
/// Default value (USE_CURRENT_DATA_SET) indicates current data set (if any).
std::size_t subTotalRowCount(int dataSet = USE_CURRENT_DATA_SET) const;
/// Returns the number of rows extracted so far for the data set.
/// Default value indicates current data set (if any).
void makeExtractors(std::size_t count);
/// Determines the type of the internal extraction container and
/// calls the extraction creation function (addInternalExtract)
/// with appropriate data type and container type arguments.
///
/// This function is only called in cases when there is data
/// returned by query, but no data storage supplied by user.
///
/// The type of the internal container is determined in the
/// following order:
/// 1. If statement has the container type set, the type is used.
/// 2. If statement does not have the container type set,
/// session is queried for container type setting. If the
/// session container type setting is found, it is used.
/// 3. If neither session nor statement have the internal
/// container type set, std::deque is used.
///
/// Supported internal extraction container types are:
/// - std::deque (default)
/// - std::vector
/// - std::list
SessionImpl& session();
/// Rteurns session associated with this statement.
virtual AbstractBinding::BinderPtr binder() = 0;
/// Returns the concrete binder used by the statement.
const AbstractBindingVec& bindings() const;
/// Returns the const reference to bindings vector.
AbstractBindingVec& bindings();
/// Returns the reference to bindings.
void fixupBinding();
/// Sets the AbstractBinder at the bindings.
void resetBinding();
/// Resets binding so it can be reused again.
virtual bool isStoredProcedure() const;
/// Returns true if the statement is stored procedure.
/// Used as a help to determine whether to automatically create the
/// internal extractions when no outside extraction is supplied.
/// The reason for this function is to prevent unnecessary internal
/// extraction creation in cases (behavior exhibited by some ODBC drivers)
/// when there is data available from the stored procedure call
/// statement execution but no external extraction is supplied (as is
/// usually the case when stored procedures are called). In such cases
/// no storage is needed because output parameters serve as storage.
/// At the Data framework level, this function always returns false.
/// When connector-specific behavior is desired, it should be overriden
/// by the statement implementation.
std::size_t currentDataSet() const;
/// Returns the current data set.
std::size_t activateNextDataSet();
/// Returns the next data set index, or throws NoDataException if the last
/// data set was reached.
std::size_t activatePreviousDataSet();
/// Returns the previous data set index, or throws NoDataException if the last
/// data set was reached.
bool hasMoreDataSets() const;
/// Returns true if there are data sets not activated yet.
private:
void compile();
/// Compiles the statement.
void bind();
/// Binds the statement, if not yet bound.
std::size_t executeWithLimit();
/// Executes with an upper limit set. Returns the number of rows
/// extracted for statements returning data or number of rows
/// affected for all other statements (insert, update, delete).
std::size_t executeWithoutLimit();
/// Executes without an upper limit set. Returns the number of rows
/// extracted for statements returning data or number of rows
/// affected for all other statements (insert, update, delete).
void resetExtraction();
/// Resets extraction so it can be reused again.
template <class C>
SharedPtr<InternalExtraction<C> > createExtract(const MetaColumn& mc)
{
C* pData = new C;
Column<C>* pCol = new Column<C>(mc, pData);
return new InternalExtraction<C>(*pData, pCol, Poco::UInt32(currentDataSet()));
}
template <class C>
SharedPtr<InternalBulkExtraction<C> > createBulkExtract(const MetaColumn& mc)
{
C* pData = new C;
Column<C>* pCol = new Column<C>(mc, pData);
return new InternalBulkExtraction<C>(*pData,
pCol,
static_cast<Poco::UInt32>(getExtractionLimit()),
Position(static_cast<Poco::UInt32>(currentDataSet())));
}
template <class T>
void addInternalExtract(const MetaColumn& mc)
/// Creates and adds the internal extraction.
///
/// The decision about internal extraction container is done
/// in a following way:
///
/// If this statement has _storage member set, that setting
/// overrides the session setting for storage, otherwise the
/// session setting is used.
/// If neither this statement nor the session have the storage
/// type set, std::deque is the default container type used.
{
std::string storage;
switch (_storage)
{
case STORAGE_DEQUE_IMPL:
storage = DEQUE; break;
case STORAGE_VECTOR_IMPL:
storage = VECTOR; break;
case STORAGE_LIST_IMPL:
storage = LIST; break;
case STORAGE_UNKNOWN_IMPL:
storage = AnyCast<std::string>(session().getProperty("storage"));
break;
}
if (storage.empty()) storage = DEQUE;
if (0 == icompare(DEQUE, storage))
{
if (!isBulkExtraction())
addExtract(createExtract<std::deque<T> >(mc));
else
addExtract(createBulkExtract<std::deque<T> >(mc));
}
else if (0 == icompare(VECTOR, storage))
{
if (!isBulkExtraction())
addExtract(createExtract<std::vector<T> >(mc));
else
addExtract(createBulkExtract<std::vector<T> >(mc));
}
else if (0 == icompare(LIST, storage))
{
if (!isBulkExtraction())
addExtract(createExtract<std::list<T> >(mc));
else
addExtract(createBulkExtract<std::list<T> >(mc));
}
}
bool isNull(std::size_t col, std::size_t row) const;
/// Returns true if the value in [col, row] is null.
void forbidBulk();
/// Forbids bulk operations.
void setBulkBinding();
/// Sets the bulk binding flag.
void setBulkExtraction(const Bulk& l);
/// Sets the bulk extraction flag and extraction limit.
void resetBulk();
/// Resets the bulk extraction and binding flag.
bool bulkBindingAllowed() const;
/// Returns true if statement can be set to bind data in bulk.
/// Once bulk binding is set for a statement, it can be
/// neither altered nor mixed with non-bulk mode binding.
bool bulkExtractionAllowed() const;
/// Returns true if statement can be set to extract data in bulk.
/// Once bulk extraction is set for a statement, it can be
/// neither altered nor mixed with non-bulk mode extraction.
bool isBulkBinding() const;
/// Returns true if statement is set to bind data in bulk.
bool isBulkExtraction() const;
/// Returns true if statement is set to extract data in bulk.
bool isBulkSupported() const;
/// Returns true if connector and session support bulk operation.
void formatSQL(std::vector<Any>& arguments);
/// Formats the SQL string by filling in placeholders with values from supplied vector.
void assignSubTotal(bool reset);
StatementImpl(const StatementImpl& stmt);
StatementImpl& operator = (const StatementImpl& stmt);
typedef std::vector<std::size_t> CountVec;
State _state;
Limit _extrLimit;
std::size_t _lowerLimit;
std::vector<int> _columnsExtracted;
SessionImpl& _rSession;
Storage _storage;
std::ostringstream _ostr;
AbstractBindingVec _bindings;
AbstractExtractionVecVec _extractors;
std::size_t _curDataSet;
BulkType _bulkBinding;
BulkType _bulkExtraction;
CountVec _subTotalRowCount;
friend class Statement;
};
//
// inlines
//
inline void StatementImpl::addBind(AbstractBinding::Ptr pBinding)
{
poco_check_ptr (pBinding);
_bindings.push_back(pBinding);
}
inline std::string StatementImpl::toString() const
{
return _ostr.str();
}
inline const AbstractBindingVec& StatementImpl::bindings() const
{
return _bindings;
}
inline AbstractBindingVec& StatementImpl::bindings()
{
return _bindings;
}
inline const AbstractExtractionVec& StatementImpl::extractions() const
{
poco_assert (_curDataSet < _extractors.size());
return _extractors[_curDataSet];
}
inline AbstractExtractionVec& StatementImpl::extractions()
{
poco_assert (_curDataSet < _extractors.size());
return _extractors[_curDataSet];
}
inline StatementImpl::State StatementImpl::getState() const
{
return _state;
}
inline SessionImpl& StatementImpl::session()
{
return _rSession;
}
inline void StatementImpl::setStorage(Storage storage)
{
_storage = storage;
}
inline StatementImpl::Storage StatementImpl::getStorage() const
{
return _storage;
}
inline std::size_t StatementImpl::extractionCount() const
{
return static_cast<std::size_t>(extractions().size());
}
inline std::size_t StatementImpl::dataSetCount() const
{
return static_cast<std::size_t>(_extractors.size());
}
inline bool StatementImpl::isStoredProcedure() const
{
return false;
}
inline bool StatementImpl::isNull(std::size_t col, std::size_t row) const
{
try
{
return extractions().at(col)->isNull(row);
}
catch (std::out_of_range& ex)
{
throw RangeException(ex.what());
}
}
inline std::size_t StatementImpl::currentDataSet() const
{
return _curDataSet;
}
inline Limit::SizeT StatementImpl::getExtractionLimit()
{
return _extrLimit.value();
}
inline const Limit& StatementImpl::extractionLimit() const
{
return _extrLimit;
}
inline void StatementImpl::forbidBulk()
{
_bulkBinding = BULK_FORBIDDEN;
_bulkExtraction = BULK_FORBIDDEN;
}
inline void StatementImpl::setBulkBinding()
{
_bulkBinding = BULK_BINDING;
}
inline bool StatementImpl::bulkBindingAllowed() const
{
return BULK_UNDEFINED == _bulkBinding ||
BULK_BINDING == _bulkBinding;
}
inline bool StatementImpl::bulkExtractionAllowed() const
{
return BULK_UNDEFINED == _bulkExtraction ||
BULK_EXTRACTION == _bulkExtraction;
}
inline bool StatementImpl::isBulkBinding() const
{
return BULK_BINDING == _bulkBinding;
}
inline bool StatementImpl::isBulkExtraction() const
{
return BULK_EXTRACTION == _bulkExtraction;
}
inline void StatementImpl::resetBulk()
{
_bulkExtraction = BULK_UNDEFINED;
_bulkBinding = BULK_UNDEFINED;\
setExtractionLimit(Limit(Limit::LIMIT_UNLIMITED, false, false));
}
inline bool StatementImpl::isBulkSupported() const
{
return _rSession.getFeature("bulk");
}
inline bool StatementImpl::hasMoreDataSets() const
{
return currentDataSet() + 1 < dataSetCount();
}
} } // namespace Poco::Data
#endif // Data_StatementImpl_INCLUDED
|