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
17 #include "sqlite_shared_result_set.h"
18 #include <algorithm>
19 #include <memory>
20 #include <rdb_errno.h>
21 #include "logger.h"
22
23 namespace OHOS {
24 namespace NativeRdb {
SqliteSharedResultSet(std::shared_ptr<RdbStoreImpl> rdbSreImpl,std::string path,std::string sql,const std::vector<std::string> & bindArgs)25 SqliteSharedResultSet::SqliteSharedResultSet(std::shared_ptr<RdbStoreImpl> rdbSreImpl, std::string path,
26 std::string sql, const std::vector<std::string> &bindArgs)
27 : AbsSharedResultSet(path), resultSetBlockCapacity(0), isOnlyFillResultSetBlock(false), rdbStoreImpl(rdbSreImpl),
28 qrySql(sql), selectionArgVec(bindArgs), rowNum(NO_COUNT)
29 {}
30
~SqliteSharedResultSet()31 SqliteSharedResultSet::~SqliteSharedResultSet() {}
32
GetAllColumnNames(std::vector<std::string> & columnNames)33 int SqliteSharedResultSet::GetAllColumnNames(std::vector<std::string> &columnNames)
34 {
35 int errCode = PrepareStep();
36 if (errCode) {
37 return errCode;
38 }
39 int columnCount = 0;
40 // Get the total number of columns
41 errCode = sqliteStatement->GetColumnCount(columnCount);
42 if (errCode) {
43 return errCode;
44 }
45 columnNames.clear();
46 for (int i = 0; i < columnCount; i++) {
47 std::string columnName;
48 errCode = sqliteStatement->GetColumnName(i, columnName);
49 if (errCode) {
50 columnNames.clear();
51 return errCode;
52 }
53 columnNames.push_back(columnName);
54 }
55
56 rdbStoreImpl->EndStepQuery();
57 sqliteStatement = nullptr;
58
59 return E_OK;
60 }
61
GetRowCount(int & count)62 int SqliteSharedResultSet::GetRowCount(int &count)
63 {
64 if (rowNum == NO_COUNT) {
65 FillSharedBlock(0);
66 }
67 count = rowNum;
68 return E_OK;
69 }
70
Close()71 int SqliteSharedResultSet::Close()
72 {
73 std::lock_guard<std::mutex> lock(sessionMutex);
74
75 AbsSharedResultSet::Close();
76
77 return E_OK;
78 }
79
80 /**
81 * Get the rdb store that this result set is associated with.
82 */
GetRdbStore() const83 std::shared_ptr<RdbStore> SqliteSharedResultSet::GetRdbStore() const
84 {
85 return rdbStoreImpl;
86 }
87
OnGo(int oldPosition,int newPosition)88 bool SqliteSharedResultSet::OnGo(int oldPosition, int newPosition)
89 {
90 if (GetBlock() == nullptr) {
91 FillSharedBlock(newPosition);
92 return true;
93 }
94 if (newPosition >= (int)GetBlock()->GetRowNum()) {
95 FillSharedBlock(newPosition);
96 }
97 return true;
98 }
99
100 /**
101 * Calculate a proper start position to fill the block.
102 */
PickFillBlockStartPosition(int resultSetPosition,int blockCapacity) const103 int SqliteSharedResultSet::PickFillBlockStartPosition(int resultSetPosition, int blockCapacity) const
104 {
105 return std::max(resultSetPosition - blockCapacity / PICK_POS, 0);
106 }
107
FillSharedBlock(int requiredPos)108 void SqliteSharedResultSet::FillSharedBlock(int requiredPos)
109 {
110 ClearBlock();
111
112 if (!HasBlock()) {
113 LOG_ERROR("SqliteSharedResultSet::FillSharedBlock sharedBlock is null.");
114 return;
115 }
116
117 std::vector<ValueObject> bindArgs;
118 size_t size = selectionArgVec.size();
119
120 for (size_t i = 0; i < size; i++) {
121 ValueObject vauObj(selectionArgVec[i]);
122 bindArgs.push_back(vauObj);
123 }
124
125 if (rowNum == NO_COUNT) {
126 rdbStoreImpl->ExecuteForSharedBlock(rowNum, GetBlock(), requiredPos, requiredPos, true, qrySql, bindArgs);
127 resultSetBlockCapacity = static_cast<int>(GetBlock()->GetRowNum());
128 } else {
129 int startPos =
130 isOnlyFillResultSetBlock ? requiredPos : PickFillBlockStartPosition(requiredPos, resultSetBlockCapacity);
131 rdbStoreImpl->ExecuteForSharedBlock(rowNum, GetBlock(), startPos, requiredPos, false, qrySql, bindArgs);
132 }
133 }
134
SetBlock(AppDataFwk::SharedBlock * block)135 void SqliteSharedResultSet::SetBlock(AppDataFwk::SharedBlock *block)
136 {
137 AbsSharedResultSet::SetBlock(block);
138 rowNum = NO_COUNT;
139 }
140
141 /**
142 * If isOnlyFillResultSetBlockInput is true, use the input requiredPos to fill the block, otherwise pick the value
143 * from requirePos and resultSetBlockCapacity.
144 */
SetFillBlockForwardOnly(bool isOnlyFillResultSetBlockInput)145 void SqliteSharedResultSet::SetFillBlockForwardOnly(bool isOnlyFillResultSetBlockInput)
146 {
147 isOnlyFillResultSetBlock = isOnlyFillResultSetBlockInput;
148 }
149
Finalize()150 void SqliteSharedResultSet::Finalize()
151 {
152 if (!AbsSharedResultSet::IsClosed()) {
153 if (rdbStoreImpl->IsOpen()) {
154 std::string filePath = rdbStoreImpl->GetPath();
155 std::string name = rdbStoreImpl->IsMemoryRdb() ? ":memory" : filePath;
156 }
157 Close();
158 }
159 }
160
PrepareStep()161 int SqliteSharedResultSet::PrepareStep()
162 {
163 if (IsClosed()) {
164 return E_STEP_RESULT_CLOSED;
165 }
166 if (sqliteStatement != nullptr) {
167 return CheckSession();
168 }
169 int errCode;
170 sqliteStatement = rdbStoreImpl->BeginStepQuery(errCode, qrySql, selectionArgVec);
171 if (sqliteStatement == nullptr) {
172 rdbStoreImpl->EndStepQuery();
173 return errCode;
174 }
175 tid = std::this_thread::get_id();
176 return E_OK;
177 }
178
CheckSession()179 int SqliteSharedResultSet::CheckSession()
180 {
181 if (std::this_thread::get_id() != tid) {
182 return E_STEP_RESULT_SET_CROSS_THREADS;
183 }
184 return E_OK;
185 }
186 } // namespace NativeRdb
187 } // namespace OHOS