1 // 2 // database.hpp 3 // 4 // Copyright © 2024 Apple Inc. All rights reserved. 5 // 6 // Please refer to the license found in the LICENSE file in the root directory of the source tree. 7 8 #pragma once 9 10 #include <string> 11 #include <system_error> 12 #include <sqlite3.h> 13 14 #include <types.hpp> 15 16 namespace executorchcoreml { 17 namespace sqlite { 18 19 /// The deleter for a sqlite statement, finalizes the statement at the time of deallocation. 20 struct StatementDeleter { operator ()executorchcoreml::sqlite::StatementDeleter21 inline void operator()(sqlite3_stmt* stmt) { 22 if (stmt) { 23 sqlite3_finalize(stmt); 24 } 25 } 26 }; 27 28 /// A class representing a compiled sqlite statement. 29 class PreparedStatement { 30 public: 31 virtual ~PreparedStatement() = default; 32 33 explicit PreparedStatement(std::unique_ptr<sqlite3_stmt, StatementDeleter> preparedStatement) noexcept; 34 35 PreparedStatement(PreparedStatement const&) = delete; 36 PreparedStatement& operator=(PreparedStatement const&) = delete; 37 38 /// Binds an int64_t value to a parameter at the specified index. 39 /// 40 /// @param index The column index. 41 /// @param value The column value. 42 /// @param error On failure, error is populated with the failure reason. 43 /// @retval `true` if the value was bound otherwise `false`. 44 bool bind(size_t index, int64_t value, std::error_code& error) const noexcept; 45 46 /// Binds an int64_t value to a parameter with the specified name. 47 /// 48 /// @param name The column name. 49 /// @param value The column value. 50 /// @param error On failure, error is populated with the failure reason. 51 /// @retval `true` if the value was bound otherwise `false`. 52 bool bind_name(const std::string& name, int64_t value, std::error_code& error) const noexcept; 53 54 /// Binds a double value to a parameter at the specified index. 55 /// 56 /// @param index The column index. 57 /// @param value The column value. 58 /// @param error On failure, error is populated with the failure reason. 59 /// @retval `true` if the value was bound otherwise `false`. 60 bool bind(size_t index, double value, std::error_code& error) const noexcept; 61 62 /// Binds a double value to a parameter with the specified name. 63 /// 64 /// @param name The column name. 65 /// @param value The column value. 66 /// @param error On failure, error is populated with the failure reason. 67 /// @retval `true` if the value was bound otherwise `false`. 68 bool bind_name(const std::string& name, double value, std::error_code& error) const noexcept; 69 70 /// Binds a string value to a parameter at the specified index. 71 /// 72 /// @param index The column index. 73 /// @param value The column value. 74 /// @param error On failure, error is populated with the failure reason. 75 /// @retval `true` if the value was bound otherwise `false`. 76 bool bind(size_t index, UnOwnedString value, std::error_code& error) const noexcept; 77 78 /// Binds a string value to a parameter at the specified index without copying. 79 /// 80 /// @param index The column index. 81 /// @param value The column value. 82 /// @param error On failure, error is populated with the failure reason. 83 /// @retval `true` if the value was bound otherwise `false`. 84 bool bind_no_copy(size_t index, UnOwnedString value, std::error_code& error) const noexcept; 85 86 /// Binds a string value to a parameter with the specified name. 87 /// 88 /// @param name The column name. 89 /// @param value The column value. 90 /// @param error On failure, error is populated with the failure reason. 91 /// @retval `true` if the value was bound otherwise `false`. 92 bool bind_name(const std::string& name, UnOwnedString value, std::error_code& error) const noexcept; 93 94 /// Binds a string value to a parameter with the specified name without copying. 95 /// 96 /// @param name The column name. 97 /// @param value The column value. 98 /// @param error On failure, error is populated with the failure reason. 99 /// @retval `true` if the value was bound otherwise `false`. 100 bool bind_name_no_copy(const std::string& name, UnOwnedString value, std::error_code& error) const noexcept; 101 102 /// Binds a blob value to a parameter at the specified index. 103 /// 104 /// @param index The column index. 105 /// @param value The column value. 106 /// @param error On failure, error is populated with the failure reason. 107 /// @retval `true` if the value was bound otherwise `false`. 108 bool bind(size_t index, const UnOwnedBlob& value, std::error_code& error) const noexcept; 109 110 /// Binds a blob value to a parameter at the specified index without copying. 111 /// 112 /// @param index The column index. 113 /// @param value The column value. 114 /// @param error On failure, error is populated with the failure reason. 115 /// @retval `true` if the value was bound otherwise `false`. 116 bool bind_no_copy(size_t index, const UnOwnedBlob& value, std::error_code& error) const noexcept; 117 118 /// Binds a blob value to a parameter with the specified name. 119 /// 120 /// @param name The column name. 121 /// @param value The column value. 122 /// @param error On failure, error is populated with the failure reason. 123 /// @retval `true` if the value was bound otherwise `false`. 124 bool bind_name(const std::string& name, const UnOwnedBlob& value, std::error_code& error) const noexcept; 125 126 /// Binds a blob value to a parameter with the specified name without copying. 127 /// 128 /// @param name The column name. 129 /// @param value The column value. 130 /// @param error On failure, error is populated with the failure reason. 131 /// @retval `true` if the value was bound otherwise `false`. 132 bool bind_name_no_copy(const std::string& name, const UnOwnedBlob& value, std::error_code& error) const noexcept; 133 134 /// Resets the statement. The statement can be used again after calling this method but the column values needs to be rebound. 135 /// 136 /// @param error On failure, error is populated with the failure reason. 137 /// @retval `true` if the value was bound otherwise `false`. 138 bool reset(std::error_code& error) const noexcept; 139 140 /// Returns the underlying sqlite statement. get_underlying_statement() const141 inline sqlite3_stmt *get_underlying_statement() const noexcept { 142 return prepared_statement_.get(); 143 } 144 145 /// Returns the column storage type. get_column_storage_type(size_t index)146 inline StorageType get_column_storage_type(size_t index) noexcept { 147 return get_column_storage_types()[index]; 148 } 149 150 /// Returns the column value at the specified index. 151 /// 152 /// @param index The column index. 153 /// @param error On failure, error is populated with the failure reason. 154 /// @retval The column value at the specified index. 155 Value get_column_value(size_t index, std::error_code& error) noexcept; 156 157 /// Returns the column value without copy at the specified index. It's the caller's responsibility to copy the value. 158 /// 159 /// @param index The column index. 160 /// @param error On failure, error is populated with the failure reason. 161 /// @retval The column value at the specified index. 162 UnOwnedValue get_column_value_no_copy(size_t index, std::error_code& error) noexcept; 163 164 /// Returns the column storage types. 165 const std::vector<StorageType>& get_column_storage_types() noexcept; 166 167 /// Returns the column count. get_column_count() const168 inline size_t get_column_count() const noexcept { 169 return column_count_; 170 } 171 172 /// Returns the column names. get_column_names() const173 inline const std::vector<std::string>& get_column_names() const noexcept { 174 return column_names_; 175 } 176 177 /// Executes the statement. 178 /// 179 /// @param error On failure, error is populated with the failure reason. 180 /// @retval `true` if the statement executed successfully `false`. 181 bool execute(std::error_code& error) const noexcept; 182 183 /// Retrieves next row. 184 /// 185 /// @param error On failure, error is populated with the failure reason. 186 /// @retval `true` if there is a next row to step to otherwise false. 187 bool step(std::error_code& error) const noexcept; 188 189 private: 190 size_t column_count_; 191 std::vector<std::string> column_names_; 192 std::vector<StorageType> column_storage_types_; 193 std::unique_ptr<sqlite3_stmt, StatementDeleter> prepared_statement_; 194 }; 195 196 } // namespace sqlite 197 } // namespace executorchcoreml 198