• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2025 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 "Thumbnail"
16 
17 #include "thumbnail_rdb_utils.h"
18 
19 #include "asset_accurate_refresh.h"
20 #include "medialibrary_errno.h"
21 #include "medialibrary_tracer.h"
22 #include "media_log.h"
23 
24 using namespace std;
25 using namespace OHOS::NativeRdb;
26 
27 namespace OHOS {
28 namespace Media {
29 
30 using HandleFunc = void(*)(const std::shared_ptr<NativeRdb::ResultSet> &resultSet, int idx, ThumbnailData &data);
31 const std::unordered_map<std::string, HandleFunc> ThumbnailRdbUtils::RESULT_SET_HANDLER = {
32     {MEDIA_DATA_DB_ID, HandleId},
33     {MEDIA_DATA_DB_FILE_PATH, HandleFilePath},
34     {MEDIA_DATA_DB_DATE_ADDED, HandleDateAdded},
35     {MEDIA_DATA_DB_NAME, HandleDisplayName},
36     {MEDIA_DATA_DB_MEDIA_TYPE, HandleMediaType},
37     {MEDIA_DATA_DB_DATE_TAKEN, HandleDateTaken},
38     {MEDIA_DATA_DB_DATE_MODIFIED, HandleDateModified},
39     {MEDIA_DATA_DB_ORIENTATION, HandleOrientation},
40     {PhotoColumn::PHOTO_EXIF_ROTATE, HandleExifRotate},
41     {MEDIA_DATA_DB_POSITION, HandlePosition},
42     {MEDIA_DATA_DB_HEIGHT, HandlePhotoHeight},
43     {MEDIA_DATA_DB_WIDTH, HandlePhotoWidth},
44     {MEDIA_DATA_DB_DIRTY, HandleDirty},
45     {MEDIA_DATA_DB_THUMBNAIL_READY, HandleReady},
46     {PhotoColumn::PHOTO_LCD_VISIT_TIME, HandleLcdVisitTime},
47 };
48 
HandleId(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,int idx,ThumbnailData & data)49 void ThumbnailRdbUtils::HandleId(const std::shared_ptr<NativeRdb::ResultSet> &resultSet, int idx, ThumbnailData &data)
50 {
51     ParseStringResult(resultSet, idx, data.id);
52 }
53 
HandleFilePath(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,int idx,ThumbnailData & data)54 void ThumbnailRdbUtils::HandleFilePath(const std::shared_ptr<NativeRdb::ResultSet> &resultSet,
55     int idx, ThumbnailData &data)
56 {
57     ParseStringResult(resultSet, idx, data.path);
58 }
59 
HandleDateAdded(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,int idx,ThumbnailData & data)60 void ThumbnailRdbUtils::HandleDateAdded(const std::shared_ptr<NativeRdb::ResultSet> &resultSet, int idx,
61     ThumbnailData &data)
62 {
63     ParseStringResult(resultSet, idx, data.dateAdded);
64 }
65 
HandleDisplayName(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,int idx,ThumbnailData & data)66 void ThumbnailRdbUtils::HandleDisplayName(const std::shared_ptr<NativeRdb::ResultSet> &resultSet,
67     int idx, ThumbnailData &data)
68 {
69     ParseStringResult(resultSet, idx, data.displayName);
70 }
71 
HandleDateTaken(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,int idx,ThumbnailData & data)72 void ThumbnailRdbUtils::HandleDateTaken(const std::shared_ptr<NativeRdb::ResultSet> &resultSet,
73     int idx, ThumbnailData &data)
74 {
75     ParseStringResult(resultSet, idx, data.dateTaken);
76 }
77 
HandleDateModified(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,int idx,ThumbnailData & data)78 void ThumbnailRdbUtils::HandleDateModified(const std::shared_ptr<NativeRdb::ResultSet> &resultSet,
79     int idx, ThumbnailData &data)
80 {
81     ParseStringResult(resultSet, idx, data.dateModified);
82 }
83 
HandleMediaType(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,int idx,ThumbnailData & data)84 void ThumbnailRdbUtils::HandleMediaType(const std::shared_ptr<NativeRdb::ResultSet> &resultSet,
85     int idx, ThumbnailData &data)
86 {
87     data.mediaType = MediaType::MEDIA_TYPE_ALL;
88     ParseInt32Result(resultSet, idx, data.mediaType);
89 }
90 
HandleOrientation(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,int idx,ThumbnailData & data)91 void ThumbnailRdbUtils::HandleOrientation(const std::shared_ptr<NativeRdb::ResultSet> &resultSet,
92     int idx, ThumbnailData &data)
93 {
94     ParseInt32Result(resultSet, idx, data.orientation);
95 }
96 
HandleExifRotate(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,int idx,ThumbnailData & data)97 void ThumbnailRdbUtils::HandleExifRotate(const std::shared_ptr<NativeRdb::ResultSet> &resultSet,
98     int idx, ThumbnailData &data)
99 {
100     ParseInt32Result(resultSet, idx, data.exifRotate);
101 }
102 
HandlePosition(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,int idx,ThumbnailData & data)103 void ThumbnailRdbUtils::HandlePosition(const std::shared_ptr<NativeRdb::ResultSet> &resultSet,
104     int idx, ThumbnailData &data)
105 {
106     int position = 0;
107     ParseInt32Result(resultSet, idx, position);
108     data.isLocalFile = (position == static_cast<int32_t>(PhotoPositionType::LOCAL) ||
109         position == static_cast<int32_t>(PhotoPositionType::LOCAL_AND_CLOUD));
110     data.position = position;
111 }
112 
HandlePhotoHeight(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,int idx,ThumbnailData & data)113 void ThumbnailRdbUtils::HandlePhotoHeight(const std::shared_ptr<NativeRdb::ResultSet> &resultSet,
114     int idx, ThumbnailData &data)
115 {
116     ParseInt32Result(resultSet, idx, data.photoHeight);
117 }
118 
HandlePhotoWidth(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,int idx,ThumbnailData & data)119 void ThumbnailRdbUtils::HandlePhotoWidth(const std::shared_ptr<NativeRdb::ResultSet> &resultSet,
120     int idx, ThumbnailData &data)
121 {
122     ParseInt32Result(resultSet, idx, data.photoWidth);
123 }
124 
HandleDirty(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,int idx,ThumbnailData & data)125 void ThumbnailRdbUtils::HandleDirty(const std::shared_ptr<NativeRdb::ResultSet> &resultSet,
126     int idx, ThumbnailData &data)
127 {
128     ParseInt32Result(resultSet, idx, data.dirty);
129 }
130 
HandleReady(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,int idx,ThumbnailData & data)131 void ThumbnailRdbUtils::HandleReady(const std::shared_ptr<NativeRdb::ResultSet> &resultSet,
132     int idx, ThumbnailData &data)
133 {
134     ParseInt64Result(resultSet, idx, data.thumbnailReady);
135 }
136 
HandleLcdVisitTime(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,int idx,ThumbnailData & data)137 void ThumbnailRdbUtils::HandleLcdVisitTime(const std::shared_ptr<NativeRdb::ResultSet> &resultSet,
138     int idx, ThumbnailData &data)
139 {
140     ParseInt64Result(resultSet, idx, data.lcdVisitTime);
141 }
142 
QueryThumbnailDataInfos(shared_ptr<MediaLibraryRdbStore> store,NativeRdb::RdbPredicates & rdbPredicates,const vector<string> & column,vector<ThumbnailData> & datas)143 bool ThumbnailRdbUtils::QueryThumbnailDataInfos(shared_ptr<MediaLibraryRdbStore> store,
144     NativeRdb::RdbPredicates &rdbPredicates, const vector<string> &column, vector<ThumbnailData> &datas)
145 {
146     int err;
147     return QueryThumbnailDataInfos(store, rdbPredicates, column, datas, err);
148 }
149 
QueryThumbnailDataInfos(shared_ptr<MediaLibraryRdbStore> store,NativeRdb::RdbPredicates & rdbPredicates,const vector<string> & column,vector<ThumbnailData> & datas,int & err)150 bool ThumbnailRdbUtils::QueryThumbnailDataInfos(shared_ptr<MediaLibraryRdbStore> store,
151     NativeRdb::RdbPredicates &rdbPredicates, const vector<string> &column, vector<ThumbnailData> &datas, int &err)
152 {
153     CHECK_AND_RETURN_RET_LOG(store != nullptr, false, "RdbStore is nullptr");
154     shared_ptr<ResultSet> resultSet = store->QueryByStep(rdbPredicates, column);
155     return QueryThumbnailDataInfos(resultSet, column, datas, err);
156 }
157 
QueryThumbnailDataInfos(const shared_ptr<ResultSet> & resultSet,const vector<string> & column,vector<ThumbnailData> & datas,int & err)158 bool ThumbnailRdbUtils::QueryThumbnailDataInfos(const shared_ptr<ResultSet> &resultSet,
159     const vector<string> &column, vector<ThumbnailData> &datas, int &err)
160 {
161     if (!CheckResultSetCount(resultSet, err)) {
162         MEDIA_ERR_LOG("CheckResultSetCount failed %{public}d", err);
163         if (err == E_EMPTY_VALUES_BUCKET) {
164             return true;
165         }
166         return false;
167     }
168 
169     err = resultSet->GoToFirstRow();
170     CHECK_AND_RETURN_RET_LOG(err == E_OK, false, "Failed GoToFirstRow %{public}d", err);
171 
172     ThumbnailData data;
173     do {
174         ParseQueryResult(resultSet, data, err, column);
175         if (!data.path.empty()) {
176             datas.push_back(data);
177         }
178     } while (resultSet->GoToNextRow() == E_OK);
179     return true;
180 }
181 
QueryThumbnailDataInfo(shared_ptr<MediaLibraryRdbStore> store,NativeRdb::RdbPredicates & rdbPredicates,const vector<string> & column,ThumbnailData & data)182 bool ThumbnailRdbUtils::QueryThumbnailDataInfo(shared_ptr<MediaLibraryRdbStore> store,
183     NativeRdb::RdbPredicates &rdbPredicates, const vector<string> &column, ThumbnailData &data)
184 {
185     int err;
186     return QueryThumbnailDataInfo(store, rdbPredicates, column, data, err);
187 }
188 
QueryThumbnailDataInfo(shared_ptr<MediaLibraryRdbStore> store,NativeRdb::RdbPredicates & rdbPredicates,const vector<string> & column,ThumbnailData & data,int & err)189 bool ThumbnailRdbUtils::QueryThumbnailDataInfo(shared_ptr<MediaLibraryRdbStore> store,
190     NativeRdb::RdbPredicates &rdbPredicates, const vector<string> &column, ThumbnailData &data, int &err)
191 {
192     CHECK_AND_RETURN_RET_LOG(store != nullptr, false, "RdbStore is nullptr");
193     auto resultSet = store->QueryByStep(rdbPredicates, column);
194     return QueryThumbnailDataInfo(resultSet, column, data, err);
195 }
196 
QueryThumbnailDataInfo(const shared_ptr<ResultSet> & resultSet,const vector<string> & column,ThumbnailData & data,int & err)197 bool ThumbnailRdbUtils::QueryThumbnailDataInfo(const shared_ptr<ResultSet> &resultSet,
198     const vector<string> &column, ThumbnailData &data, int &err)
199 {
200     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, false, "ResultSet is nullptr");
201 
202     err = resultSet->GoToFirstRow();
203     CHECK_AND_RETURN_RET_LOG(err == NativeRdb::E_OK, false, "Fail to GoToFirstRow");
204 
205     ParseQueryResult(resultSet, data, err, column);
206     return true;
207 }
208 
CheckResultSetCount(const shared_ptr<ResultSet> & resultSet,int & err)209 bool ThumbnailRdbUtils::CheckResultSetCount(const shared_ptr<ResultSet> &resultSet, int &err)
210 {
211     if (resultSet == nullptr) {
212         MEDIA_ERR_LOG("ResultSet is nullptr!");
213         return false;
214     }
215     int rowCount = 0;
216     err = resultSet->GetRowCount(rowCount);
217     if (err != E_OK || rowCount < 0) {
218         MEDIA_ERR_LOG("Failed to get row count %{public}d", err);
219         return false;
220     } else if (rowCount == 0) {
221         MEDIA_INFO_LOG("CheckCount No match!");
222         err = E_EMPTY_VALUES_BUCKET;
223         return false;
224     }
225     return true;
226 }
227 
ParseQueryResult(const shared_ptr<ResultSet> & resultSet,ThumbnailData & data,int & err,const std::vector<std::string> & column)228 void ThumbnailRdbUtils::ParseQueryResult(const shared_ptr<ResultSet> &resultSet, ThumbnailData &data,
229     int &err, const std::vector<std::string> &column)
230 {
231     CHECK_AND_RETURN_LOG(resultSet != nullptr, "ResultSet is nullptr!");
232     int index;
233     for (auto &columnValue : column) {
234         err = resultSet->GetColumnIndex(columnValue, index);
235         if (err != NativeRdb::E_OK) {
236             continue;
237         }
238         auto iter = RESULT_SET_HANDLER.find(columnValue);
239         if (iter != RESULT_SET_HANDLER.end()) {
240             iter->second(resultSet, index, data);
241         }
242     }
243 }
244 
ParseStringResult(const shared_ptr<ResultSet> & resultSet,int index,string & data)245 void ThumbnailRdbUtils::ParseStringResult(const shared_ptr<ResultSet> &resultSet, int index, string &data)
246 {
247     CHECK_AND_RETURN_LOG(resultSet != nullptr, "ResultSet is nullptr!");
248     bool isNull = true;
249     int err = resultSet->IsColumnNull(index, isNull);
250     if (err != E_OK) {
251         MEDIA_ERR_LOG("Failed to check column %{public}d null %{public}d", index, err);
252     }
253 
254     if (!isNull) {
255         err = resultSet->GetString(index, data);
256         if (err != E_OK) {
257             MEDIA_ERR_LOG("Failed to get column %{public}d string %{public}d", index, err);
258         }
259     }
260 }
261 
ParseInt32Result(const shared_ptr<ResultSet> & resultSet,int index,int32_t & data)262 void ThumbnailRdbUtils::ParseInt32Result(const shared_ptr<ResultSet> &resultSet, int index, int32_t &data)
263 {
264     CHECK_AND_RETURN_LOG(resultSet != nullptr, "ResultSet is nullptr!");
265     bool isNull = true;
266     int err = resultSet->IsColumnNull(index, isNull);
267     if (err != E_OK) {
268         MEDIA_ERR_LOG("Failed to check column %{public}d null %{public}d", index, err);
269     }
270 
271     if (!isNull) {
272         err = resultSet->GetInt(index, data);
273         if (err != E_OK) {
274             MEDIA_ERR_LOG("Failed to get column %{public}d int32 %{public}d", index, err);
275         }
276     }
277 }
278 
ParseInt64Result(const shared_ptr<ResultSet> & resultSet,int index,int64_t & data)279 void ThumbnailRdbUtils::ParseInt64Result(const shared_ptr<ResultSet> &resultSet, int index, int64_t &data)
280 {
281     CHECK_AND_RETURN_LOG(resultSet != nullptr, "ResultSet is nullptr!");
282     bool isNull = true;
283     int err = resultSet->IsColumnNull(index, isNull);
284     if (err != E_OK) {
285         MEDIA_ERR_LOG("Failed to check column %{public}d null %{public}d", index, err);
286     }
287 
288     if (!isNull) {
289         err = resultSet->GetLong(index, data);
290         if (err != E_OK) {
291             MEDIA_ERR_LOG("Failed to get column %{public}d int64 %{public}d", index, err);
292         }
293     }
294 }
295 
QueryLocalNoExifRotateInfos(ThumbRdbOpt & opts,vector<ThumbnailData> & infos)296 bool ThumbnailRdbUtils::QueryLocalNoExifRotateInfos(ThumbRdbOpt &opts, vector<ThumbnailData> &infos)
297 {
298     vector<string> column = {
299         MEDIA_DATA_DB_ID, MEDIA_DATA_DB_FILE_PATH, MEDIA_DATA_DB_MEDIA_TYPE, MEDIA_DATA_DB_NAME,
300     };
301     RdbPredicates rdbPredicates(PhotoColumn::PHOTOS_TABLE);
302     rdbPredicates.OrderByDesc(MEDIA_DATA_DB_DATE_TAKEN);
303     rdbPredicates.BeginWrap()
304         ->EqualTo(PhotoColumn::PHOTO_EXIF_ROTATE, "0")
305         ->And()->EqualTo(MediaColumn::MEDIA_TIME_PENDING, "0")
306         ->And()->EqualTo(PhotoColumn::PHOTO_IS_TEMP, "0")
307         ->EndWrap();
308 
309     rdbPredicates.BeginWrap()
310         ->EqualTo(PhotoColumn::PHOTO_POSITION, "1")->Or()->EqualTo(PhotoColumn::PHOTO_POSITION, "3")
311         ->EndWrap();
312     CHECK_AND_RETURN_RET_LOG(ThumbnailRdbUtils::QueryThumbnailDataInfos(opts.store, rdbPredicates, column, infos),
313         false, "QueryThumbnailDataInfos failed");
314     return true;
315 }
316 
UpdateRdbStoreById(ThumbRdbOpt & opts,const string & id,const NativeRdb::ValuesBucket & values)317 int32_t ThumbnailRdbUtils::UpdateRdbStoreById(ThumbRdbOpt &opts, const string &id,
318     const NativeRdb::ValuesBucket &values)
319 {
320     CHECK_AND_RETURN_RET_LOG(opts.store != nullptr, E_RDB_STORE_NULL, "Store is nullptr!");
321     CHECK_AND_RETURN_RET_LOG(!values.IsEmpty(), E_OK, "ValuesBucket is empty");
322     NativeRdb::AbsRdbPredicates predicates = NativeRdb::AbsRdbPredicates(opts.table);
323     predicates.EqualTo(MediaColumn::MEDIA_ID, id);
324     int32_t changedRows = -1;
325     MediaLibraryTracer tracer;
326     tracer.Start("UpdateRdbStoreById");
327     int32_t ret = opts.store->Update(changedRows, values, predicates);
328     CHECK_AND_RETURN_RET_LOG(ret == E_OK, ret, "Store execute update err: %{public}d", ret);
329     CHECK_AND_RETURN_RET_LOG(changedRows > 0, E_RDB_UPDATE_NO_ROWS_CHANGED,
330         "Update changedRows: %{public}d", changedRows);
331     return E_OK;
332 }
333 
UpdateExifRotateAndDirty(const ThumbnailData & data,DirtyType dirtyType)334 int32_t ThumbnailRdbUtils::UpdateExifRotateAndDirty(const ThumbnailData &data, DirtyType dirtyType)
335 {
336     CHECK_AND_RETURN_RET_LOG(dirtyType == DirtyType::TYPE_FDIRTY || dirtyType == DirtyType::TYPE_MDIRTY,
337         E_ERR, "Not support update this type dirty, type:%{public}d", dirtyType);
338 
339     string dirtyStr = std::to_string(static_cast<int32_t>(dirtyType));
340     std::string updateSql =
341         "UPDATE " + PhotoColumn::PHOTOS_TABLE +
342         " SET " +
343             PhotoColumn::PHOTO_EXIF_ROTATE + " = " + to_string(data.exifRotate) + ", " +
344             PhotoColumn::PHOTO_META_DATE_MODIFIED + " = " + to_string(MediaFileUtils::UTCTimeMilliSeconds()) + ", " +
345             PhotoColumn::PHOTO_DIRTY + " = CASE " +
346                 " WHEN " + PhotoColumn::PHOTO_DIRTY + " IN (0, 2, 6, 8) THEN " + dirtyStr +
347                 " ELSE " + PhotoColumn::PHOTO_DIRTY +
348             " END " +
349         " WHERE " + MediaColumn::MEDIA_ID + " = " + data.id;
350     std::shared_ptr<AccurateRefresh::AssetAccurateRefresh> assetRefresh =
351         std::make_shared<AccurateRefresh::AssetAccurateRefresh>();
352     CHECK_AND_RETURN_RET_LOG(assetRefresh != nullptr, E_ERR, "Create assetRefresh failed");
353 
354     int32_t ret = assetRefresh->ExecuteSql(updateSql, AccurateRefresh::RdbOperation::RDB_OPERATION_UPDATE);
355     CHECK_AND_RETURN_RET_LOG(ret == AccurateRefresh::ACCURATE_REFRESH_RET_OK,
356         E_ERR, "Failed to Update, ret: %{public}d", ret);
357     assetRefresh->Notify();
358     return E_OK;
359 }
360 } // namespace Media
361 } // namespace OHOS