xref: /aosp_15_r20/external/executorch/backends/apple/coreml/runtime/kvstore/statement.hpp (revision 523fa7a60841cd1ecfb9cc4201f1ca8b03ed023a)
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