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