"Fossies" - the Fresh Open Source Software Archive

Member "qt-creator-opensource-src-4.15.1/src/libs/sqlite/sqlitebasestatement.h" (8 Jun 2021, 12826 Bytes) of package /linux/misc/qt-creator-opensource-src-4.15.1.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "sqlitebasestatement.h" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: opensource-src-4.15.0_vs_opensource-src-4.15.1.

    1 /****************************************************************************
    2 **
    3 ** Copyright (C) 2016 The Qt Company Ltd.
    4 ** Contact: https://www.qt.io/licensing/
    5 **
    6 ** This file is part of Qt Creator.
    7 **
    8 ** Commercial License Usage
    9 ** Licensees holding valid commercial Qt licenses may use this file in
   10 ** accordance with the commercial license agreement provided with the
   11 ** Software or, alternatively, in accordance with the terms contained in
   12 ** a written agreement between you and The Qt Company. For licensing terms
   13 ** and conditions see https://www.qt.io/terms-conditions. For further
   14 ** information use the contact form at https://www.qt.io/contact-us.
   15 **
   16 ** GNU General Public License Usage
   17 ** Alternatively, this file may be used under the terms of the GNU
   18 ** General Public License version 3 as published by the Free Software
   19 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
   20 ** included in the packaging of this file. Please review the following
   21 ** information to ensure the GNU General Public License requirements will
   22 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
   23 **
   24 ****************************************************************************/
   25 
   26 #pragma once
   27 
   28 #include "sqliteglobal.h"
   29 
   30 #include "sqliteblob.h"
   31 #include "sqliteexception.h"
   32 #include "sqlitevalue.h"
   33 
   34 #include <utils/smallstringvector.h>
   35 
   36 #include <utils/optional.h>
   37 #include <utils/span.h>
   38 
   39 #include <cstdint>
   40 #include <functional>
   41 #include <memory>
   42 #include <tuple>
   43 #include <type_traits>
   44 
   45 using std::int64_t;
   46 
   47 struct sqlite3_stmt;
   48 struct sqlite3;
   49 
   50 namespace Sqlite {
   51 
   52 class Database;
   53 class DatabaseBackend;
   54 
   55 enum class Type : char { Invalid, Integer, Float, Text, Blob, Null };
   56 
   57 class SQLITE_EXPORT BaseStatement
   58 {
   59 public:
   60     explicit BaseStatement(Utils::SmallStringView sqlStatement, Database &database);
   61 
   62     BaseStatement(const BaseStatement &) = delete;
   63     BaseStatement &operator=(const BaseStatement &) = delete;
   64 
   65     static void deleteCompiledStatement(sqlite3_stmt *m_compiledStatement);
   66 
   67     bool next() const;
   68     void step() const;
   69     void reset() const;
   70 
   71     Type fetchType(int column) const;
   72     int fetchIntValue(int column) const;
   73     long fetchLongValue(int column) const;
   74     long long fetchLongLongValue(int column) const;
   75     double fetchDoubleValue(int column) const;
   76     Utils::SmallStringView fetchSmallStringViewValue(int column) const;
   77     ValueView fetchValueView(int column) const;
   78     BlobView fetchBlobValue(int column) const;
   79     template<typename Type>
   80     Type fetchValue(int column) const;
   81     int columnCount() const;
   82 
   83     void bind(int index, NullValue);
   84     void bind(int index, int value);
   85     void bind(int index, long long value);
   86     void bind(int index, double value);
   87     void bind(int index, void *pointer);
   88     void bind(int index, Utils::span<int> values);
   89     void bind(int index, Utils::span<long long> values);
   90     void bind(int index, Utils::span<double> values);
   91     void bind(int index, Utils::span<const char *> values);
   92     void bind(int index, Utils::SmallStringView value);
   93     void bind(int index, const Value &value);
   94     void bind(int index, BlobView blobView);
   95 
   96     void bind(int index, uint value) { bind(index, static_cast<long long>(value)); }
   97 
   98     void bind(int index, long value)
   99     {
  100         bind(index, static_cast<long long>(value));
  101     }
  102 
  103     void prepare(Utils::SmallStringView sqlStatement);
  104     void waitForUnlockNotify() const;
  105 
  106     sqlite3 *sqliteDatabaseHandle() const;
  107 
  108     [[noreturn]] void checkForStepError(int resultCode) const;
  109     [[noreturn]] void checkForResetError(int resultCode) const;
  110     [[noreturn]] void checkForPrepareError(int resultCode) const;
  111     [[noreturn]] void checkForBindingError(int resultCode) const;
  112     void setIfIsReadyToFetchValues(int resultCode) const;
  113     void checkColumnCount(int columnCount) const;
  114     void checkBindingName(int index) const;
  115     void setBindingParameterCount();
  116     void setColumnCount();
  117     bool isReadOnlyStatement() const;
  118     [[noreturn]] void throwStatementIsBusy(const char *whatHasHappened) const;
  119     [[noreturn]] void throwStatementHasError(const char *whatHasHappened) const;
  120     [[noreturn]] void throwStatementIsMisused(const char *whatHasHappened) const;
  121     [[noreturn]] void throwInputOutputError(const char *whatHasHappened) const;
  122     [[noreturn]] void throwConstraintPreventsModification(const char *whatHasHappened) const;
  123     [[noreturn]] void throwNoValuesToFetch(const char *whatHasHappened) const;
  124     [[noreturn]] void throwInvalidColumnFetched(const char *whatHasHappened) const;
  125     [[noreturn]] void throwBindingIndexIsOutOfRange(const char *whatHasHappened) const;
  126     [[noreturn]] void throwWrongBingingName(const char *whatHasHappened) const;
  127     [[noreturn]] void throwUnknowError(const char *whatHasHappened) const;
  128     [[noreturn]] void throwBingingTooBig(const char *whatHasHappened) const;
  129     [[noreturn]] void throwTooBig(const char *whatHasHappened) const;
  130     [[noreturn]] void throwSchemaChangeError(const char *whatHasHappened) const;
  131     [[noreturn]] void throwCannotWriteToReadOnlyConnection(const char *whatHasHappened) const;
  132     [[noreturn]] void throwProtocolError(const char *whatHasHappened) const;
  133     [[noreturn]] void throwDatabaseExceedsMaximumFileSize(const char *whatHasHappened) const;
  134     [[noreturn]] void throwDataTypeMismatch(const char *whatHasHappened) const;
  135     [[noreturn]] void throwConnectionIsLocked(const char *whatHasHappened) const;
  136     [[noreturn]] void throwExecutionInterrupted(const char *whatHasHappened) const;
  137     [[noreturn]] void throwDatabaseIsCorrupt(const char *whatHasHappened) const;
  138     [[noreturn]] void throwCannotOpen(const char *whatHasHappened) const;
  139 
  140     QString columnName(int column) const;
  141 
  142     Database &database() const;
  143 
  144 protected:
  145     ~BaseStatement() = default;
  146 
  147 private:
  148     std::unique_ptr<sqlite3_stmt, void (*)(sqlite3_stmt *)> m_compiledStatement;
  149     Database &m_database;
  150     int m_bindingParameterCount;
  151     int m_columnCount;
  152 };
  153 
  154 template <> SQLITE_EXPORT int BaseStatement::fetchValue<int>(int column) const;
  155 template <> SQLITE_EXPORT long BaseStatement::fetchValue<long>(int column) const;
  156 template <> SQLITE_EXPORT long long BaseStatement::fetchValue<long long>(int column) const;
  157 template <> SQLITE_EXPORT double BaseStatement::fetchValue<double>(int column) const;
  158 extern template SQLITE_EXPORT Utils::SmallStringView BaseStatement::fetchValue<Utils::SmallStringView>(int column) const;
  159 extern template SQLITE_EXPORT Utils::SmallString BaseStatement::fetchValue<Utils::SmallString>(int column) const;
  160 extern template SQLITE_EXPORT Utils::PathString BaseStatement::fetchValue<Utils::PathString>(int column) const;
  161 
  162 template<typename BaseStatement, int ResultCount>
  163 class StatementImplementation : public BaseStatement
  164 {
  165 
  166 public:
  167     using BaseStatement::BaseStatement;
  168 
  169     void execute()
  170     {
  171         Resetter resetter{*this};
  172         BaseStatement::next();
  173         resetter.reset();
  174     }
  175 
  176     void bindValues() {}
  177 
  178     template<typename... ValueType>
  179     void bindValues(const ValueType&... values)
  180     {
  181         int index = 0;
  182         (BaseStatement::bind(++index, values), ...);
  183     }
  184 
  185     template<typename... ValueType>
  186     void write(const ValueType&... values)
  187     {
  188         Resetter resetter{*this};
  189         bindValues(values...);
  190         BaseStatement::next();
  191         resetter.reset();
  192     }
  193 
  194     template<typename ResultType>
  195     std::vector<ResultType> values(std::size_t reserveSize)
  196     {
  197         Resetter resetter{*this};
  198         std::vector<ResultType> resultValues;
  199         resultValues.reserve(std::max(reserveSize, m_maximumResultCount));
  200 
  201         while (BaseStatement::next())
  202             emplaceBackValues(resultValues);
  203 
  204         setMaximumResultCount(resultValues.size());
  205 
  206         resetter.reset();
  207 
  208         return resultValues;
  209     }
  210 
  211     template<typename ResultType, typename... QueryTypes>
  212     auto values(std::size_t reserveSize, const QueryTypes &...queryValues)
  213     {
  214         Resetter resetter{*this};
  215         std::vector<ResultType> resultValues;
  216         resultValues.reserve(std::max(reserveSize, m_maximumResultCount));
  217 
  218         bindValues(queryValues...);
  219 
  220         while (BaseStatement::next())
  221             emplaceBackValues(resultValues);
  222 
  223         setMaximumResultCount(resultValues.size());
  224 
  225         resetter.reset();
  226 
  227         return resultValues;
  228     }
  229 
  230     template<typename ResultType, typename... QueryTypes>
  231     auto value(const QueryTypes &...queryValues)
  232     {
  233         Resetter resetter{*this};
  234         Utils::optional<ResultType> resultValue;
  235 
  236         bindValues(queryValues...);
  237 
  238         if (BaseStatement::next())
  239             resultValue = assignValue<Utils::optional<ResultType>>();
  240 
  241         resetter.reset();
  242 
  243         return resultValue;
  244     }
  245 
  246     template<typename Type>
  247     static auto toValue(Utils::SmallStringView sqlStatement, Database &database)
  248     {
  249         StatementImplementation statement(sqlStatement, database);
  250 
  251         statement.checkColumnCount(1);
  252 
  253         statement.next();
  254 
  255         return statement.template fetchValue<Type>(0);
  256     }
  257 
  258     template<typename Callable, typename... QueryTypes>
  259     void readCallback(Callable &&callable, const QueryTypes &...queryValues)
  260     {
  261         Resetter resetter{*this};
  262 
  263         bindValues(queryValues...);
  264 
  265         while (BaseStatement::next()) {
  266             auto control = callCallable(callable);
  267 
  268             if (control == CallbackControl::Abort)
  269                 break;
  270         }
  271 
  272         resetter.reset();
  273     }
  274 
  275     template<int ResultTypeCount = 1, typename Container, typename... QueryTypes>
  276     void readTo(Container &container, const QueryTypes &...queryValues)
  277     {
  278         Resetter resetter{*this};
  279 
  280         bindValues(queryValues...);
  281 
  282         while (BaseStatement::next())
  283             emplaceBackValues(container);
  284 
  285         resetter.reset();
  286     }
  287 
  288 protected:
  289     ~StatementImplementation() = default;
  290 
  291 private:
  292     struct Resetter
  293     {
  294         Resetter(StatementImplementation &statement)
  295             : statement(statement)
  296         {}
  297 
  298         void reset()
  299         {
  300             try {
  301                 statement.reset();
  302             } catch (...) {
  303                 shouldReset = false;
  304                 throw;
  305             }
  306 
  307             shouldReset = false;
  308         }
  309 
  310         ~Resetter() noexcept
  311         {
  312             try {
  313                 if (shouldReset)
  314                     statement.reset();
  315             } catch (...) {
  316             }
  317         }
  318 
  319         StatementImplementation &statement;
  320         bool shouldReset = true;
  321     };
  322 
  323     struct ValueGetter
  324     {
  325         ValueGetter(StatementImplementation &statement, int column)
  326             : statement(statement)
  327             , column(column)
  328         {}
  329 
  330         operator int() { return statement.fetchIntValue(column); }
  331         operator long() { return statement.fetchLongValue(column); }
  332         operator long long() { return statement.fetchLongLongValue(column); }
  333         operator double() { return statement.fetchDoubleValue(column); }
  334         operator Utils::SmallStringView() { return statement.fetchSmallStringViewValue(column); }
  335         operator BlobView() { return statement.fetchBlobValue(column); }
  336         operator ValueView() { return statement.fetchValueView(column); }
  337 
  338         StatementImplementation &statement;
  339         int column;
  340     };
  341 
  342     template<typename ContainerType, int... ColumnIndices>
  343     void emplaceBackValues(ContainerType &container, std::integer_sequence<int, ColumnIndices...>)
  344     {
  345         container.emplace_back(ValueGetter(*this, ColumnIndices)...);
  346     }
  347 
  348     template<typename ContainerType>
  349     void emplaceBackValues(ContainerType &container)
  350     {
  351         emplaceBackValues(container, std::make_integer_sequence<int, ResultCount>{});
  352     }
  353 
  354     template <typename ResultOptionalType,
  355               int... ColumnIndices>
  356     ResultOptionalType assignValue(std::integer_sequence<int, ColumnIndices...>)
  357     {
  358         return ResultOptionalType(Utils::in_place, ValueGetter(*this, ColumnIndices)...);
  359     }
  360 
  361     template<typename ResultOptionalType>
  362     ResultOptionalType assignValue()
  363     {
  364         return assignValue<ResultOptionalType>(std::make_integer_sequence<int, ResultCount>{});
  365     }
  366 
  367     template<typename Callable, int... ColumnIndices>
  368     CallbackControl callCallable(Callable &&callable, std::integer_sequence<int, ColumnIndices...>)
  369     {
  370         return std::invoke(callable, ValueGetter(*this, ColumnIndices)...);
  371     }
  372 
  373     template<typename Callable>
  374     CallbackControl callCallable(Callable &&callable)
  375     {
  376         return callCallable(callable, std::make_integer_sequence<int, ResultCount>{});
  377     }
  378 
  379     void setMaximumResultCount(std::size_t count)
  380     {
  381         m_maximumResultCount = std::max(m_maximumResultCount, count);
  382     }
  383 
  384 public:
  385     std::size_t m_maximumResultCount = 0;
  386 };
  387 
  388 } // namespace Sqlite