1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef NATIVE_RDB_ABS_RESULT_SET_H
17 #define NATIVE_RDB_ABS_RESULT_SET_H
18 
19 #include <memory>
20 #include <string>
21 #include <vector>
22 #include <map>
23 #include <mutex>
24 
25 #include "result_set.h"
26 #include "value_object.h"
27 
28 namespace OHOS {
29 namespace NativeRdb {
30 /**
31  * The AbsResultSet class of RDB.
32  * Provides methods for accessing a database result set generated by querying the database.
33  */
34 class API_EXPORT AbsResultSet : public ResultSet {
35 public:
36     /**
37      * @brief Constructor.
38      */
39     API_EXPORT AbsResultSet();
40 
41     /**
42      * @brief Destructor.
43      */
44     API_EXPORT virtual ~AbsResultSet();
45 
46     /**
47      * @brief Obtains the number of rows in the result set.
48      */
49     API_EXPORT int GetRowCount(int &count) override;
50 
51     /**
52      * @brief Obtains the names of all columns in a result set.
53      */
54     API_EXPORT int GetAllColumnNames(std::vector<std::string> &columnNames) override;
55 
56     /**
57      * @brief Obtains the value of the specified column in the current row as a byte array.
58      *
59      * The implementation class determines whether to throw an exception if the value of the specified column
60      * in the current row is null or the specified column is not of the Blob type.
61      *
62      * @param columnIndex Indicates the specified column index, which starts from 0.
63      *
64      * @return Returns the value of the specified column as a byte array.
65      */
66     API_EXPORT int GetBlob(int columnIndex, std::vector<uint8_t> &blob) override;
67 
68     /**
69      * @brief Obtains the value of the specified column in the current row as string.
70      *
71      * The implementation class determines whether to throw an exception if the value of the specified column
72      * in the current row is null or the specified column is not of the string type.
73      *
74      * @param columnIndex Indicates the specified column index, which starts from 0.
75      *
76      * @return Returns the value of the specified column as a string.
77      */
78     API_EXPORT int GetString(int columnIndex, std::string &value) override;
79 
80     /**
81      * @brief Obtains the value of the specified column in the current row as int.
82      *
83      * The implementation class determines whether to throw an exception if the value of the specified column
84      * in the current row is null or the specified column is not of the integer type.
85      *
86      * @param columnIndex Indicates the specified column index, which starts from 0.
87      *
88      * @return Returns the value of the specified column as a int.
89      */
90     API_EXPORT int GetInt(int columnIndex, int &value) override;
91 
92     /**
93      * @brief Obtains the value of the specified column in the current row as long.
94      *
95      * The implementation class determines whether to throw an exception if the value of the specified column
96      * in the current row is null or the specified column is not of the long type.
97      *
98      * @param columnIndex Indicates the specified column index, which starts from 0.
99      *
100      * @return Returns the value of the specified column as a long.
101      */
102     API_EXPORT int GetLong(int columnIndex, int64_t &value) override;
103 
104     /**
105      * @brief Obtains the value of the specified column in the current row as double.
106      *
107      * The implementation class determines whether to throw an exception if the value of the specified column
108      * in the current row is null or the specified column is not of the double type.
109      *
110      * @param columnIndex Indicates the specified column index, which starts from 0.
111      *
112      * @return Returns the value of the specified column as a double.
113      */
114     API_EXPORT int GetDouble(int columnIndex, double &value) override;
115 
116     /**
117      * @brief Obtains the value of the specified column in the current row as asset.
118      *
119      * The implementation class determines whether to throw an exception if the value of the specified column
120      * in the current row is null or the specified column is not of the Asset type.
121      *
122      * @param columnIndex Indicates the specified column index, which starts from 0.
123      *
124      * @return Returns the value of the specified column as a double.
125      */
126     API_EXPORT int GetAsset(int32_t col, ValueObject::Asset &value) override;
127 
128     /**
129      * @brief Obtains the value of the specified column in the current row as assets.
130      *
131      * The implementation class determines whether to throw an exception if the value of the specified column
132      * in the current row is null or the specified column is not of the Assets type.
133      *
134      * @param columnIndex Indicates the specified column index, which starts from 0.
135      *
136      * @return Returns the value of the specified column as a double.
137      */
138     API_EXPORT int GetAssets(int32_t col, ValueObject::Assets &value) override;
139 
140     /**
141      * @brief Obtains the value of the specified column in the current row as vector.
142      *
143      * The implementation class determines whether to throw an exception if the value of the specified column
144      * in the current row is null or the specified column is not of the vector type.
145      *
146      * @param columnIndex Indicates the specified column index, which starts from 0.
147      *
148      * @return Returns the value of the specified column as a double.
149      */
150     API_EXPORT int GetFloat32Array(int32_t index, ValueObject::FloatVector &vecs) override;
151 
152     /**
153      * @brief Checks whether the value of the specified column in the current row is null.
154      *
155      * @param columnIndex Indicates the specified column index, which starts from 0.
156      *
157      * @return Returns true if the value of the specified column in the current row is null;
158      * returns false otherwise.
159      */
160     API_EXPORT int IsColumnNull(int columnIndex, bool &isNull) override;
161 
162     /**
163      * @brief Gets the entire row of data for the current row from the result set.
164      */
165     API_EXPORT int GetRow(RowEntity &rowEntity) override;
166 
167     /**
168      * @brief Move the cursor to an absolute position.
169      *
170      * @param position Indicates the specified column index, which starts from 0.
171      *
172      * @return Returns whether the requested move succeeded.
173      */
174     API_EXPORT int GoToRow(int position) override;
175 
176     /**
177      * @brief Obtains data type of the given column's value.
178      *
179      * @param columnIndex Indicates the specified column index, which starts from 0.
180      *
181      * @return Returns column value type.
182      */
183     API_EXPORT int GetColumnType(int columnIndex, ColumnType &columnType) override;
184 
185     /**
186      * @brief Returns the current position of the cursor in the result set.
187      *
188      * The value is zero-based. When the result set is first returned the cursor
189      * will be at position -1, which is before the first row.
190      * After the last row is returned another call to next() will leave the cursor past
191      * the last entry, at a position of count().
192      *
193      * @return Returns the current cursor position.
194      */
195     API_EXPORT int GetRowIndex(int &position) const override;
196 
197     /**
198      * @brief Go to the specified row of the result set forwards or backwards by an offset
199      * relative to its current position.
200      *
201      * A positive offset indicates moving backwards, and a negative offset indicates moving forwards.
202      *
203      * @param offset Indicates the offset relative to the current position.
204      *
205      * @return Returns whether true if the result set is moved successfully and does not go beyond the range;
206      * returns false otherwise.
207      */
208     API_EXPORT int GoTo(int offset) override;
209 
210     /**
211      * @brief Go to the first row of the result set.
212      *
213      * @return Returns if the result set is moved successfully;
214      * returns false otherwise, for example, if the result set is empty.
215      */
216     API_EXPORT int GoToFirstRow() override;
217 
218     /**
219      * @brief Go to the last row of the result set.
220      *
221      * @return Returns if the result set is moved successfully;
222      * returns false otherwise, for example, if the result set is empty.
223      */
224     API_EXPORT int GoToLastRow() override;
225 
226     /**
227      * @brief Go to the next row of the result set.
228      *
229      * @return Returns if the result set is moved successfully;
230      * returns false otherwise, for example, if the result set is already in the last row.
231      */
232     API_EXPORT int GoToNextRow() override;
233 
234     /**
235      * @brief Go to the previous row of the result set.
236      *
237      * @return Returns if the result set is moved successfully;
238      * returns false otherwise, for example, if the result set is already in the first row.
239      */
240     API_EXPORT int GoToPreviousRow() override;
241 
242     /**
243      * @brief Checks whether the result set is positioned at the first row.
244      */
245     API_EXPORT int IsAtFirstRow(bool &result) const override;
246 
247     /**
248      * @brief Checks whether the result set is positioned at the last row.
249      */
250     API_EXPORT int IsAtLastRow(bool &result) override;
251 
252     /**
253      * @brief Returns whether the cursor is pointing to the position before the first row.
254      */
255     API_EXPORT int IsStarted(bool &result) const override;
256 
257     /**
258      * @brief Checks whether the result set is positioned after the last row.
259      */
260     API_EXPORT int IsEnded(bool &result) override;
261 
262     /**
263      * @brief Obtains the number of columns in the result set.
264      */
265     API_EXPORT int GetColumnCount(int &count) override;
266 
267     /**
268      * @brief Returns the zero-based index for the given column name.
269      *
270      * @param columnName Indicates the specified name of the column.
271      *
272      * @return Returns the column index for the given column, or -1 if the column does not exist.
273      */
274     API_EXPORT int GetColumnIndex(const std::string &columnName, int &columnIndex) override;
275 
276     /**
277      * @brief Returns the column name at the given column index.
278      *
279      * @param columnIndex Indicates the specified column index, which starts from 0.
280      *
281      * @return Returns the column name for the given index.
282      */
283     API_EXPORT int GetColumnName(int columnIndex, std::string &columnName) override;
284 
285     /**
286      * @brief Checks whether the current result set is closed.
287      *
288      * @return Returns the true if the result set is closed by calling the close method.
289      */
290     API_EXPORT bool IsClosed() const override;
291 
292     /**
293      * @brief Closes the result set.
294      *
295      * Calling this method on the result set will release all of its resources and makes it ineffective.
296      */
297     API_EXPORT int Close() override;
298 
299 protected:
300     /**
301      * @brief Constructor.
302      */
303     API_EXPORT explicit AbsResultSet(bool safe);
304 
305     template<typename Mtx>
306     class Lock {
307     public:
308         Lock(bool enable = false)
309         {
310             if (enable) {
311                 mutex_ = new Mtx();
312             }
313         };
~Lock()314         ~Lock()
315         {
316             delete mutex_;
317             mutex_ = nullptr;
318         }
lock()319         void lock()
320         {
321             if (mutex_ != nullptr) {
322                 mutex_->lock();
323             }
324         };
unlock()325         void unlock()
326         {
327             if (mutex_ != nullptr) {
328                 mutex_->unlock();
329             }
330         };
331 
332     private:
333         Mtx* mutex_ = nullptr;
334     };
335     using Mutex = Lock<std::mutex>;
336 
337     virtual std::pair<int, std::vector<std::string>> GetColumnNames();
338     std::pair<int, bool> IsEnded();
339 
340     // The default position of the result set
341     static const int INIT_POS = -1;
342     static constexpr int NO_COUNT = -1;
343 
344     Mutex globalMtx_;
345     /*
346      * The value can be in the range [-1 ~ n], where -1 represents the start flag position and N represents the data end
347      * flag position, and [0, n-1] represents the real data index.
348      */
349     int rowPos_ = INIT_POS;
350     bool isClosed_ = false;
351     int rowCount_ = NO_COUNT;
352     int32_t lastErr_ = E_OK;
353 
354 private:
355     int InitColumnNames();
356 
357     // Indicates whether the result set is closed
358     int columnCount_ = -1;
359     std::map<std::string, int> columnMap_;
360 };
361 } // namespace NativeRdb
362 } // namespace OHOS
363 
364 #endif