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 #define MLOG_TAG "Scanner"
16
17 #include "media_scanner_db.h"
18
19 #include "abs_rdb_predicates.h"
20 #include "ipc_skeleton.h"
21 #include "medialibrary_asset_operations.h"
22 #include "media_column.h"
23 #include "media_file_utils.h"
24 #include "media_log.h"
25 #include "medialibrary_command.h"
26 #include "medialibrary_data_manager.h"
27 #include "medialibrary_db_const.h"
28 #include "medialibrary_errno.h"
29 #include "medialibrary_rdb_utils.h"
30 #include "medialibrary_smartalbum_map_operations.h"
31 #include "medialibrary_type_const.h"
32 #include "medialibrary_unistore_manager.h"
33 #include "rdb_errno.h"
34 #include "rdb_utils.h"
35 #include "result_set.h"
36 #include "result_set_utils.h"
37 #include "userfile_manager_types.h"
38 #include "userfilemgr_uri.h"
39 #include "values_bucket.h"
40 #include "post_event_utils.h"
41
42 namespace OHOS {
43 namespace Media {
44 using namespace std;
45 using namespace OHOS::NativeRdb;
46 using namespace OHOS::DataShare;
47
MediaScannerDb()48 MediaScannerDb::MediaScannerDb() {}
49
GetDatabaseInstance()50 unique_ptr<MediaScannerDb> MediaScannerDb::GetDatabaseInstance()
51 {
52 unique_ptr<MediaScannerDb> database = make_unique<MediaScannerDb>();
53 return database;
54 }
55
SetRdbHelper(void)56 void MediaScannerDb::SetRdbHelper(void)
57 {
58 }
59
60 #ifdef MEDIALIBRARY_COMPATIBILITY
SetVirtualPath(const Metadata & metadata,ValuesBucket & values)61 static inline void SetVirtualPath(const Metadata &metadata, ValuesBucket &values)
62 {
63 string relativePath = metadata.GetRelativePath();
64 string displayName = metadata.GetFileName();
65 string virtualPath = (relativePath.back() == '/' ? relativePath : relativePath + "/") + displayName;
66 values.PutString(MediaColumn::MEDIA_VIRTURL_PATH, virtualPath);
67 }
68 #endif
69
SetRemainFileMetadataApi9(const Metadata & metadata,ValuesBucket & values)70 static inline void SetRemainFileMetadataApi9(const Metadata &metadata, ValuesBucket &values)
71 {
72 values.PutString(MEDIA_DATA_DB_AUDIO_ALBUM, metadata.GetAlbum());
73 values.PutString(MEDIA_DATA_DB_ARTIST, metadata.GetFileArtist());
74 values.PutInt(MEDIA_DATA_DB_HEIGHT, metadata.GetFileHeight());
75 values.PutInt(MEDIA_DATA_DB_WIDTH, metadata.GetFileWidth());
76 values.PutInt(MEDIA_DATA_DB_ORIENTATION, metadata.GetOrientation());
77 values.PutString(MEDIA_DATA_DB_BUCKET_NAME, metadata.GetAlbumName());
78 values.PutInt(MEDIA_DATA_DB_PARENT_ID, metadata.GetParentId());
79 values.PutInt(MEDIA_DATA_DB_BUCKET_ID, metadata.GetParentId());
80 values.PutDouble(MEDIA_DATA_DB_LATITUDE, metadata.GetLatitude());
81 values.PutDouble(MEDIA_DATA_DB_LONGITUDE, metadata.GetLongitude());
82 }
83
SetValuesFromMetaDataAndType(const Metadata & metadata,ValuesBucket & values,MediaType mediaType,const string & tableName)84 static void SetValuesFromMetaDataAndType(const Metadata &metadata, ValuesBucket &values, MediaType mediaType,
85 const string &tableName)
86 {
87 #ifdef MEDIALIBRARY_COMPATIBILITY
88 if (mediaType == MediaType::MEDIA_TYPE_IMAGE || mediaType == MEDIA_TYPE_VIDEO) {
89 if (tableName == MEDIALIBRARY_TABLE) {
90 SetRemainFileMetadataApi9(metadata, values);
91 } else {
92 values.PutInt(MEDIA_DATA_DB_HEIGHT, metadata.GetFileHeight());
93 values.PutInt(MEDIA_DATA_DB_WIDTH, metadata.GetFileWidth());
94 values.PutInt(MEDIA_DATA_DB_ORIENTATION, metadata.GetOrientation());
95 values.PutDouble(MEDIA_DATA_DB_LATITUDE, metadata.GetLatitude());
96 values.PutDouble(MEDIA_DATA_DB_LONGITUDE, metadata.GetLongitude());
97 SetVirtualPath(metadata, values);
98 if (metadata.GetPhotoSubType() != 0) {
99 values.PutInt(PhotoColumn::PHOTO_SUBTYPE, metadata.GetPhotoSubType());
100 }
101 }
102 } else if (mediaType == MediaType::MEDIA_TYPE_AUDIO) {
103 if (tableName == MEDIALIBRARY_TABLE) {
104 SetRemainFileMetadataApi9(metadata, values);
105 } else {
106 values.PutString(MEDIA_DATA_DB_AUDIO_ALBUM, metadata.GetAlbum());
107 values.PutString(MEDIA_DATA_DB_ARTIST, metadata.GetFileArtist());
108 SetVirtualPath(metadata, values);
109 }
110 } else {
111 SetRemainFileMetadataApi9(metadata, values);
112 }
113 #else
114 SetRemainFileMetadataApi9(metadata, values);
115 #endif
116 }
117
SetDateDay(const int64_t dateAdded,ValuesBucket & outValues)118 static inline void SetDateDay(const int64_t dateAdded, ValuesBucket &outValues)
119 {
120 outValues.PutString(PhotoColumn::PHOTO_DATE_YEAR,
121 MediaFileUtils::StrCreateTimeByMilliseconds(PhotoColumn::PHOTO_DATE_YEAR_FORMAT, dateAdded));
122 outValues.PutString(PhotoColumn::PHOTO_DATE_MONTH,
123 MediaFileUtils::StrCreateTimeByMilliseconds(PhotoColumn::PHOTO_DATE_MONTH_FORMAT, dateAdded));
124 outValues.PutString(PhotoColumn::PHOTO_DATE_DAY,
125 MediaFileUtils::StrCreateTimeByMilliseconds(PhotoColumn::PHOTO_DATE_DAY_FORMAT, dateAdded));
126 }
127
SetDateAdded(const int64_t dateAdded,const Metadata & metadata,ValuesBucket & outValues)128 static inline void SetDateAdded(const int64_t dateAdded, const Metadata &metadata, ValuesBucket &outValues)
129 {
130 outValues.PutLong(MediaColumn::MEDIA_DATE_ADDED, dateAdded);
131 MediaType type = metadata.GetFileMediaType();
132 if ((type != MEDIA_TYPE_PHOTO) && (type != MEDIA_TYPE_IMAGE) && (type != MEDIA_TYPE_VIDEO)) {
133 return;
134 }
135 SetDateDay(dateAdded, outValues);
136 }
137
InsertDateAdded(const Metadata & metadata,ValuesBucket & outValues)138 static void InsertDateAdded(const Metadata &metadata, ValuesBucket &outValues)
139 {
140 int64_t dateAdded = metadata.GetFileDateAdded();
141 if (dateAdded == 0) {
142 int64_t dateTaken = metadata.GetDateTaken();
143 if (dateTaken == 0) {
144 int64_t dateModified = metadata.GetFileDateModified();
145 if (dateModified == 0) {
146 dateAdded = MediaFileUtils::UTCTimeMilliSeconds();
147 MEDIA_WARN_LOG("Invalid dateAdded time, use current time instead: %{public}lld",
148 static_cast<long long>(dateAdded));
149 } else {
150 dateAdded = dateModified;
151 MEDIA_WARN_LOG("Invalid dateAdded time, use dateModified instead: %{public}lld",
152 static_cast<long long>(dateAdded));
153 }
154 } else {
155 dateAdded = dateTaken * MSEC_TO_SEC;
156 MEDIA_WARN_LOG("Invalid dateAdded time, use dateTaken instead: %{public}lld",
157 static_cast<long long>(dateAdded));
158 }
159 }
160 SetDateAdded(dateAdded, metadata, outValues);
161 }
162
FixDateDayIfNeeded(const Metadata & metadata,ValuesBucket & outValues)163 static inline void FixDateDayIfNeeded(const Metadata &metadata, ValuesBucket &outValues)
164 {
165 MediaType type = metadata.GetFileMediaType();
166 if ((type != MEDIA_TYPE_PHOTO) && (type != MEDIA_TYPE_IMAGE) && (type != MEDIA_TYPE_VIDEO)) {
167 return;
168 }
169 int64_t dateAdded = metadata.GetFileDateAdded();
170 string dateDayOld = metadata.GetDateDay();
171 string dateDayNew = MediaFileUtils::StrCreateTimeByMilliseconds(PhotoColumn::PHOTO_DATE_DAY_FORMAT, dateAdded);
172 if (dateDayOld != dateDayNew) {
173 SetDateDay(dateAdded, outValues);
174 }
175 }
176
HandleDateAdded(const Metadata & metadata,const bool isInsert,ValuesBucket & outValues)177 static inline void HandleDateAdded(const Metadata &metadata, const bool isInsert, ValuesBucket &outValues)
178 {
179 if (isInsert) {
180 InsertDateAdded(metadata, outValues);
181 return;
182 }
183
184 FixDateDayIfNeeded(metadata, outValues);
185 }
186
SetValuesFromMetaDataApi9(const Metadata & metadata,ValuesBucket & values,bool isInsert,const string & table)187 static void SetValuesFromMetaDataApi9(const Metadata &metadata, ValuesBucket &values, bool isInsert,
188 const string &table)
189 {
190 MediaType mediaType = metadata.GetFileMediaType();
191 values.PutString(MEDIA_DATA_DB_FILE_PATH, metadata.GetFilePath());
192 values.PutString(MEDIA_DATA_DB_RELATIVE_PATH, metadata.GetRelativePath());
193 values.PutString(MEDIA_DATA_DB_MIME_TYPE, metadata.GetFileMimeType());
194 values.PutInt(MEDIA_DATA_DB_MEDIA_TYPE, mediaType);
195 values.PutString(MEDIA_DATA_DB_NAME, metadata.GetFileName());
196 values.PutString(MEDIA_DATA_DB_TITLE, metadata.GetFileTitle());
197 values.PutLong(MEDIA_DATA_DB_SIZE, metadata.GetFileSize());
198 values.PutLong(MEDIA_DATA_DB_DATE_MODIFIED, metadata.GetFileDateModified());
199 values.PutInt(MEDIA_DATA_DB_DURATION, metadata.GetFileDuration());
200 values.PutLong(MEDIA_DATA_DB_DATE_TAKEN, metadata.GetDateTaken());
201 values.PutLong(MEDIA_DATA_DB_TIME_PENDING, 0);
202
203 SetValuesFromMetaDataAndType(metadata, values, mediaType, table);
204 HandleDateAdded(metadata, isInsert, values);
205 }
206
SetValuesFromMetaDataApi10(const Metadata & metadata,ValuesBucket & values,bool isInsert,bool skipPhoto=true)207 static void SetValuesFromMetaDataApi10(const Metadata &metadata, ValuesBucket &values, bool isInsert,
208 bool skipPhoto = true)
209 {
210 MediaType mediaType = metadata.GetFileMediaType();
211
212 values.PutString(MediaColumn::MEDIA_FILE_PATH, metadata.GetFilePath());
213 values.PutString(MediaColumn::MEDIA_MIME_TYPE, metadata.GetFileMimeType());
214 values.PutInt(MediaColumn::MEDIA_TYPE, mediaType);
215 if (skipPhoto) {
216 values.PutString(MediaColumn::MEDIA_NAME, metadata.GetFileName());
217 }
218 values.PutString(MediaColumn::MEDIA_TITLE, metadata.GetFileTitle());
219
220 values.PutLong(MediaColumn::MEDIA_SIZE, metadata.GetFileSize());
221 values.PutLong(MediaColumn::MEDIA_DATE_MODIFIED, metadata.GetFileDateModified());
222 values.PutInt(MediaColumn::MEDIA_DURATION, metadata.GetFileDuration());
223 values.PutLong(MediaColumn::MEDIA_DATE_TAKEN, metadata.GetDateTaken());
224 values.PutLong(MediaColumn::MEDIA_TIME_PENDING, 0);
225
226 if (mediaType == MediaType::MEDIA_TYPE_IMAGE || mediaType == MEDIA_TYPE_VIDEO) {
227 values.PutInt(PhotoColumn::PHOTO_HEIGHT, metadata.GetFileHeight());
228 values.PutInt(PhotoColumn::PHOTO_WIDTH, metadata.GetFileWidth());
229 values.PutInt(PhotoColumn::PHOTO_ORIENTATION, metadata.GetOrientation());
230 values.PutDouble(PhotoColumn::PHOTO_LONGITUDE, metadata.GetLongitude());
231 values.PutDouble(PhotoColumn::PHOTO_LATITUDE, metadata.GetLatitude());
232 if (skipPhoto) {
233 values.PutString(PhotoColumn::PHOTO_USER_COMMENT, metadata.GetUserComment());
234 }
235 values.PutString(PhotoColumn::PHOTO_ALL_EXIF, metadata.GetAllExif());
236 values.PutString(PhotoColumn::PHOTO_SHOOTING_MODE, metadata.GetShootingMode());
237 values.PutString(PhotoColumn::PHOTO_SHOOTING_MODE_TAG, metadata.GetShootingModeTag());
238 values.PutLong(PhotoColumn::PHOTO_LAST_VISIT_TIME, metadata.GetLastVisitTime());
239
240 #ifdef MEDIALIBRARY_COMPATIBILITY
241 if (metadata.GetPhotoSubType() != 0) {
242 values.PutInt(PhotoColumn::PHOTO_SUBTYPE, metadata.GetPhotoSubType());
243 }
244 #endif
245 } else if (mediaType == MediaType::MEDIA_TYPE_AUDIO) {
246 values.PutString(AudioColumn::AUDIO_ALBUM, metadata.GetAlbum());
247 values.PutString(AudioColumn::AUDIO_ARTIST, metadata.GetFileArtist());
248 }
249
250 HandleDateAdded(metadata, isInsert, values);
251 }
252
GetTableNameByPath(int32_t mediaType,string & tableName,const string & path="")253 static void GetTableNameByPath(int32_t mediaType, string &tableName, const string &path = "")
254 {
255 if (!path.empty() && MediaFileUtils::IsFileTablePath(path)) {
256 tableName = MEDIALIBRARY_TABLE;
257 return;
258 }
259 switch (mediaType) {
260 case MediaType::MEDIA_TYPE_IMAGE:
261 case MediaType::MEDIA_TYPE_VIDEO: {
262 tableName = PhotoColumn::PHOTOS_TABLE;
263 break;
264 }
265 case MediaType::MEDIA_TYPE_AUDIO: {
266 tableName = AudioColumn::AUDIOS_TABLE;
267 break;
268 }
269 default: {
270 tableName = MEDIALIBRARY_TABLE;
271 break;
272 }
273 }
274 }
275
InsertData(const ValuesBucket values,const string & tableName,int64_t & rowNum)276 bool MediaScannerDb::InsertData(const ValuesBucket values, const string &tableName, int64_t &rowNum)
277 {
278 auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStoreRaw();
279 if (rdbStore == nullptr) {
280 MEDIA_ERR_LOG("MediaDataAbility Insert functionality rdbStore is null");
281 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_HAS_DB_ERROR},
282 {KEY_OPT_TYPE, OptType::SCAN}};
283 PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
284 return false;
285 }
286 auto rdbStorePtr = rdbStore->GetRaw();
287 if (rdbStorePtr == nullptr) {
288 MEDIA_ERR_LOG("MediaDataAbility Insert functionality rdbStorePtr is null");
289 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_HAS_DB_ERROR},
290 {KEY_OPT_TYPE, OptType::SCAN}};
291 PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
292 return false;
293 }
294
295 int32_t result = rdbStorePtr->Insert(rowNum, tableName, values);
296 if (rowNum <= 0) {
297 MEDIA_ERR_LOG("MediaDataAbility Insert functionality is failed, rowNum %{public}ld", (long)rowNum);
298 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__},
299 {KEY_ERR_CODE, static_cast<int32_t>(rowNum)}, {KEY_OPT_TYPE, OptType::SCAN}};
300 PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
301 return false;
302 }
303
304 if (result != NativeRdb::E_OK) {
305 MEDIA_ERR_LOG("MediaDataAbility Insert functionality is failed, return %{public}d", result);
306 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, result},
307 {KEY_OPT_TYPE, OptType::SCAN}};
308 PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
309 return false;
310 }
311
312 return true;
313 }
314
InsertMetadata(const Metadata & metadata,string & tableName,MediaLibraryApi api)315 string MediaScannerDb::InsertMetadata(const Metadata &metadata, string &tableName, MediaLibraryApi api)
316 {
317 MediaType mediaType = metadata.GetFileMediaType();
318 string mediaTypeUri;
319 ValuesBucket values;
320 if (api == MediaLibraryApi::API_10) {
321 mediaTypeUri = MediaFileUtils::GetMediaTypeUriV10(mediaType);
322 } else {
323 mediaTypeUri = MediaFileUtils::GetMediaTypeUri(mediaType);
324 #ifdef MEDIALIBRARY_COMPATIBILITY
325 if ((mediaType != MediaType::MEDIA_TYPE_IMAGE) && (mediaType != MediaType::MEDIA_TYPE_VIDEO) &&
326 (mediaType != MediaType::MEDIA_TYPE_AUDIO)) {
327 values.PutString(MEDIA_DATA_DB_URI, mediaTypeUri);
328 }
329 #else
330 values.PutString(MEDIA_DATA_DB_URI, mediaTypeUri);
331 #endif
332 }
333
334 tableName = MEDIALIBRARY_TABLE;
335 if (api == MediaLibraryApi::API_10) {
336 SetValuesFromMetaDataApi10(metadata, values, true);
337 GetTableNameByPath(mediaType, tableName);
338 } else {
339 #ifdef MEDIALIBRARY_COMPATIBILITY
340 GetTableNameByPath(mediaType, tableName, metadata.GetFilePath());
341 #endif
342 SetValuesFromMetaDataApi9(metadata, values, true, tableName);
343 }
344
345 int64_t rowNum = 0;
346 if (!InsertData(values, tableName, rowNum)) {
347 return "";
348 }
349
350 if (mediaTypeUri.empty()) {
351 return "";
352 }
353 if (api == MediaLibraryApi::API_10) {
354 return MediaFileUtils::GetUriByExtrConditions(mediaTypeUri + "/", to_string(rowNum),
355 MediaFileUtils::GetExtraUri(metadata.GetFileName(), metadata.GetFilePath())) + "?api_version=10";
356 }
357 return MediaFileUtils::GetUriByExtrConditions(mediaTypeUri + "/", to_string(rowNum));
358 }
359
GetUriStringInUpdate(MediaType mediaType,MediaLibraryApi api,string & mediaTypeUri,ValuesBucket & values)360 static inline void GetUriStringInUpdate(MediaType mediaType, MediaLibraryApi api, string &mediaTypeUri,
361 ValuesBucket &values)
362 {
363 if (api == MediaLibraryApi::API_10) {
364 mediaTypeUri = MediaFileUtils::GetMediaTypeUriV10(mediaType);
365 } else {
366 mediaTypeUri = MediaFileUtils::GetMediaTypeUri(mediaType);
367 #ifdef MEDIALIBRARY_COMPATIBILITY
368 if ((mediaType != MediaType::MEDIA_TYPE_IMAGE) && (mediaType != MediaType::MEDIA_TYPE_VIDEO) &&
369 (mediaType != MediaType::MEDIA_TYPE_AUDIO)) {
370 values.PutString(MEDIA_DATA_DB_URI, mediaTypeUri);
371 }
372 #else
373 values.PutString(MEDIA_DATA_DB_URI, mediaTypeUri);
374 #endif
375 }
376 }
377
378 /**
379 * @brief Update single metadata in the media database
380 *
381 * @param metadata The metadata object which has the information about the file
382 * @return string The mediatypeUri corresponding to the given metadata
383 */
UpdateMetadata(const Metadata & metadata,string & tableName,MediaLibraryApi api,bool skipPhoto)384 string MediaScannerDb::UpdateMetadata(const Metadata &metadata, string &tableName, MediaLibraryApi api, bool skipPhoto)
385 {
386 int32_t updateCount(0);
387 ValuesBucket values;
388 string whereClause = MEDIA_DATA_DB_ID + " = ?";
389 vector<string> whereArgs = { to_string(metadata.GetFileId()) };
390 MediaType mediaType = metadata.GetFileMediaType();
391 string mediaTypeUri;
392 GetUriStringInUpdate(mediaType, api, mediaTypeUri, values);
393
394 tableName = MEDIALIBRARY_TABLE;
395 if (api == MediaLibraryApi::API_10) {
396 SetValuesFromMetaDataApi10(metadata, values, false, skipPhoto);
397 GetTableNameByPath(mediaType, tableName);
398 } else {
399 #ifdef MEDIALIBRARY_COMPATIBILITY
400 GetTableNameByPath(mediaType, tableName, metadata.GetFilePath());
401 #endif
402 SetValuesFromMetaDataApi9(metadata, values, false, tableName);
403 }
404
405 auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStoreRaw();
406 if (rdbStore == nullptr) {
407 return "";
408 }
409 auto rdbStorePtr = rdbStore->GetRaw();
410 if (rdbStorePtr == nullptr) {
411 return "";
412 }
413 int32_t result = rdbStorePtr->Update(updateCount, tableName, values, whereClause, whereArgs);
414 if (result != NativeRdb::E_OK || updateCount <= 0) {
415 MEDIA_ERR_LOG("Update operation failed. Result %{public}d. Updated %{public}d", result, updateCount);
416 if (result != NativeRdb::E_OK) {
417 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, result},
418 {KEY_OPT_TYPE, OptType::SCAN}};
419 PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
420 }
421 if (updateCount <= 0) {
422 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, updateCount},
423 {KEY_OPT_TYPE, OptType::SCAN}};
424 PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
425 }
426 return "";
427 }
428 if (mediaTypeUri.empty()) {
429 return "";
430 }
431 if (api == MediaLibraryApi::API_10) {
432 return MakeFileUri(mediaTypeUri, metadata);
433 }
434 return MediaFileUtils::GetUriByExtrConditions(mediaTypeUri + "/", to_string(metadata.GetFileId()));
435 }
436
437 /**
438 * @brief Deletes particular entry in database based on row id
439 *
440 * @param idList The list of IDs to be deleted from the media db
441 * @return bool Status of the delete operation
442 */
DeleteMetadata(const vector<string> & idList,const string & tableName)443 bool MediaScannerDb::DeleteMetadata(const vector<string> &idList, const string &tableName)
444 {
445 if (idList.size() == 0) {
446 MEDIA_ERR_LOG("to-deleted idList size equals to 0");
447 return false;
448 }
449
450 auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStoreRaw();
451 if (rdbStore == nullptr) {
452 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_HAS_DB_ERROR},
453 {KEY_OPT_TYPE, OptType::SCAN}};
454 PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
455 MEDIA_ERR_LOG("rdbStore is nullptr");
456 return E_ERR;
457 }
458
459 NativeRdb::RdbPredicates rdbPredicate(tableName);
460 rdbPredicate.In(MEDIA_DATA_DB_ID, idList);
461 int32_t ret = rdbStore->Delete(rdbPredicate);
462 return ret == static_cast<int32_t>(idList.size());
463 }
464
GetOprnObjectFromPath(const string & path)465 static OperationObject GetOprnObjectFromPath(const string &path)
466 {
467 const map<string, OperationObject> oprnMap = {
468 { ROOT_MEDIA_DIR + PHOTO_BUCKET, OperationObject::FILESYSTEM_PHOTO },
469 { ROOT_MEDIA_DIR + AUDIO_BUCKET, OperationObject::FILESYSTEM_AUDIO },
470 #ifdef MEDIALIBRARY_COMPATIBILITY
471 { ROOT_MEDIA_DIR + PIC_DIR_VALUES, OperationObject::FILESYSTEM_PHOTO },
472 { ROOT_MEDIA_DIR + AUDIO_DIR_VALUES, OperationObject::FILESYSTEM_AUDIO },
473 { ROOT_MEDIA_DIR + VIDEO_DIR_VALUES, OperationObject::FILESYSTEM_PHOTO },
474 { ROOT_MEDIA_DIR + CAMERA_DIR_VALUES, OperationObject::FILESYSTEM_PHOTO }
475 #endif
476 };
477
478 for (const auto &iter : oprnMap) {
479 if (path.find(iter.first) != string::npos) {
480 return iter.second;
481 }
482 }
483 return OperationObject::FILESYSTEM_ASSET;
484 }
485
GetQueryParamsByPath(const string & path,MediaLibraryApi api,vector<string> & columns,OperationObject & oprnObject,string & whereClause)486 static void GetQueryParamsByPath(const string &path, MediaLibraryApi api, vector<string> &columns,
487 OperationObject &oprnObject, string &whereClause)
488 {
489 oprnObject = GetOprnObjectFromPath(path);
490 if (api == MediaLibraryApi::API_10) {
491 whereClause = MediaColumn::MEDIA_FILE_PATH + " = ?";
492 if (oprnObject == OperationObject::FILESYSTEM_PHOTO) {
493 columns = {
494 MediaColumn::MEDIA_ID, MediaColumn::MEDIA_SIZE, MediaColumn::MEDIA_DATE_MODIFIED,
495 MediaColumn::MEDIA_NAME, PhotoColumn::PHOTO_ORIENTATION, MediaColumn::MEDIA_TIME_PENDING,
496 MediaColumn::MEDIA_DATE_ADDED, PhotoColumn::PHOTO_DATE_DAY
497 };
498 } else if (oprnObject == OperationObject::FILESYSTEM_AUDIO) {
499 columns = {
500 MediaColumn::MEDIA_ID, MediaColumn::MEDIA_SIZE, MediaColumn::MEDIA_DATE_MODIFIED,
501 MediaColumn::MEDIA_NAME, MediaColumn::MEDIA_TIME_PENDING
502 };
503 }
504 } else {
505 if (oprnObject == OperationObject::FILESYSTEM_PHOTO) {
506 whereClause = MediaColumn::MEDIA_FILE_PATH + " = ?";
507 columns = {
508 MediaColumn::MEDIA_ID, MediaColumn::MEDIA_SIZE, MediaColumn::MEDIA_DATE_MODIFIED,
509 MediaColumn::MEDIA_NAME, PhotoColumn::PHOTO_ORIENTATION, MediaColumn::MEDIA_TIME_PENDING,
510 MediaColumn::MEDIA_DATE_ADDED, PhotoColumn::PHOTO_DATE_DAY
511 };
512 } else if (oprnObject == OperationObject::FILESYSTEM_AUDIO) {
513 whereClause = MediaColumn::MEDIA_FILE_PATH + " = ?";
514 columns = {
515 MediaColumn::MEDIA_ID, MediaColumn::MEDIA_SIZE, MediaColumn::MEDIA_DATE_MODIFIED,
516 MediaColumn::MEDIA_NAME, MediaColumn::MEDIA_TIME_PENDING
517 };
518 } else {
519 whereClause = MEDIA_DATA_DB_FILE_PATH + " = ? And " + MEDIA_DATA_DB_IS_TRASH + " = ? ";
520 columns = {
521 MEDIA_DATA_DB_ID, MEDIA_DATA_DB_SIZE, MEDIA_DATA_DB_DATE_MODIFIED,
522 MEDIA_DATA_DB_NAME, MEDIA_DATA_DB_ORIENTATION, MEDIA_DATA_DB_RECYCLE_PATH
523 };
524 }
525 }
526 }
527
GetFileSet(MediaLibraryCommand & cmd,const vector<string> & columns,shared_ptr<NativeRdb::ResultSet> & resultSet)528 int32_t MediaScannerDb::GetFileSet(MediaLibraryCommand &cmd, const vector<string> &columns,
529 shared_ptr<NativeRdb::ResultSet> &resultSet)
530 {
531 auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStoreRaw();
532 if (rdbStore == nullptr) {
533 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_RDB},
534 {KEY_OPT_TYPE, OptType::SCAN}};
535 PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
536 return E_RDB;
537 }
538 resultSet = rdbStore->Query(cmd, columns);
539 if (resultSet == nullptr) {
540 MEDIA_ERR_LOG("return nullptr when query rdb");
541 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_RDB},
542 {KEY_OPT_TYPE, OptType::SCAN}};
543 PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
544 return E_RDB;
545 }
546
547 int32_t rowCount = 0;
548 int32_t ret = resultSet->GetRowCount(rowCount);
549 if (ret != NativeRdb::E_OK) {
550 MEDIA_ERR_LOG("failed to get row count");
551 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, ret},
552 {KEY_OPT_TYPE, OptType::SCAN}};
553 PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
554 return E_RDB;
555 }
556
557 if (rowCount == 0) {
558 return E_OK;
559 }
560
561 ret = resultSet->GoToFirstRow();
562 if (ret != NativeRdb::E_OK) {
563 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, ret},
564 {KEY_OPT_TYPE, OptType::SCAN}};
565 PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
566 MEDIA_ERR_LOG("failed to go to first row");
567 return E_RDB;
568 }
569 return E_OK;
570 }
571
572 /**
573 * @brief Get date modified, id, size and name info for a file
574 *
575 * @param path The file path for which to obtain the latest modification info from the db
576 * @return unique_ptr<Metadata> The metadata object representing the latest info for the given filepath
577 */
GetFileBasicInfo(const string & path,unique_ptr<Metadata> & ptr,MediaLibraryApi api)578 int32_t MediaScannerDb::GetFileBasicInfo(const string &path, unique_ptr<Metadata> &ptr, MediaLibraryApi api)
579 {
580 vector<string> columns;
581 string whereClause;
582 OperationObject oprnObject = OperationObject::FILESYSTEM_ASSET;
583 GetQueryParamsByPath(path, api, columns, oprnObject, whereClause);
584
585 vector<string> args;
586 if (oprnObject == OperationObject::FILESYSTEM_PHOTO || oprnObject == OperationObject::FILESYSTEM_AUDIO) {
587 args = { path };
588 } else {
589 args = { path, to_string(NOT_TRASHED) };
590 }
591
592 MediaLibraryCommand cmd(oprnObject, OperationType::QUERY, api);
593 cmd.GetAbsRdbPredicates()->SetWhereClause(whereClause);
594 cmd.GetAbsRdbPredicates()->SetWhereArgs(args);
595
596 shared_ptr<NativeRdb::ResultSet> resultSet;
597 int32_t ret = GetFileSet(cmd, columns, resultSet);
598 if (ret != E_OK) {
599 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, ret},
600 {KEY_OPT_TYPE, OptType::SCAN}};
601 PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
602 return ret;
603 }
604 ptr->SetTableName(cmd.GetTableName());
605
606 return FillMetadata(resultSet, ptr);
607 }
608
PreparePredicatesAndColumns(const string & path,const string & tableName,const string & whitePath,AbsRdbPredicates & predicates,vector<string> & columns)609 static void PreparePredicatesAndColumns(const string &path, const string &tableName, const string &whitePath,
610 AbsRdbPredicates &predicates, vector<string> &columns)
611 {
612 string querySql;
613 vector<string> args;
614 if (whitePath.empty()) {
615 if (tableName == MEDIALIBRARY_TABLE) {
616 querySql = MEDIA_DATA_DB_FILE_PATH + " LIKE ? AND " + MEDIA_DATA_DB_IS_TRASH + " = ? ";
617 args = { path.back() != '/' ? path + "/%" : path + "%", to_string(NOT_TRASHED) };
618 columns = { MEDIA_DATA_DB_ID, MEDIA_DATA_DB_MEDIA_TYPE, MEDIA_DATA_DB_RECYCLE_PATH };
619 } else {
620 querySql = MEDIA_DATA_DB_FILE_PATH + " LIKE ? AND " + MediaColumn::MEDIA_TIME_PENDING + " <> ? ";
621 args= { path.back() != '/' ? path + "/%" : path + "%", to_string(UNCREATE_FILE_TIMEPENDING) };
622 columns = { MEDIA_DATA_DB_ID, MEDIA_DATA_DB_MEDIA_TYPE };
623 }
624 } else {
625 if (tableName == MEDIALIBRARY_TABLE) {
626 querySql = MEDIA_DATA_DB_FILE_PATH + " LIKE ? AND " + MEDIA_DATA_DB_FILE_PATH + " NOT LIKE ? AND " +
627 MEDIA_DATA_DB_IS_TRASH + " = ? ";
628 args = { path.back() != '/' ? path + "/%" : path + "%",
629 whitePath.back() != '/' ? whitePath + "/%" : whitePath + "%", to_string(NOT_TRASHED) };
630 columns = { MEDIA_DATA_DB_ID, MEDIA_DATA_DB_MEDIA_TYPE, MEDIA_DATA_DB_RECYCLE_PATH };
631 } else {
632 querySql = MEDIA_DATA_DB_FILE_PATH + " LIKE ? AND " + MEDIA_DATA_DB_FILE_PATH + " NOT LIKE ? AND " +
633 MediaColumn::MEDIA_TIME_PENDING + " <> ? ";
634 args= { path.back() != '/' ? path + "/%" : path + "%",
635 whitePath.back() != '/' ? whitePath + "/%" : whitePath + "%", to_string(UNCREATE_FILE_TIMEPENDING) };
636 columns = { MEDIA_DATA_DB_ID, MEDIA_DATA_DB_MEDIA_TYPE };
637 }
638 }
639
640 predicates.SetWhereClause(querySql);
641 predicates.SetWhereArgs(args);
642 }
643
644 /**
645 * @brief Get the list of all IDs corresponding to given path
646 *
647 * @param path The path from which to obtain the list of child IDs
648 * @return unordered_map<int32_t, MediaType> The list of IDS along with mediaType information
649 */
GetIdsFromFilePath(const string & path,const string & tableName,const string & whitePath)650 unordered_map<int32_t, MediaType> MediaScannerDb::GetIdsFromFilePath(const string &path, const string &tableName,
651 const string &whitePath)
652 {
653 unordered_map<int32_t, MediaType> idMap = {};
654 AbsRdbPredicates predicates(tableName);
655 vector<string> columns;
656 PreparePredicatesAndColumns(path, tableName, whitePath, predicates, columns);
657
658 auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStoreRaw();
659 if (rdbStore == nullptr) {
660 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_HAS_DB_ERROR},
661 {KEY_OPT_TYPE, OptType::SCAN}};
662 PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
663 return idMap;
664 }
665 auto rdbStorePtr = rdbStore->GetRaw();
666 if (rdbStorePtr == nullptr) {
667 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_HAS_DB_ERROR},
668 {KEY_OPT_TYPE, OptType::SCAN}};
669 PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
670 return idMap;
671 }
672 auto resultSet = rdbStorePtr->Query(predicates, columns);
673 if (resultSet == nullptr) {
674 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_HAS_DB_ERROR},
675 {KEY_OPT_TYPE, OptType::SCAN}};
676 PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
677 return idMap;
678 }
679
680 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
681 if (tableName == MEDIALIBRARY_TABLE) {
682 string recyclePath = GetStringVal(MEDIA_DATA_DB_RECYCLE_PATH, resultSet);
683 if (!recyclePath.empty()) {
684 continue;
685 }
686 }
687 int32_t id = GetInt32Val(MEDIA_DATA_DB_ID, resultSet);
688 int32_t mediaType = GetInt32Val(MEDIA_DATA_DB_MEDIA_TYPE, resultSet);
689 idMap.emplace(make_pair(id, static_cast<MediaType>(mediaType)));
690 }
691 return idMap;
692 }
693
GetFileDBUriFromPath(const string & path)694 string MediaScannerDb::GetFileDBUriFromPath(const string &path)
695 {
696 string uri;
697
698 vector<string> columns = {};
699 columns.push_back(MEDIA_DATA_DB_URI);
700
701 DataShare::DataSharePredicates predicates;
702 predicates.SetWhereClause(MEDIA_DATA_DB_FILE_PATH + " = ? AND " + MEDIA_DATA_DB_IS_TRASH + " = ?");
703 vector<string> args = { path, to_string(NOT_TRASHED) };
704 predicates.SetWhereArgs(args);
705
706 Uri queryUri(MEDIALIBRARY_DATA_URI);
707 MediaLibraryCommand cmd(queryUri, OperationType::QUERY);
708 int errCode = 0;
709 auto resultSet = MediaLibraryDataManager::GetInstance()->QueryRdb(cmd, columns, predicates, errCode);
710 if (resultSet == nullptr) {
711 MEDIA_ERR_LOG("No result found for this path");
712 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_HAS_DB_ERROR},
713 {KEY_OPT_TYPE, OptType::SCAN}};
714 PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
715 return uri;
716 }
717 auto ret = resultSet->GoToFirstRow();
718 if (ret != NativeRdb::E_OK) {
719 MEDIA_ERR_LOG("Get data error for this path");
720 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, ret},
721 {KEY_OPT_TYPE, OptType::SCAN}};
722 PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
723 return uri;
724 }
725
726 int32_t intValue(0);
727 int32_t columnIndex(0);
728 resultSet->GetColumnIndex(MEDIA_DATA_DB_ID, columnIndex);
729 resultSet->GetInt(columnIndex, intValue);
730 uri = MEDIALIBRARY_DATA_URI + "/" + to_string(intValue);
731 return uri;
732 }
733
GetIdFromPath(const string & path)734 int32_t MediaScannerDb::GetIdFromPath(const string &path)
735 {
736 int32_t id = UNKNOWN_ID;
737 int32_t columnIndex = -1;
738
739 DataShare::DataSharePredicates predicates;
740 predicates.SetWhereClause(MEDIA_DATA_DB_FILE_PATH + " = ? AND " + MEDIA_DATA_DB_IS_TRASH + " = ?");
741 vector<string> args = { path, to_string(NOT_TRASHED) };
742 predicates.SetWhereArgs(args);
743
744 Uri uri(MEDIALIBRARY_DATA_URI);
745 MediaLibraryCommand cmd(uri, OperationType::QUERY);
746 vector<string> columns = {MEDIA_DATA_DB_ID};
747 int errCode = 0;
748 auto resultSet = MediaLibraryDataManager::GetInstance()->QueryRdb(cmd, columns, predicates, errCode);
749 if (resultSet == nullptr) {
750 MEDIA_ERR_LOG("No data found for the given path %{private}s", path.c_str());
751 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_HAS_DB_ERROR},
752 {KEY_OPT_TYPE, OptType::SCAN}};
753 PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
754 return id;
755 }
756 auto ret = resultSet->GoToFirstRow();
757 if (ret != NativeRdb::E_OK) {
758 MEDIA_ERR_LOG("Get data for the given path %{private}s error", path.c_str());
759 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, ret},
760 {KEY_OPT_TYPE, OptType::SCAN}};
761 PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
762 return id;
763 }
764
765 resultSet->GetColumnIndex(MEDIA_DATA_DB_ID, columnIndex);
766 resultSet->GetInt(columnIndex, id);
767
768 return id;
769 }
770
ReadAlbums(const string & path,unordered_map<string,Metadata> & albumMap)771 int32_t MediaScannerDb::ReadAlbums(const string &path, unordered_map<string, Metadata> &albumMap)
772 {
773 if ((path + "/").find(ROOT_MEDIA_DIR) != 0) {
774 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_INVALID_ARGUMENTS},
775 {KEY_OPT_TYPE, OptType::SCAN}};
776 PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
777 return E_INVALID_ARGUMENTS;
778 }
779
780 AbsRdbPredicates predicates(MEDIALIBRARY_TABLE);
781 string queryCmd = MEDIA_DATA_DB_MEDIA_TYPE + " = ? AND " + MEDIA_DATA_DB_FILE_PATH + " like ? AND " +
782 MEDIA_DATA_DB_IS_TRASH + " = ?";
783 string queryPath = path.back() != '/' ? path + "/%" : path + "%";
784 vector<string> args = { to_string(MediaType::MEDIA_TYPE_ALBUM), queryPath, to_string(NOT_TRASHED) };
785 predicates.SetWhereClause(queryCmd);
786 predicates.SetWhereArgs(args);
787 vector<string> columns = {MEDIA_DATA_DB_ID, MEDIA_DATA_DB_FILE_PATH, MEDIA_DATA_DB_DATE_MODIFIED};
788
789 auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStoreRaw();
790 if (rdbStore == nullptr) {
791 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_HAS_DB_ERROR},
792 {KEY_OPT_TYPE, OptType::SCAN}};
793 PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
794 return E_HAS_DB_ERROR;
795 }
796 auto rdbStorePtr = rdbStore->GetRaw();
797 if (rdbStorePtr == nullptr) {
798 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_HAS_DB_ERROR},
799 {KEY_OPT_TYPE, OptType::SCAN}};
800 PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
801 return E_HAS_DB_ERROR;
802 }
803 auto resultSet = rdbStorePtr->Query(predicates, columns);
804 if (resultSet == nullptr) {
805 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_HAS_DB_ERROR},
806 {KEY_OPT_TYPE, OptType::SCAN}};
807 PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
808 return E_HAS_DB_ERROR;
809 }
810
811 albumMap.clear();
812 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
813 Metadata metadata;
814 int32_t intValue = GetInt32Val(MEDIA_DATA_DB_ID, resultSet);
815 metadata.SetFileId(intValue);
816 string strValue = GetStringVal(MEDIA_DATA_DB_FILE_PATH, resultSet);
817 metadata.SetFilePath(strValue);
818 int64_t dateModified = GetInt64Val(MEDIA_DATA_DB_DATE_MODIFIED, resultSet);
819 metadata.SetFileDateModified(dateModified);
820 albumMap.insert(make_pair(strValue, metadata));
821 }
822
823 return E_OK;
824 }
825
InsertAlbum(const Metadata & metadata)826 int32_t MediaScannerDb::InsertAlbum(const Metadata &metadata)
827 {
828 int32_t id = 0;
829
830 string tableName;
831 string uri = InsertMetadata(metadata, tableName);
832 id = stoi(MediaFileUtils::GetIdFromUri(uri));
833
834 return id;
835 }
836
UpdateAlbum(const Metadata & metadata)837 int32_t MediaScannerDb::UpdateAlbum(const Metadata &metadata)
838 {
839 int32_t id = 0;
840
841 string tableName;
842 string uri = UpdateMetadata(metadata, tableName);
843 id = stoi(MediaFileUtils::GetIdFromUri(uri));
844
845 return id;
846 }
847
NotifyDatabaseChange(const MediaType mediaType)848 void MediaScannerDb::NotifyDatabaseChange(const MediaType mediaType)
849 {
850 string notifyUri = MediaFileUtils::GetMediaTypeUri(mediaType);
851 Uri uri(notifyUri);
852
853 MediaLibraryDataManager::GetInstance()->NotifyChange(uri);
854 }
855
ExtractMetaFromColumn(const shared_ptr<NativeRdb::ResultSet> & resultSet,unique_ptr<Metadata> & metadata,const std::string & col)856 void MediaScannerDb::ExtractMetaFromColumn(const shared_ptr<NativeRdb::ResultSet> &resultSet,
857 unique_ptr<Metadata> &metadata, const std::string &col)
858 {
859 ResultSetDataType dataType = ResultSetDataType::TYPE_NULL;
860 Metadata::MetadataFnPtr requestFunc = nullptr;
861 auto itr = metadata->memberFuncMap_.find(col);
862 if (itr != metadata->memberFuncMap_.end()) {
863 dataType = itr->second.first;
864 requestFunc = itr->second.second;
865 } else {
866 MEDIA_ERR_LOG("invalid column name %{private}s", col.c_str());
867 return;
868 }
869
870 std::variant<int32_t, std::string, int64_t, double> data =
871 ResultSetUtils::GetValFromColumn<const shared_ptr<NativeRdb::ResultSet>>(col, resultSet, dataType);
872
873 // Use the function pointer from map and pass data to fn ptr
874 if (requestFunc != nullptr) {
875 (metadata.get()->*requestFunc)(data);
876 }
877 }
878
FillMetadata(const shared_ptr<NativeRdb::ResultSet> & resultSet,unique_ptr<Metadata> & ptr)879 int32_t MediaScannerDb::FillMetadata(const shared_ptr<NativeRdb::ResultSet> &resultSet,
880 unique_ptr<Metadata> &ptr)
881 {
882 std::vector<std::string> columnNames;
883 int32_t err = resultSet->GetAllColumnNames(columnNames);
884 if (err != NativeRdb::E_OK) {
885 MEDIA_ERR_LOG("failed to get all column names");
886 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, err},
887 {KEY_OPT_TYPE, OptType::SCAN}};
888 PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
889 return E_RDB;
890 }
891
892 for (const auto &col : columnNames) {
893 ExtractMetaFromColumn(resultSet, ptr, col);
894 }
895
896 return E_OK;
897 }
898
RecordError(const std::string & err)899 int32_t MediaScannerDb::RecordError(const std::string &err)
900 {
901 auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStoreRaw();
902 if (rdbStore == nullptr) {
903 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_HAS_DB_ERROR},
904 {KEY_OPT_TYPE, OptType::SCAN}};
905 PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
906 MEDIA_ERR_LOG("rdbStore is nullptr");
907 return E_ERR;
908 }
909
910 ValuesBucket valuesBucket;
911 valuesBucket.PutString(MEDIA_DATA_ERROR, err);
912 int64_t outRowId = -1;
913 auto rdbStorePtr = rdbStore->GetRaw();
914 if (rdbStorePtr == nullptr) {
915 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_HAS_DB_ERROR},
916 {KEY_OPT_TYPE, OptType::SCAN}};
917 PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
918 MEDIA_ERR_LOG("rdbStorePtr is nullptr");
919 return E_ERR;
920 }
921 int32_t ret = rdbStorePtr->Insert(outRowId, MEDIALIBRARY_ERROR_TABLE, valuesBucket);
922 if (ret) {
923 MEDIA_ERR_LOG("rdb insert err %{public}d", ret);
924 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, ret},
925 {KEY_OPT_TYPE, OptType::SCAN}};
926 PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
927 return E_ERR;
928 }
929
930 return E_OK;
931 }
932
ReadError()933 std::set<std::string> MediaScannerDb::ReadError()
934 {
935 auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStoreRaw();
936 if (rdbStore == nullptr) {
937 MEDIA_ERR_LOG("rdbStore is nullptr");
938 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_HAS_DB_ERROR},
939 {KEY_OPT_TYPE, OptType::SCAN}};
940 PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
941 return {};
942 }
943
944 AbsRdbPredicates predicates(MEDIALIBRARY_ERROR_TABLE);
945 vector<string> columns = { MEDIA_DATA_ERROR };
946 auto rdbStorePtr = rdbStore->GetRaw();
947 if (rdbStorePtr == nullptr) {
948 MEDIA_ERR_LOG("rdbStorePtr is nullptr");
949 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_HAS_DB_ERROR},
950 {KEY_OPT_TYPE, OptType::SCAN}};
951 PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
952 return {};
953 }
954 auto resultSet = rdbStorePtr->Query(predicates, columns);
955 if (resultSet == nullptr) {
956 MEDIA_ERR_LOG("rdb query return nullptr");
957 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_HAS_DB_ERROR},
958 {KEY_OPT_TYPE, OptType::SCAN}};
959 PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
960 return {};
961 }
962
963 int32_t rowCount = 0;
964 auto ret = resultSet->GetRowCount(rowCount);
965 if (ret != NativeRdb::E_OK) {
966 MEDIA_ERR_LOG("failed to get row count");
967 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, ret},
968 {KEY_OPT_TYPE, OptType::SCAN}};
969 PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
970 return {};
971 }
972
973 if (rowCount == 0) {
974 return {};
975 }
976
977 string str;
978 set<string> errSet;
979 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
980 resultSet->GetString(0, str);
981 errSet.insert(move(str));
982 }
983
984 return errSet;
985 }
986
DeleteError(const std::string & err)987 int32_t MediaScannerDb::DeleteError(const std::string &err)
988 {
989 auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStoreRaw();
990 if (rdbStore == nullptr) {
991 MEDIA_ERR_LOG("rdbStore is nullptr");
992 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_HAS_DB_ERROR},
993 {KEY_OPT_TYPE, OptType::SCAN}};
994 PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
995 return E_ERR;
996 }
997
998 int32_t outRowId = -1;
999 string whereClause = MEDIA_DATA_ERROR + " = ?";
1000 vector<string> whereArgs= { err };
1001 auto rdbStorePtr = rdbStore->GetRaw();
1002 if (rdbStorePtr == nullptr) {
1003 MEDIA_ERR_LOG("rdbStorePtr is nullptr");
1004 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_HAS_DB_ERROR},
1005 {KEY_OPT_TYPE, OptType::SCAN}};
1006 PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
1007 return E_ERR;
1008 }
1009 int32_t ret = rdbStorePtr->Delete(outRowId, MEDIALIBRARY_ERROR_TABLE, whereClause, whereArgs);
1010 if (ret) {
1011 MEDIA_ERR_LOG("rdb delete err %{public}d", ret);
1012 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, ret},
1013 {KEY_OPT_TYPE, OptType::SCAN}};
1014 PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
1015 return E_ERR;
1016 }
1017
1018 return E_OK;
1019 }
1020
UpdateAlbumInfo(const std::vector<std::string> & subtypes,const std::vector<std::string> & userAlbumIds,const std::vector<std::string> & sourceAlbumIds)1021 void MediaScannerDb::UpdateAlbumInfo(const std::vector<std::string> &subtypes,
1022 const std::vector<std::string> &userAlbumIds, const std::vector<std::string> &sourceAlbumIds)
1023 {
1024 MediaLibraryRdbUtils::UpdateSystemAlbumInternal(
1025 MediaLibraryUnistoreManager::GetInstance().GetRdbStoreRaw()->GetRaw(), {
1026 to_string(PhotoAlbumSubType::IMAGE),
1027 to_string(PhotoAlbumSubType::VIDEO),
1028 to_string(PhotoAlbumSubType::SCREENSHOT),
1029 to_string(PhotoAlbumSubType::FAVORITE),
1030 });
1031 MediaLibraryRdbUtils::UpdateSourceAlbumInternal(
1032 MediaLibraryUnistoreManager::GetInstance().GetRdbStoreRaw()->GetRaw(), sourceAlbumIds);
1033 }
1034
MakeFileUri(const std::string & mediaTypeUri,const Metadata & metadata)1035 std::string MediaScannerDb::MakeFileUri(const std::string &mediaTypeUri, const Metadata &metadata)
1036 {
1037 return MediaFileUtils::GetUriByExtrConditions(mediaTypeUri + "/", to_string(metadata.GetFileId()),
1038 MediaFileUtils::GetExtraUri(metadata.GetFileName(), metadata.GetFilePath())) + "?api_version=10" +
1039 "&date_added=" + to_string(metadata.GetFileDateAdded());
1040 }
1041 } // namespace Media
1042 } // namespace OHOS
1043