/** * * @file Result.h * @author An Tao * * Copyright 2018, An Tao. All rights reserved. * https://github.com/an-tao/drogon * Use of this source code is governed by a MIT license * that can be found in the License file. * * Drogon * */ // Taken from libpqxx and modified. // The license for libpqxx can be found in the COPYING file. #pragma once #include #include #include #include #include #include namespace drogon { namespace orm { class ConstResultIterator; class ConstReverseResultIterator; class Row; class ResultImpl; using ResultImplPtr = std::shared_ptr; enum class SqlStatus { Ok, End }; /// Result set containing data returned by a query or command. /** This behaves as a container (as defined by the C++ standard library) and * provides random access const iterators to iterate over its rows. A row * can also be accessed by indexing a result R by the row's zero-based * number: * * @code * for (Result::SizeType i=0; i < R.size(); ++i) Process(R[i]); * @endcode * * Result sets in libpqxx are lightweight, Reference-counted wrapper objects * which are relatively small and cheap to copy. Think of a result object as * a "smart pointer" to an underlying result set. */ class DROGON_EXPORT Result { public: explicit Result(ResultImplPtr ptr) : resultPtr_(std::move(ptr)) { } Result(const Result &r) noexcept = default; Result(Result &&) noexcept = default; Result &operator=(const Result &r) noexcept; Result &operator=(Result &&) noexcept; using DifferenceType = long; using SizeType = size_t; using Reference = Row; using ConstIterator = ConstResultIterator; using Iterator = ConstIterator; using RowSizeType = unsigned long; using FieldSizeType = unsigned long; using ConstReverseIterator = ConstReverseResultIterator; using ReverseIterator = ConstReverseIterator; // C++ type type defination compatibility using value_type = Row; using size_type = SizeType; using difference_type = DifferenceType; using reference = Reference; using const_reference = const Reference; using iterator = Iterator; using const_iterator = ConstIterator; using reverse_iterator = ConstReverseIterator; using const_reverse_iterator = ConstReverseIterator; SizeType size() const noexcept; SizeType capacity() const noexcept { return size(); } ConstIterator begin() const noexcept; ConstIterator cbegin() const noexcept; ConstIterator end() const noexcept; ConstIterator cend() const noexcept; ConstReverseIterator rbegin() const; ConstReverseIterator crbegin() const; ConstReverseIterator rend() const; ConstReverseIterator crend() const; bool empty() const noexcept { return size() == 0; } Reference front() const noexcept; Reference back() const noexcept; Reference operator[](SizeType index) const noexcept; Reference at(SizeType index) const; void swap(Result &) noexcept; /// Number of columns in result. RowSizeType columns() const noexcept; /// Name of column with this number (throws exception if it doesn't exist) const char *columnName(RowSizeType number) const; /// If command was @c INSERT, @c UPDATE, or @c DELETE: number of affected /// rows /** * @return Number of affected rows if last command was @c INSERT, @c UPDATE, * or @c DELETE; zero for all other commands. */ SizeType affectedRows() const noexcept; /// For Mysql, Sqlite3 databases, return the auto-incrementing primary key /// after inserting /** * For postgreSQL databases, this method always returns zero, One can use * the following sql to get auto-incrementing id: * insert into table_name volumn1, volumn2 values(....) returning id; */ unsigned long long insertId() const noexcept; #ifdef _MSC_VER Result() = default; #endif private: ResultImplPtr resultPtr_; friend class Field; friend class Row; /// Number of given column (throws exception if it doesn't exist). RowSizeType columnNumber(const char colName[]) const; /// Number of given column (throws exception if it doesn't exist). RowSizeType columnNumber(const std::string &name) const { return columnNumber(name.c_str()); } /// Get the column oid, for postgresql database int oid(RowSizeType column) const noexcept; const char *getValue(SizeType row, RowSizeType column) const; bool isNull(SizeType row, RowSizeType column) const; FieldSizeType getLength(SizeType row, RowSizeType column) const; }; inline void swap(Result &one, Result &two) noexcept { one.swap(two); } } // namespace orm } // namespace drogon #ifndef _MSC_VER namespace std { template <> inline void swap(drogon::orm::Result &one, drogon::orm::Result &two) noexcept { one.swap(two); } } // namespace std #endif