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 if (columnNames_.empty()){
36 std::lock_guard<std::mutex> lock(mutex_);
37 if (columnNames_.empty()) {
38 int errCode = PrepareStep();
39 if (errCode) {
40 return errCode;
41 }
42 int columnCount = 0;
43 // Get the total number of columns
44 errCode = sqliteStatement->GetColumnCount(columnCount);
45 if (errCode) {
46 return errCode;
47 }
48 columnNames_.clear();
49 for (int i = 0; i < columnCount; i++) {
50 std::string columnName;
51 errCode = sqliteStatement->GetColumnName(i, columnName);
52 if (errCode) {
53 columnNames_.clear();
54 return errCode;
55 }
56 columnNames_.push_back(columnName);
57 transform(columnName.begin(), columnName.end(), columnName.begin(), ::tolower);
58 columnMap_[columnName] = i;
59 }
60
61 rdbStoreImpl->EndStepQuery();
62 sqliteStatement = nullptr;
63 }
64 }
65
66 columnNames.assign(columnNames_.begin(), columnNames_.end());
67 return E_OK;
68 }
69
GetRowCount(int & count)70 int SqliteSharedResultSet::GetRowCount(int &count)
71 {
72 if (rowNum == NO_COUNT) {
73 FillSharedBlock(0);
74 }
75 count = rowNum;
76 return E_OK;
77 }
78
Close()79 int SqliteSharedResultSet::Close()
80 {
81 std::lock_guard<std::mutex> lock(sessionMutex);
82
83 AbsSharedResultSet::Close();
84
85 return E_OK;
86 }
87
88 /**
89 * Get the rdb store that this result set is associated with.
90 */
GetRdbStore() const91 std::shared_ptr<RdbStore> SqliteSharedResultSet::GetRdbStore() const
92 {
93 return rdbStoreImpl;
94 }
95
OnGo(int oldPosition,int newPosition)96 bool SqliteSharedResultSet::OnGo(int oldPosition, int newPosition)
97 {
98 if (GetBlock() == nullptr) {
99 FillSharedBlock(newPosition);
100 return true;
101 }
102 if ((uint32_t)newPosition < GetBlock()->GetStartPos() || (uint32_t)newPosition >= GetBlock()->GetLastPos() ||
103 oldPosition == rowNum) {
104 FillSharedBlock(newPosition);
105 }
106 return true;
107 }
108
109 /**
110 * Calculate a proper start position to fill the block.
111 */
PickFillBlockStartPosition(int resultSetPosition,int blockCapacity) const112 int SqliteSharedResultSet::PickFillBlockStartPosition(int resultSetPosition, int blockCapacity) const
113 {
114 return std::max(resultSetPosition - blockCapacity / PICK_POS, 0);
115 }
116
FillSharedBlock(int requiredPos)117 void SqliteSharedResultSet::FillSharedBlock(int requiredPos)
118 {
119 ClearBlock();
120
121 if (!HasBlock()) {
122 LOG_ERROR("SqliteSharedResultSet::FillSharedBlock sharedBlock is null.");
123 return;
124 }
125
126 std::vector<ValueObject> bindArgs;
127 size_t size = selectionArgVec.size();
128
129 for (size_t i = 0; i < size; i++) {
130 ValueObject vauObj(selectionArgVec[i]);
131 bindArgs.push_back(vauObj);
132 }
133
134 if (rowNum == NO_COUNT) {
135 rdbStoreImpl->ExecuteForSharedBlock(rowNum, GetBlock(), requiredPos, requiredPos, true, qrySql, bindArgs);
136 resultSetBlockCapacity = static_cast<int>(GetBlock()->GetRowNum());
137 if (resultSetBlockCapacity > 0) {
138 GetBlock()->SetStartPos(requiredPos);
139 GetBlock()->SetBlockPos(0);
140 GetBlock()->SetLastPos(requiredPos + resultSetBlockCapacity);
141 }
142 } else {
143 int blockRowNum = rowNum;
144 int startPos = (int)GetBlock()->GetStartPos();
145 startPos =
146 isOnlyFillResultSetBlock ? requiredPos : PickFillBlockStartPosition(requiredPos, resultSetBlockCapacity);
147 rdbStoreImpl->ExecuteForSharedBlock(blockRowNum, GetBlock(), startPos, requiredPos, false, qrySql, bindArgs);
148 int currentBlockCapacity = static_cast<int>(GetBlock()->GetRowNum());
149 GetBlock()->SetStartPos((uint32_t)startPos);
150 GetBlock()->SetBlockPos(requiredPos - startPos);
151 GetBlock()->SetLastPos(startPos + currentBlockCapacity);
152 LOG_INFO("requiredPos= %{public}d, startPos_= %{public}" PRIu32 ", lastPos_= %{public}" PRIu32
153 ", blockPos_= %{public}" PRIu32 ".",
154 requiredPos, GetBlock()->GetStartPos(), GetBlock()->GetLastPos(), GetBlock()->GetBlockPos());
155 }
156 }
157
SetBlock(AppDataFwk::SharedBlock * block)158 void SqliteSharedResultSet::SetBlock(AppDataFwk::SharedBlock *block)
159 {
160 AbsSharedResultSet::SetBlock(block);
161 rowNum = NO_COUNT;
162 }
163
164 /**
165 * If isOnlyFillResultSetBlockInput is true, use the input requiredPos to fill the block, otherwise pick the value
166 * from requirePos and resultSetBlockCapacity.
167 */
SetFillBlockForwardOnly(bool isOnlyFillResultSetBlockInput)168 void SqliteSharedResultSet::SetFillBlockForwardOnly(bool isOnlyFillResultSetBlockInput)
169 {
170 isOnlyFillResultSetBlock = isOnlyFillResultSetBlockInput;
171 }
172
Finalize()173 void SqliteSharedResultSet::Finalize()
174 {
175 if (!AbsSharedResultSet::IsClosed()) {
176 if (rdbStoreImpl->IsOpen()) {
177 std::string filePath = rdbStoreImpl->GetPath();
178 std::string name = rdbStoreImpl->IsMemoryRdb() ? ":memory" : filePath;
179 }
180 Close();
181 }
182 }
183
PrepareStep()184 int SqliteSharedResultSet::PrepareStep()
185 {
186 if (IsClosed()) {
187 return E_STEP_RESULT_CLOSED;
188 }
189 if (sqliteStatement != nullptr) {
190 return CheckSession();
191 }
192 int errCode;
193 sqliteStatement = rdbStoreImpl->BeginStepQuery(errCode, qrySql, selectionArgVec);
194 if (sqliteStatement == nullptr) {
195 rdbStoreImpl->EndStepQuery();
196 return errCode;
197 }
198 tid = std::this_thread::get_id();
199 return E_OK;
200 }
201
CheckSession()202 int SqliteSharedResultSet::CheckSession()
203 {
204 if (std::this_thread::get_id() != tid) {
205 return E_STEP_RESULT_SET_CROSS_THREADS;
206 }
207 return E_OK;
208 }
209 } // namespace NativeRdb
210 } // namespace OHOS