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 #include "sqlite_shared_result_set.h"
17
18 #include <rdb_errno.h>
19
20 #include <algorithm>
21 #include <memory>
22
23 #include "logger.h"
24 #include "rdb_sql_utils.h"
25 #include "sqlite_utils.h"
26
27 namespace OHOS {
28 namespace NativeRdb {
29 using namespace OHOS::Rdb;
30
SqliteSharedResultSet(std::shared_ptr<RdbStoreImpl> store,SqliteConnectionPool * connectionPool,std::string path,std::string sql,const std::vector<ValueObject> & bindArgs)31 SqliteSharedResultSet::SqliteSharedResultSet(std::shared_ptr<RdbStoreImpl> store, SqliteConnectionPool *connectionPool,
32 std::string path, std::string sql, const std::vector<ValueObject> &bindArgs)
33 : AbsSharedResultSet(path), store_(store), connectionPool_(connectionPool), resultSetBlockCapacity(0),
34 isOnlyFillResultSetBlock(false), qrySql(sql), bindArgs_(std::move(bindArgs)), rowNum(NO_COUNT)
35 {
36 }
37
~SqliteSharedResultSet()38 SqliteSharedResultSet::~SqliteSharedResultSet() {
39 }
40
PrepareStep(SqliteConnection * connection,int & errCode)41 std::shared_ptr<SqliteStatement> SqliteSharedResultSet::PrepareStep(SqliteConnection* connection, int &errCode)
42 {
43 if (SqliteUtils::GetSqlStatementType(qrySql) != SqliteUtils::STATEMENT_SELECT) {
44 LOG_ERROR("StoreSession BeginStepQuery fail : not select sql !");
45 errCode = E_EXECUTE_IN_STEP_QUERY;
46 return nullptr;
47 }
48
49 std::shared_ptr<SqliteStatement> sqliteStatement = connection->BeginStepQuery(errCode,
50 qrySql, bindArgs_);
51 if (sqliteStatement == nullptr) {
52 connection->EndStepQuery();
53 }
54
55 return sqliteStatement;
56 }
57
GetAllColumnNames(std::vector<std::string> & columnNames)58 int SqliteSharedResultSet::GetAllColumnNames(std::vector<std::string> &columnNames)
59 {
60 if (!columnNames_.empty()) {
61 columnNames = columnNames_;
62 return E_OK;
63 }
64
65 if (isClosed) {
66 return E_STEP_RESULT_CLOSED;
67 }
68
69 SqliteConnection *connection = connectionPool_->AcquireConnection(true);
70 if (connection == nullptr) {
71 return E_CON_OVER_LIMIT;
72 }
73
74 int errCode = E_OK;
75 std::shared_ptr<SqliteStatement> sqliteStatement = PrepareStep(connection, errCode);
76 if (sqliteStatement == nullptr) {
77 connectionPool_->ReleaseConnection(connection);
78 return errCode;
79 }
80
81 int columnCount = 0;
82 // Get the total number of columns
83 errCode = sqliteStatement->GetColumnCount(columnCount);
84 if (errCode) {
85 connectionPool_->ReleaseConnection(connection);
86 return errCode;
87 }
88
89 std::lock_guard<std::mutex> lock(columnNamesLock_);
90 for (int i = 0; i < columnCount; i++) {
91 std::string columnName;
92 errCode = sqliteStatement->GetColumnName(i, columnName);
93 if (errCode) {
94 connectionPool_->ReleaseConnection(connection);
95 columnNames_.clear();
96 return errCode;
97 }
98 columnNames_.push_back(columnName);
99 }
100
101 columnNames = columnNames_;
102 columnCount_ = static_cast<int>(columnNames_.size());
103 connection->EndStepQuery();
104 connectionPool_->ReleaseConnection(connection);
105
106 return E_OK;
107 }
108
GetRowCount(int & count)109 int SqliteSharedResultSet::GetRowCount(int &count)
110 {
111 if (rowNum != NO_COUNT) {
112 count = rowNum;
113 return E_OK;
114 }
115
116 if (isClosed) {
117 return E_STEP_RESULT_CLOSED;
118 }
119
120 FillSharedBlock(0);
121 count = rowNum;
122 return E_OK;
123 }
124
Close()125 int SqliteSharedResultSet::Close()
126 {
127 AbsSharedResultSet::Close();
128 return E_OK;
129 }
130
OnGo(int oldPosition,int newPosition)131 bool SqliteSharedResultSet::OnGo(int oldPosition, int newPosition)
132 {
133 if (GetBlock() == nullptr) {
134 FillSharedBlock(newPosition);
135 return true;
136 }
137 if ((uint32_t)newPosition < GetBlock()->GetStartPos() || (uint32_t)newPosition >= GetBlock()->GetLastPos() ||
138 oldPosition == rowNum) {
139 FillSharedBlock(newPosition);
140 }
141 return true;
142 }
143
144 /**
145 * Calculate a proper start position to fill the block.
146 */
PickFillBlockStartPosition(int resultSetPosition,int blockCapacity) const147 int SqliteSharedResultSet::PickFillBlockStartPosition(int resultSetPosition, int blockCapacity) const
148 {
149 return std::max(resultSetPosition - blockCapacity / PICK_POS, 0);
150 }
151
FillSharedBlock(int requiredPos)152 void SqliteSharedResultSet::FillSharedBlock(int requiredPos)
153 {
154 ClearBlock();
155 SqliteConnection* connection = connectionPool_->AcquireConnection(true);
156 if (connection == nullptr) {
157 return;
158 }
159 AppDataFwk::SharedBlock *sharedBlock = GetBlock();
160 if (sharedBlock == nullptr) {
161 return;
162 }
163 if (rowNum == NO_COUNT) {
164 connection->ExecuteForSharedBlock(rowNum, qrySql, bindArgs_, sharedBlock, requiredPos, requiredPos, true);
165 resultSetBlockCapacity = static_cast<int>(sharedBlock->GetRowNum());
166 if (resultSetBlockCapacity > 0) {
167 sharedBlock->SetStartPos(requiredPos);
168 sharedBlock->SetBlockPos(0);
169 sharedBlock->SetLastPos(requiredPos + resultSetBlockCapacity);
170 }
171 } else {
172 int blockRowNum = rowNum;
173 int startPos =
174 isOnlyFillResultSetBlock ? requiredPos : PickFillBlockStartPosition(requiredPos, resultSetBlockCapacity);
175 connection->ExecuteForSharedBlock(blockRowNum, qrySql, bindArgs_, sharedBlock, startPos, requiredPos, false);
176 int currentBlockCapacity = static_cast<int>(sharedBlock->GetRowNum());
177 sharedBlock->SetStartPos((uint32_t)startPos);
178 sharedBlock->SetBlockPos(requiredPos - startPos);
179 sharedBlock->SetLastPos(startPos + currentBlockCapacity);
180 LOG_INFO("requiredPos= %{public}d, startPos_= %{public}" PRIu32 ", lastPos_= %{public}" PRIu32
181 ", blockPos_= %{public}" PRIu32 ".",
182 requiredPos, sharedBlock->GetStartPos(), sharedBlock->GetLastPos(), sharedBlock->GetBlockPos());
183 }
184 connectionPool_->ReleaseConnection(connection);
185 }
186
SetBlock(AppDataFwk::SharedBlock * block)187 void SqliteSharedResultSet::SetBlock(AppDataFwk::SharedBlock *block)
188 {
189 AbsSharedResultSet::SetBlock(block);
190 rowNum = NO_COUNT;
191 }
192
193 /**
194 * If isOnlyFillResultSetBlockInput is true, use the input requiredPos to fill the block, otherwise pick the value
195 * from requirePos and resultSetBlockCapacity.
196 */
SetFillBlockForwardOnly(bool isOnlyFillResultSetBlockInput)197 void SqliteSharedResultSet::SetFillBlockForwardOnly(bool isOnlyFillResultSetBlockInput)
198 {
199 isOnlyFillResultSetBlock = isOnlyFillResultSetBlockInput;
200 }
201
Finalize()202 void SqliteSharedResultSet::Finalize()
203 {
204 Close();
205 }
206 } // namespace NativeRdb
207 } // namespace OHOS