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