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