1 /*
2 * Copyright (C) 2021-2022 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 #define MLOG_TAG "FetchResult"
16
17 #include "fetch_result.h"
18 #include "album_asset.h"
19 #include "media_log.h"
20 #include "medialibrary_tracer.h"
21
22 using namespace std;
23
24 namespace OHOS {
25 namespace Media {
26 static const unordered_map<string, ResultSetDataType> RESULT_TYPE_MAP = {
27 { MEDIA_DATA_DB_ID, TYPE_INT32 },
28 { MEDIA_DATA_DB_NAME, TYPE_STRING },
29 { MEDIA_DATA_DB_RELATIVE_PATH, TYPE_STRING },
30 { MEDIA_DATA_DB_MEDIA_TYPE, TYPE_INT32 },
31 { MEDIA_DATA_DB_PARENT_ID, TYPE_INT32 },
32 { MEDIA_DATA_DB_SIZE, TYPE_INT64 },
33 { MEDIA_DATA_DB_DATE_ADDED, TYPE_INT64 },
34 { MEDIA_DATA_DB_DATE_MODIFIED, TYPE_INT64 },
35 { MEDIA_DATA_DB_DATE_TAKEN, TYPE_INT64 },
36 { MEDIA_DATA_DB_FILE_PATH, TYPE_STRING },
37 { MEDIA_DATA_DB_MIME_TYPE, TYPE_STRING },
38 { MEDIA_DATA_DB_TITLE, TYPE_STRING },
39 { MEDIA_DATA_DB_ARTIST, TYPE_STRING },
40 { MEDIA_DATA_DB_ALBUM, TYPE_STRING },
41 { MEDIA_DATA_DB_WIDTH, TYPE_INT32 },
42 { MEDIA_DATA_DB_HEIGHT, TYPE_INT32 },
43 { MEDIA_DATA_DB_DURATION, TYPE_INT32 },
44 { MEDIA_DATA_DB_ORIENTATION, TYPE_INT32 },
45 { MEDIA_DATA_DB_BUCKET_ID, TYPE_INT32 },
46 { MEDIA_DATA_DB_BUCKET_NAME, TYPE_STRING },
47 { MEDIA_DATA_DB_TIME_PENDING, TYPE_INT64 },
48 { MEDIA_DATA_DB_IS_PENDING, TYPE_INT32 },
49 { MEDIA_DATA_DB_IS_FAV, TYPE_INT32 },
50 { MEDIA_DATA_DB_DATE_TRASHED, TYPE_INT64 },
51 { MEDIA_DATA_DB_SELF_ID, TYPE_STRING },
52 { MEDIA_DATA_DB_RECYCLE_PATH, TYPE_STRING },
53 { MEDIA_DATA_DB_IS_TRASH, TYPE_INT32 },
54 { MEDIA_DATA_DB_AUDIO_ALBUM, TYPE_STRING },
55 };
56
57 template <class T>
FetchResult(const shared_ptr<DataShare::DataShareResultSet> & resultset)58 FetchResult<T>::FetchResult(const shared_ptr<DataShare::DataShareResultSet> &resultset)
59 {
60 count_ = 0;
61 if (resultset != nullptr) {
62 resultset->GetRowCount(count_);
63 }
64 isContain_ = count_ > 0;
65 isClosed_ = false;
66 resultset_ = resultset;
67 networkId_ = "";
68 resultNapiType_ = ResultNapiType::TYPE_NAPI_MAX;
69 if (std::is_same<T, FileAsset>::value) {
70 fetchResType_ = FetchResType::TYPE_FILE;
71 } else if (std::is_same<T, AlbumAsset>::value) {
72 fetchResType_ = FetchResType::TYPE_ALBUM;
73 } else if (std::is_same<T, SmartAlbumAsset>::value) {
74 fetchResType_ = FetchResType::TYPE_SMARTALBUM;
75 } else {
76 MEDIA_ERR_LOG("unsupported FetchResType");
77 fetchResType_ = FetchResType::TYPE_FILE;
78 }
79 }
80
81 template <class T>
82 // empty constructor napi
FetchResult()83 FetchResult<T>::FetchResult()
84 : isContain_(false), isClosed_(false), count_(0), resultNapiType_(ResultNapiType::TYPE_NAPI_MAX),
85 resultset_(nullptr) {}
86
87 template <class T>
~FetchResult()88 FetchResult<T>::~FetchResult() {}
89
90 template <class T>
Close()91 void FetchResult<T>::Close()
92 {
93 isClosed_ = true;
94 }
95
96 template <class T>
IsContain()97 bool FetchResult<T>::IsContain()
98 {
99 return isContain_;
100 }
101
102 template <class T>
GetCount()103 int32_t FetchResult<T>::GetCount()
104 {
105 return count_;
106 }
107
108 template <class T>
IsClosed()109 bool FetchResult<T>::IsClosed()
110 {
111 return isClosed_;
112 }
113
114 template <class T>
SetInfo(unique_ptr<FetchResult<T>> & fetch)115 void FetchResult<T>::SetInfo(unique_ptr<FetchResult<T>> &fetch)
116 {
117 isContain_ = fetch->isContain_;
118 isClosed_ = fetch->isClosed_;
119 count_ = fetch->count_;
120 networkId_ = fetch->networkId_;
121 resultNapiType_ = fetch->resultNapiType_;
122 typeMask_ = fetch->typeMask_;
123 }
124
125 template <class T>
SetNetworkId(const string & networkId)126 void FetchResult<T>::SetNetworkId(const string &networkId)
127 {
128 networkId_ = networkId;
129 }
130
131 template <class T>
GetObjectAtPosition(int32_t index)132 unique_ptr<T> FetchResult<T>::GetObjectAtPosition(int32_t index)
133 {
134 if ((index < 0) || (index > (count_ - 1)) || (resultset_ == nullptr)) {
135 MEDIA_ERR_LOG("index not proper or rs is null");
136 return nullptr;
137 }
138
139 if (resultset_->GoToRow(index) != 0) {
140 MEDIA_ERR_LOG("failed to go to row at index pos");
141 return nullptr;
142 }
143
144 return GetObject();
145 }
146
147 template <class T>
GetFirstObject()148 unique_ptr<T> FetchResult<T>::GetFirstObject()
149 {
150 if ((resultset_ == nullptr) || (resultset_->GoToFirstRow() != 0)) {
151 MEDIA_ERR_LOG("resultset is null|first row failed");
152 return nullptr;
153 }
154
155 return GetObject();
156 }
157
158 template <class T>
GetNextObject()159 unique_ptr<T> FetchResult<T>::GetNextObject()
160 {
161 if ((resultset_ == nullptr) || (resultset_->GoToNextRow() != 0)) {
162 MEDIA_ERR_LOG("resultset is null|go to next row failed");
163 return nullptr;
164 }
165
166 return GetObject();
167 }
168
169 template <class T>
GetLastObject()170 unique_ptr<T> FetchResult<T>::GetLastObject()
171 {
172 if ((resultset_ == nullptr) || (resultset_->GoToLastRow() != 0)) {
173 MEDIA_ERR_LOG("resultset is null|go to last row failed");
174 return nullptr;
175 }
176
177 return GetObject();
178 }
179
180 template <class T>
IsAtLastRow()181 bool FetchResult<T>::IsAtLastRow()
182 {
183 if (resultset_ == nullptr) {
184 MEDIA_ERR_LOG("resultset null");
185 return false;
186 }
187
188 bool retVal = false;
189 resultset_->IsAtLastRow(retVal);
190 return retVal;
191 }
192
ReturnDefaultOnError(string errMsg,ResultSetDataType dataType)193 variant<int32_t, int64_t, string> ReturnDefaultOnError(string errMsg, ResultSetDataType dataType)
194 {
195 MEDIA_ERR_LOG("%{public}s", errMsg.c_str());
196 if (dataType == TYPE_STRING) {
197 return "";
198 } else if (dataType == TYPE_INT64) {
199 return static_cast<int64_t>(0);
200 } else {
201 return 0;
202 }
203 }
204
205 template <class T>
GetRowValFromColumn(string columnName,ResultSetDataType dataType,shared_ptr<NativeRdb::AbsSharedResultSet> & resultSet)206 variant<int32_t, int64_t, string> FetchResult<T>::GetRowValFromColumn(string columnName, ResultSetDataType dataType,
207 shared_ptr<NativeRdb::AbsSharedResultSet> &resultSet)
208 {
209 if ((resultset_ == nullptr) && (resultSet == nullptr)) {
210 return ReturnDefaultOnError("Resultset is null", dataType);
211 }
212 int index;
213 int status;
214 if (resultSet) {
215 status = resultSet->GetColumnIndex(columnName, index);
216 } else {
217 status = resultset_->GetColumnIndex(columnName, index);
218 }
219 if (status != NativeRdb::E_OK) {
220 ReturnDefaultOnError("failed to obtain the index", dataType);
221 }
222 return GetValByIndex(index, dataType, resultSet);
223 }
224
225 template <class T>
GetValByIndex(int32_t index,ResultSetDataType dataType,shared_ptr<NativeRdb::AbsSharedResultSet> & resultSet)226 variant<int32_t, int64_t, string> FetchResult<T>::GetValByIndex(int32_t index, ResultSetDataType dataType,
227 shared_ptr<NativeRdb::AbsSharedResultSet> &resultSet)
228 {
229 if ((resultset_ == nullptr) && (resultSet == nullptr)) {
230 return ReturnDefaultOnError("Resultset is null", dataType);
231 }
232
233 variant<int32_t, int64_t, string> cellValue;
234 int integerVal = 0;
235 string stringVal = "";
236 int64_t longVal = 0;
237 int status;
238 switch (dataType) {
239 case TYPE_STRING:
240 if (resultSet) {
241 status = resultSet->GetString(index, stringVal);
242 } else {
243 status = resultset_->GetString(index, stringVal);
244 }
245 cellValue = stringVal;
246 break;
247 case TYPE_INT32:
248 if (resultSet) {
249 status = resultSet->GetInt(index, integerVal);
250 } else {
251 status = resultset_->GetInt(index, integerVal);
252 }
253 cellValue = integerVal;
254 break;
255 case TYPE_INT64:
256 if (resultSet) {
257 status = resultSet->GetLong(index, longVal);
258 } else {
259 status = resultset_->GetLong(index, longVal);
260 }
261 cellValue = longVal;
262 break;
263 default:
264 MEDIA_ERR_LOG("not match dataType %{public}d", dataType);
265 break;
266 }
267
268 return cellValue;
269 }
270
GetFileMediaTypeUri(MediaType mediaType,const string & networkId)271 static string GetFileMediaTypeUri(MediaType mediaType, const string &networkId)
272 {
273 string uri = MEDIALIBRARY_DATA_ABILITY_PREFIX + networkId + MEDIALIBRARY_DATA_URI_IDENTIFIER;
274 switch (mediaType) {
275 case MEDIA_TYPE_AUDIO:
276 return uri + MEDIALIBRARY_TYPE_AUDIO_URI;
277 case MEDIA_TYPE_VIDEO:
278 return uri + MEDIALIBRARY_TYPE_VIDEO_URI;
279 case MEDIA_TYPE_IMAGE:
280 return uri + MEDIALIBRARY_TYPE_IMAGE_URI;
281 case MEDIA_TYPE_FILE:
282 default:
283 return uri + MEDIALIBRARY_TYPE_FILE_URI;
284 }
285 }
286
MediaTypeToMask(MediaType mediaType,std::string & typeMask)287 static void MediaTypeToMask(MediaType mediaType, std::string &typeMask)
288 {
289 typeMask.resize(TYPE_MASK_STRING_SIZE, TYPE_MASK_BIT_DEFAULT);
290 if ((mediaType >= MEDIA_TYPE_FILE) && (mediaType <= MEDIA_TYPE_AUDIO)) {
291 typeMask[std::get<POS_TYPE_MASK_STRING_INDEX>(MEDIA_TYPE_TUPLE_VEC[mediaType])] = TYPE_MASK_BIT_SET;
292 }
293 }
294
UriAddFragmentTypeMask(std::string & uri,const std::string & typeMask)295 static void UriAddFragmentTypeMask(std::string &uri, const std::string &typeMask)
296 {
297 if (!typeMask.empty()) {
298 uri += "#" + URI_PARAM_KEY_TYPE + ":" + typeMask;
299 }
300 }
301
302 template<class T>
GetFileCount(const shared_ptr<DataShare::DataShareResultSet> & resultSet)303 int32_t FetchResult<T>::GetFileCount(const shared_ptr<DataShare::DataShareResultSet> &resultSet)
304 {
305 int32_t count = 1;
306 if (resultSet) {
307 string name;
308 resultSet->GetColumnName(0, name);
309 if (name.find("count(") != string::npos) {
310 resultSet->GetInt(0, count);
311 }
312 }
313 return count;
314 }
315
316 template<class T>
SetFileAsset(FileAsset * fileAsset,shared_ptr<NativeRdb::AbsSharedResultSet> & resultSet)317 void FetchResult<T>::SetFileAsset(FileAsset *fileAsset, shared_ptr<NativeRdb::AbsSharedResultSet> &resultSet)
318 {
319 if ((resultset_ == nullptr) && (resultSet == nullptr)) {
320 MEDIA_ERR_LOG("SetFileAsset fail, result is nullptr");
321 return;
322 }
323 vector<string> columnNames;
324 if (resultSet != nullptr) {
325 resultSet->GetAllColumnNames(columnNames);
326 } else {
327 resultset_->GetAllColumnNames(columnNames);
328 }
329 int32_t index = -1;
330 auto &map = fileAsset->GetMemberMap();
331 for (const auto &name : columnNames) {
332 index++;
333 if (RESULT_TYPE_MAP.count(name) == 0) {
334 continue;
335 }
336 auto memberType = RESULT_TYPE_MAP.at(name);
337 map.emplace(move(name), move(GetValByIndex(index, memberType, resultSet)));
338 }
339 fileAsset->SetResultNapiType(resultNapiType_);
340 fileAsset->SetCount(GetFileCount(resultset_));
341 string typeMask;
342 MediaTypeToMask(fileAsset->GetMediaType(), typeMask);
343 string uri = GetFileMediaTypeUri(fileAsset->GetMediaType(), networkId_) + "/" + to_string(fileAsset->GetId());
344 if (resultNapiType_ == ResultNapiType::TYPE_USERFILE_MGR) {
345 UriAddFragmentTypeMask(uri, typeMask);
346 }
347 fileAsset->SetUri(uri);
348 }
349
350 template<class T>
GetObjectFromAsset(FileAsset * asset,shared_ptr<NativeRdb::AbsSharedResultSet> & resultSet)351 void FetchResult<T>::GetObjectFromAsset(FileAsset *asset, shared_ptr<NativeRdb::AbsSharedResultSet> &resultSet)
352 {
353 SetFileAsset(asset, resultSet);
354 }
355
356 template<class T>
GetObjectFromAsset(AlbumAsset * asset,shared_ptr<NativeRdb::AbsSharedResultSet> & resultSet)357 void FetchResult<T>::GetObjectFromAsset(AlbumAsset *asset, shared_ptr<NativeRdb::AbsSharedResultSet> &resultSet)
358 {
359 SetAlbumAsset(asset, resultSet);
360 }
361
362 template<class T>
GetObjectFromAsset(SmartAlbumAsset * asset,shared_ptr<NativeRdb::AbsSharedResultSet> & resultSet)363 void FetchResult<T>::GetObjectFromAsset(SmartAlbumAsset *asset, shared_ptr<NativeRdb::AbsSharedResultSet> &resultSet)
364 {
365 SetSmartAlbumAsset(asset, resultSet);
366 }
367
368 template<class T>
GetObject(shared_ptr<NativeRdb::AbsSharedResultSet> & resultSet)369 unique_ptr<T> FetchResult<T>::GetObject(shared_ptr<NativeRdb::AbsSharedResultSet> &resultSet)
370 {
371 MediaLibraryTracer tracer;
372 tracer.Start("FetchResult::GetObject");
373 unique_ptr<T> asset = make_unique<T>();
374 GetObjectFromAsset(asset.get(), resultSet);
375 return asset;
376 }
377
378 template <class T>
GetObject()379 unique_ptr<T> FetchResult<T>::GetObject()
380 {
381 shared_ptr<NativeRdb::AbsSharedResultSet> resultSet = nullptr;
382 return GetObject(resultSet);
383 }
384
385 template <class T>
GetObjectFromRdb(shared_ptr<NativeRdb::AbsSharedResultSet> & resultSet,int idx)386 unique_ptr<T> FetchResult<T>::GetObjectFromRdb(shared_ptr<NativeRdb::AbsSharedResultSet> &resultSet, int idx)
387 {
388 if ((resultSet == nullptr) || (resultSet->GoToFirstRow() != 0) || (resultSet->GoTo(idx))) {
389 MEDIA_ERR_LOG("resultset is null|first row failed");
390 return nullptr;
391 }
392
393 return GetObject(resultSet);
394 }
395
396 template<class T>
SetAlbumAsset(AlbumAsset * albumData,shared_ptr<NativeRdb::AbsSharedResultSet> & resultSet)397 void FetchResult<T>::SetAlbumAsset(AlbumAsset *albumData, shared_ptr<NativeRdb::AbsSharedResultSet> &resultSet)
398 {
399 // Get album id index and value
400 albumData->SetAlbumId(get<int32_t>(GetRowValFromColumn(MEDIA_DATA_DB_BUCKET_ID, TYPE_INT32, resultSet)));
401
402 // Get album title index and value
403 albumData->SetAlbumName(get<string>(GetRowValFromColumn(MEDIA_DATA_DB_TITLE, TYPE_STRING, resultSet)));
404
405 // Get album asset count index and value
406 albumData->SetCount(get<int32_t>(GetRowValFromColumn(MEDIA_DATA_DB_COUNT, TYPE_INT32, resultSet)));
407 albumData->SetAlbumUri(GetFileMediaTypeUri(MEDIA_TYPE_ALBUM, networkId_) + "/" +
408 to_string(albumData->GetAlbumId()));
409 // Get album relativePath index and value
410 albumData->SetAlbumRelativePath(get<string>(GetRowValFromColumn(MEDIA_DATA_DB_RELATIVE_PATH,
411 TYPE_STRING, resultSet)));
412 albumData->SetAlbumDateModified(get<int64_t>(GetRowValFromColumn(MEDIA_DATA_DB_DATE_MODIFIED,
413 TYPE_INT64, resultSet)));
414
415 albumData->SetResultNapiType(resultNapiType_);
416 albumData->SetAlbumTypeMask(typeMask_);
417 }
418
419 template<class T>
SetSmartAlbumAsset(SmartAlbumAsset * smartAlbumData,std::shared_ptr<NativeRdb::AbsSharedResultSet> & resultSet)420 void FetchResult<T>::SetSmartAlbumAsset(SmartAlbumAsset* smartAlbumData,
421 std::shared_ptr<NativeRdb::AbsSharedResultSet> &resultSet)
422 {
423 smartAlbumData->SetAlbumId(get<int32_t>(GetRowValFromColumn(SMARTALBUM_DB_ID, TYPE_INT32, resultSet)));
424 smartAlbumData->SetAlbumName(get<string>(GetRowValFromColumn(SMARTALBUM_DB_NAME, TYPE_STRING, resultSet)));
425 smartAlbumData->SetAlbumCapacity(get<int32_t>(GetRowValFromColumn(SMARTALBUM_DB_CAPACITY, TYPE_INT32, resultSet)));
426 smartAlbumData->SetResultNapiType(resultNapiType_);
427 smartAlbumData->SetTypeMask(typeMask_);
428 }
429
430 template class FetchResult<FileAsset>;
431 template class FetchResult<AlbumAsset>;
432 template class FetchResult<SmartAlbumAsset>;
433 } // namespace Media
434 } // namespace OHOS
435