• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #define LOG_TAG "StepResultSet"
17 
18 #include "step_result_set.h"
19 
20 #include <unistd.h>
21 
22 #include "logger.h"
23 #include "rdb_errno.h"
24 #include "rdb_trace.h"
25 #include "sqlite3sym.h"
26 #include "sqlite_errno.h"
27 
28 namespace OHOS {
29 namespace NativeRdb {
StepResultSet(std::shared_ptr<RdbStoreImpl> rdb,const std::string & sql,const std::vector<std::string> & selectionArgs)30 StepResultSet::StepResultSet(
31     std::shared_ptr<RdbStoreImpl> rdb, const std::string &sql, const std::vector<std::string> &selectionArgs)
32     : rdb(rdb), sql(sql), selectionArgs(selectionArgs), isAfterLast(false), rowCount(INIT_POS),
33       sqliteStatement(nullptr)
34 {
35 }
36 
~StepResultSet()37 StepResultSet::~StepResultSet()
38 {
39     Close();
40 }
41 
GetAllColumnNames(std::vector<std::string> & columnNames)42 int StepResultSet::GetAllColumnNames(std::vector<std::string> &columnNames)
43 {
44     bool needRelease = false;
45     if (sqliteStatement == nullptr) {
46         int errCode = E_STEP_RESULT_QUERY_NOT_EXECUTED;
47         sqliteStatement = rdb->BeginStepQuery(errCode, sql, selectionArgs);
48         if (sqliteStatement == nullptr) {
49             return errCode;
50         }
51         needRelease = true;
52     }
53 
54     int columnCount = 0;
55     auto errCode = sqliteStatement->GetColumnCount(columnCount);
56     if (errCode) {
57         return errCode;
58     }
59 
60     columnNames.clear();
61     for (int i = 0; i < columnCount; i++) {
62         std::string columnName;
63         errCode = sqliteStatement->GetColumnName(i, columnName);
64         if (errCode) {
65             columnNames.clear();
66             return errCode;
67         }
68         columnNames.push_back(columnName);
69         columnMap_[columnName] = i;
70     }
71     if (needRelease) {
72         rdb->EndStepQuery();
73         sqliteStatement = nullptr;
74     }
75     return E_OK;
76 }
77 
GetColumnType(int columnIndex,ColumnType & columnType)78 int StepResultSet::GetColumnType(int columnIndex, ColumnType &columnType)
79 {
80     if (rowPos_ == INIT_POS) {
81         return E_STEP_RESULT_QUERY_NOT_EXECUTED;
82     }
83     int sqliteType;
84     int errCode = sqliteStatement->GetColumnType(columnIndex, sqliteType);
85     if (errCode) {
86         return errCode;
87     }
88 
89     switch (sqliteType) {
90         case SQLITE_INTEGER:
91             columnType = ColumnType::TYPE_INTEGER;
92             break;
93         case SQLITE_FLOAT:
94             columnType = ColumnType::TYPE_FLOAT;
95             break;
96         case SQLITE_BLOB:
97             columnType = ColumnType::TYPE_BLOB;
98             break;
99         case SQLITE_NULL:
100             columnType = ColumnType::TYPE_NULL;
101             break;
102         default:
103             columnType = ColumnType::TYPE_STRING;
104     }
105 
106     return E_OK;
107 }
108 
GetRowCount(int & count)109 int StepResultSet::GetRowCount(int &count)
110 {
111     if (rowCount != INIT_POS) {
112         count = rowCount;
113         return E_OK;
114     }
115     int oldPosition = 0;
116     // Get the start position of the query result
117     GetRowIndex(oldPosition);
118 
119     while (GoToNextRow() == E_OK) {
120     }
121     count = rowCount;
122     // Reset the start position of the query result
123     GoToRow(oldPosition);
124 
125     return E_OK;
126 }
127 
128 /**
129  * Moves the result set to a specified position
130  */
GoToRow(int position)131 int StepResultSet::GoToRow(int position)
132 {
133     if (!rdb) {
134         return E_ERROR;
135     }
136     // If the moved position is less than zero, reset the result and return an error
137     if (position < 0) {
138         Reset();
139         return E_ERROR;
140     }
141     if (position == rowPos_) {
142         return E_OK;
143     }
144     if (position < rowPos_) {
145         Reset();
146         return GoToRow(position);
147     }
148     while (position != rowPos_) {
149         int errCode = GoToNextRow();
150         if (errCode) {
151             return errCode;
152         }
153     }
154 
155     return E_OK;
156 }
157 
158 /**
159  * Move the result set to the next row
160  */
GoToNextRow()161 int StepResultSet::GoToNextRow()
162 {
163     int errCode = PrepareStep();
164     if (errCode) {
165         return errCode;
166     }
167 
168     int retryCount = 0;
169     errCode = sqliteStatement->Step();
170 
171     while (errCode == SQLITE_LOCKED || errCode == SQLITE_BUSY) {
172         // The table is locked, retry
173         if (retryCount > STEP_QUERY_RETRY_MAX_TIMES) {
174             LOG_ERROR("StepResultSet::GoToNextRow retrycount exceeded");
175             return E_STEP_RESULT_QUERY_EXCEEDED;
176         } else {
177             // Sleep to give the thread holding the lock a chance to finish
178             usleep(STEP_QUERY_RETRY_INTERVAL);
179             errCode = sqliteStatement->Step();
180             retryCount++;
181         }
182     }
183 
184     if (errCode == SQLITE_ROW) {
185         rowPos_++;
186         return E_OK;
187     } else if (errCode == SQLITE_DONE) {
188         isAfterLast = true;
189         rowCount = rowPos_ + 1;
190         FinishStep();
191         return E_STEP_RESULT_IS_AFTER_LAST;
192     } else {
193         LOG_ERROR("StepResultSet::GoToNextRow step err = %{public}d", errCode);
194         FinishStep();
195         return SQLiteError::ErrNo(errCode);
196     }
197 }
198 
199 /**
200  * Checks whether the result set is positioned after the last row
201  */
IsEnded(bool & result)202 int StepResultSet::IsEnded(bool &result)
203 {
204     result = isAfterLast;
205     return E_OK;
206 }
207 
208 /**
209  * Checks whether the result set is moved
210  */
IsStarted(bool & result) const211 int StepResultSet::IsStarted(bool &result) const
212 {
213     result = (rowPos_ != INIT_POS);
214     return E_OK;
215 }
216 
217 /**
218  * Check whether the result set is in the first row
219  */
IsAtFirstRow(bool & result) const220 int StepResultSet::IsAtFirstRow(bool &result) const
221 {
222     result = (rowPos_ == 0);
223     return E_OK;
224 }
225 
GetBlob(int columnIndex,std::vector<uint8_t> & blob)226 int StepResultSet::GetBlob(int columnIndex, std::vector<uint8_t> &blob)
227 {
228     if (rowPos_ == INIT_POS) {
229         return E_STEP_RESULT_QUERY_NOT_EXECUTED;
230     }
231 
232     return sqliteStatement->GetColumnBlob(columnIndex, blob);
233 }
234 
GetString(int columnIndex,std::string & value)235 int StepResultSet::GetString(int columnIndex, std::string &value)
236 {
237     DISTRIBUTED_DATA_HITRACE("StepResultSet::GetString");
238     if (rowPos_ == INIT_POS) {
239         return E_STEP_RESULT_QUERY_NOT_EXECUTED;
240     }
241 
242     int errCode = sqliteStatement->GetColumnString(columnIndex, value);
243     if (errCode != E_OK) {
244         LOG_ERROR("StepResultSet::GetString is err=%{public}d", errCode);
245         return errCode;
246     }
247     return E_OK;
248 }
249 
GetInt(int columnIndex,int & value)250 int StepResultSet::GetInt(int columnIndex, int &value)
251 {
252     if (rowPos_ == INIT_POS) {
253         return E_STEP_RESULT_QUERY_NOT_EXECUTED;
254     }
255 
256     int64_t columnValue;
257     int errCode = sqliteStatement->GetColumnLong(columnIndex, columnValue);
258     if (errCode != E_OK) {
259         return errCode;
260     }
261     value = static_cast<int>(columnValue);
262     return E_OK;
263 }
264 
GetLong(int columnIndex,int64_t & value)265 int StepResultSet::GetLong(int columnIndex, int64_t &value)
266 {
267     if (rowPos_ == INIT_POS) {
268         return E_STEP_RESULT_QUERY_NOT_EXECUTED;
269     }
270     int errCode = sqliteStatement->GetColumnLong(columnIndex, value);
271     if (errCode != E_OK) {
272         return errCode;
273     }
274     return E_OK;
275 }
276 
GetDouble(int columnIndex,double & value)277 int StepResultSet::GetDouble(int columnIndex, double &value)
278 {
279     if (rowPos_ == INIT_POS) {
280         return E_STEP_RESULT_QUERY_NOT_EXECUTED;
281     }
282     int errCode = sqliteStatement->GetColumnDouble(columnIndex, value);
283     if (errCode != E_OK) {
284         return errCode;
285     }
286     return E_OK;
287 }
288 
IsColumnNull(int columnIndex,bool & isNull)289 int StepResultSet::IsColumnNull(int columnIndex, bool &isNull)
290 {
291     ColumnType columnType;
292     int errCode = GetColumnType(columnIndex, columnType);
293     if (errCode != E_OK) {
294         return errCode;
295     }
296     isNull = (columnType == ColumnType::TYPE_NULL);
297     return E_OK;
298 }
299 
300 /**
301  * Check whether the result set is over
302  */
IsClosed() const303 bool StepResultSet::IsClosed() const
304 {
305     return isClosed;
306 }
307 
Close()308 int StepResultSet::Close()
309 {
310     if (isClosed) {
311         return E_OK;
312     }
313     isClosed = true;
314     int errCode = FinishStep();
315     rdb = nullptr;
316     return errCode;
317 }
318 
CheckSession()319 int StepResultSet::CheckSession()
320 {
321     if (std::this_thread::get_id() != tid) {
322         LOG_ERROR("StepResultSet is passed cross threads!");
323         return E_STEP_RESULT_SET_CROSS_THREADS;
324     }
325     return E_OK;
326 }
327 
328 /**
329  * Obtain session and prepare precompile statement for step query
330  */
PrepareStep()331 int StepResultSet::PrepareStep()
332 {
333     LOG_DEBUG("begin");
334     if (isClosed) {
335         return E_STEP_RESULT_CLOSED;
336     }
337 
338     if (sqliteStatement != nullptr) {
339         return CheckSession();
340     }
341 
342     int errCode;
343     LOG_DEBUG("rdb->BeginStepQuery begin");
344     sqliteStatement = rdb->BeginStepQuery(errCode, sql, selectionArgs);
345     if (sqliteStatement == nullptr) {
346         rdb->EndStepQuery();
347         return errCode;
348     }
349 
350     LOG_DEBUG("get_id begin");
351     tid = std::this_thread::get_id();
352     return E_OK;
353 }
354 
355 /**
356  * Release resource of step result set, this method can be called more than once
357  */
FinishStep()358 int StepResultSet::FinishStep()
359 {
360     if (sqliteStatement == nullptr) {
361         return E_OK;
362     }
363 
364     int errCode = CheckSession();
365     if (errCode != E_OK) {
366         return errCode;
367     }
368 
369     sqliteStatement = nullptr;
370     rowPos_ = INIT_POS;
371     if (rdb != nullptr) {
372         errCode = rdb->EndStepQuery();
373     }
374     if (errCode != E_OK) {
375         LOG_ERROR("StepResultSet::FinishStep err = %{public}d", errCode);
376     }
377     return errCode;
378 }
379 
380 /**
381  * Reset the statement
382  */
Reset()383 void StepResultSet::Reset()
384 {
385     if (sqliteStatement != nullptr) {
386         sqlite3_reset(sqliteStatement->GetSql3Stmt());
387     }
388     rowPos_ = INIT_POS;
389     isAfterLast = false;
390 }
391 } // namespace NativeRdb
392 } // namespace OHOS