• 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 #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