1 /*
2 * Copyright (c) 2024 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
16 #define MLOG_TAG "PhotoDayMonthYearOperation"
17
18 #include "photo_day_month_year_operation.h"
19
20 #include "media_file_utils.h"
21 #include "media_log.h"
22 #include "medialibrary_unistore_manager.h"
23 #include "result_set_utils.h"
24
25 namespace OHOS {
26 namespace Media {
27 const int32_t UPDATE_BATCH_SIZE = 200;
28
29 const std::string QUERY_NEED_UPDATE_FILE_IDS = ""
30 "SELECT file_id FROM Photos "
31 "WHERE"
32 " date_added = 0"
33 " OR date_taken = 0"
34 " OR date_day <> strftime( '%Y%m%d', date_taken / 1000, 'unixepoch', 'localtime' );";
35
36 const std::string UPDATE_DAY_MONTH_YEAR = ""
37 "UPDATE Photos "
38 "SET date_added ="
39 " CASE"
40 " WHEN date_added <> 0 THEN"
41 " date_added "
42 " WHEN date_taken <> 0 THEN"
43 " date_taken "
44 " WHEN date_modified <> 0 THEN"
45 " date_modified ELSE strftime( '%s', 'now' ) "
46 " END, "
47 "date_taken ="
48 " CASE"
49 " WHEN date_taken <> 0 THEN"
50 " date_taken "
51 " WHEN date_added <> 0 THEN"
52 " date_added "
53 " WHEN date_modified <> 0 THEN"
54 " date_modified ELSE strftime( '%s', 'now' ) "
55 " END, "
56 "date_day ="
57 " CASE"
58 " WHEN date_taken <> 0 THEN"
59 " strftime( '%Y%m%d', date_taken / 1000, 'unixepoch', 'localtime' ) "
60 " WHEN date_added <> 0 THEN"
61 " strftime( '%Y%m%d', date_added / 1000, 'unixepoch', 'localtime' ) "
62 " WHEN date_modified <> 0 THEN"
63 " strftime( '%Y%m%d', date_modified / 1000, 'unixepoch', 'localtime' ) "
64 " ELSE strftime( '%Y%m%d', strftime( '%s', 'now' ) / 1000, 'unixepoch', 'localtime' ) "
65 " END, "
66 "date_month ="
67 " CASE"
68 " WHEN date_taken <> 0 THEN"
69 " strftime( '%Y%m', date_taken / 1000, 'unixepoch', 'localtime' ) "
70 " WHEN date_added <> 0 THEN"
71 " strftime( '%Y%m', date_added / 1000, 'unixepoch', 'localtime' ) "
72 " WHEN date_modified <> 0 THEN"
73 " strftime( '%Y%m', date_modified / 1000, 'unixepoch', 'localtime' ) "
74 " ELSE strftime( '%Y%m', strftime( '%s', 'now' ) / 1000, 'unixepoch', 'localtime' ) "
75 " END, "
76 "date_year ="
77 " CASE"
78 " WHEN date_taken <> 0 THEN"
79 " strftime( '%Y', date_taken / 1000, 'unixepoch', 'localtime' ) "
80 " WHEN date_added <> 0 THEN"
81 " strftime( '%Y', date_added / 1000, 'unixepoch', 'localtime' ) "
82 " WHEN date_modified <> 0 THEN"
83 " strftime( '%Y', date_modified / 1000, 'unixepoch', 'localtime' ) "
84 " ELSE strftime( '%Y', strftime( '%s', 'now' ) / 1000, 'unixepoch', 'localtime' ) "
85 " END, "
86 "dirty ="
87 " CASE"
88 " WHEN dirty = 0 THEN"
89 " 2 ELSE dirty "
90 " END "
91 "WHERE"
92 " ( date_added = 0 "
93 " OR date_taken = 0 "
94 " OR date_day <> strftime( '%Y%m%d', date_taken / 1000, 'unixepoch', 'localtime' ) )"
95 " AND file_id IN ( ";
96
UpdatePhotosDate(const std::shared_ptr<MediaLibraryRdbStore> rdbStore)97 int32_t PhotoDayMonthYearOperation::UpdatePhotosDate(const std::shared_ptr<MediaLibraryRdbStore> rdbStore)
98 {
99 MEDIA_INFO_LOG("update photos date start");
100 int64_t startTime = MediaFileUtils::UTCTimeMilliSeconds();
101 if (rdbStore == nullptr || !rdbStore->CheckRdbStore()) {
102 MEDIA_ERR_LOG("Pointer rdbStore_ is nullptr. Maybe it didn't init successfully.");
103 return NativeRdb::E_ERROR;
104 }
105
106 auto resultSet = rdbStore->QueryByStep(QUERY_NEED_UPDATE_FILE_IDS);
107 CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, NativeRdb::E_ERROR, "query photos by step failed");
108
109 std::vector<std::string> needUpdateFileIds;
110 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
111 needUpdateFileIds.push_back(GetStringVal(PhotoColumn::MEDIA_ID, resultSet));
112 }
113 resultSet->Close();
114 auto needChangedSize = needUpdateFileIds.size();
115 CHECK_AND_RETURN_RET(needChangedSize > 0, NativeRdb::E_OK);
116
117 int32_t ret = NativeRdb::E_OK;
118 int64_t totalChanged = 0;
119 for (size_t start = 0; start < needChangedSize; start += UPDATE_BATCH_SIZE) {
120 size_t end = std::min(start + UPDATE_BATCH_SIZE, needChangedSize);
121 std::stringstream updateSql;
122 updateSql << UPDATE_DAY_MONTH_YEAR;
123 for (size_t i = start; i < end; ++i) {
124 if (i != start) {
125 updateSql << ", ";
126 }
127 updateSql << needUpdateFileIds[i];
128 }
129 updateSql << " );";
130 int64_t batchStart = MediaFileUtils::UTCTimeMilliSeconds();
131 int64_t changedRowCount = 0;
132 auto errCode = rdbStore->ExecuteForChangedRowCount(changedRowCount, updateSql.str());
133 if (errCode != NativeRdb::E_OK) {
134 ret = errCode;
135 MEDIA_ERR_LOG("update photos date failed, errCode: %{public}d, batchStart: %{public}" PRId64
136 ", cost: %{public}" PRId64,
137 errCode, batchStart, MediaFileUtils::UTCTimeMilliSeconds() - batchStart);
138 } else {
139 totalChanged += changedRowCount;
140 MEDIA_DEBUG_LOG("update photos date, batchStart: %{public}" PRId64 ", cost: %{public}" PRId64
141 ", changedRowCount: %{public}" PRId64,
142 batchStart, MediaFileUtils::UTCTimeMilliSeconds() - batchStart, changedRowCount);
143 }
144 }
145
146 MEDIA_INFO_LOG("update photos date end, startTime: %{public}" PRId64 ", cost: %{public}" PRId64
147 ", needChangedSize: %{public}zu, totalChanged: %{public}" PRId64,
148 startTime, MediaFileUtils::UTCTimeMilliSeconds() - startTime, needChangedSize, totalChanged);
149 return ret;
150 }
151
UpdatePhotosDateAndIdx(const std::shared_ptr<MediaLibraryRdbStore> rdbStore)152 int32_t PhotoDayMonthYearOperation::UpdatePhotosDateAndIdx(const std::shared_ptr<MediaLibraryRdbStore> rdbStore)
153 {
154 MEDIA_INFO_LOG("update phots date start");
155 int64_t startTime = MediaFileUtils::UTCTimeMilliSeconds();
156 if (rdbStore == nullptr || !rdbStore->CheckRdbStore()) {
157 MEDIA_ERR_LOG("Pointer rdbStore_ is nullptr. Maybe it didn't init successfully.");
158 return NativeRdb::E_ERROR;
159 }
160
161 auto ret = UpdatePhotosDate(rdbStore);
162 CHECK_AND_RETURN_RET_LOG(ret == NativeRdb::E_OK, ret, "update day month year failed, ret=%{public}d", ret);
163
164 MEDIA_INFO_LOG("update phots date end, startTime: %{public}" PRId64 ", cost: %{public}" PRId64, startTime,
165 (MediaFileUtils::UTCTimeMilliSeconds() - startTime));
166 return NativeRdb::E_OK;
167 }
168
UpdatePhotosDate(NativeRdb::RdbStore & rdbStore)169 int32_t PhotoDayMonthYearOperation::UpdatePhotosDate(NativeRdb::RdbStore &rdbStore)
170 {
171 MEDIA_INFO_LOG("update photos date start");
172 int64_t startTime = MediaFileUtils::UTCTimeMilliSeconds();
173
174 auto resultSet = rdbStore.QueryByStep(QUERY_NEED_UPDATE_FILE_IDS);
175 CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, NativeRdb::E_ERROR, "query photos by step failed");
176
177 std::vector<std::string> needUpdateFileIds;
178 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
179 needUpdateFileIds.push_back(GetStringVal(PhotoColumn::MEDIA_ID, resultSet));
180 }
181 resultSet->Close();
182 auto needChangedSize = needUpdateFileIds.size();
183 CHECK_AND_RETURN_RET(needChangedSize > 0, NativeRdb::E_OK);
184
185 std::stringstream updateSql;
186 updateSql << UPDATE_DAY_MONTH_YEAR;
187 for (size_t i = 0; i < needChangedSize; ++i) {
188 if (i != 0) {
189 updateSql << ", ";
190 }
191 updateSql << needUpdateFileIds[i];
192 }
193 updateSql << " );";
194 int64_t changedRowCount = 0;
195 auto errCode = rdbStore.ExecuteForChangedRowCount(changedRowCount, updateSql.str());
196 if (errCode != NativeRdb::E_OK) {
197 MEDIA_ERR_LOG("update photos date failed, errCode: %{public}d, startTime: %{public}" PRId64
198 ", cost: %{public}" PRId64 ", needChangedSize: %{public}zu",
199 errCode, startTime, MediaFileUtils::UTCTimeMilliSeconds() - startTime, needChangedSize);
200 return errCode;
201 }
202 MEDIA_INFO_LOG("update photos date end, startTime: %{public}" PRId64 ", cost: %{public}" PRId64
203 ", needChangedSize: %{public}zu, changedRowCount: %{public}" PRId64,
204 startTime, MediaFileUtils::UTCTimeMilliSeconds() - startTime, needChangedSize, changedRowCount);
205 return NativeRdb::E_OK;
206 }
207
UpdatePhotosDateIdx(const std::shared_ptr<MediaLibraryRdbStore> rdbStore)208 int32_t PhotoDayMonthYearOperation::UpdatePhotosDateIdx(const std::shared_ptr<MediaLibraryRdbStore> rdbStore)
209 {
210 MEDIA_INFO_LOG("update photos date idx start");
211 int64_t startTime = MediaFileUtils::UTCTimeMilliSeconds();
212 if (rdbStore == nullptr || !rdbStore->CheckRdbStore()) {
213 MEDIA_ERR_LOG("Pointer rdbStore_ is nullptr. Maybe it didn't init successfully.");
214 return NativeRdb::E_ERROR;
215 }
216
217 auto ret = rdbStore->ExecuteSql(PhotoColumn::DROP_SCHPT_DAY_INDEX);
218 CHECK_AND_PRINT_LOG(ret == NativeRdb::E_OK, "drop idx date_day failed, ret=%{public}d", ret);
219
220 ret = rdbStore->ExecuteSql(PhotoColumn::CREATE_SCHPT_DAY_INDEX);
221 CHECK_AND_PRINT_LOG(ret == NativeRdb::E_OK, "create idx date_day failed, ret=%{public}d", ret);
222
223 ret = rdbStore->ExecuteSql(PhotoColumn::DROP_SCHPT_MONTH_COUNT_READY_INDEX);
224 CHECK_AND_PRINT_LOG(ret == NativeRdb::E_OK, "drop idx date_month failed, ret=%{public}d", ret);
225
226 ret = rdbStore->ExecuteSql(PhotoColumn::CREATE_SCHPT_MONTH_COUNT_READY_INDEX);
227 CHECK_AND_PRINT_LOG(ret == NativeRdb::E_OK, "create idx date_month failed, ret=%{public}d", ret);
228
229 ret = rdbStore->ExecuteSql(PhotoColumn::DROP_SCHPT_YEAR_COUNT_READY_INDEX);
230 CHECK_AND_PRINT_LOG(ret == NativeRdb::E_OK, "drop idx date_year failed, ret=%{public}d", ret);
231
232 ret = rdbStore->ExecuteSql(PhotoColumn::CREATE_SCHPT_YEAR_COUNT_READY_INDEX);
233 CHECK_AND_RETURN_RET_LOG(ret == NativeRdb::E_OK, ret, "create idx date_year failed, ret=%{public}d", ret);
234
235 MEDIA_INFO_LOG("update photos date idx end, startTime: %{public}" PRId64 ", cost: %{public}" PRId64, startTime,
236 (MediaFileUtils::UTCTimeMilliSeconds() - startTime));
237 return NativeRdb::E_OK;
238 }
239
QueryNeedUpdateFileIds(const int32_t batchSize)240 std::pair<int32_t, std::vector<std::string>> PhotoDayMonthYearOperation::QueryNeedUpdateFileIds(const int32_t batchSize)
241 {
242 MEDIA_DEBUG_LOG("Query need update fileIds start");
243
244 std::vector<std::string> needUpdateFileIds;
245 auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
246 if (rdbStore == nullptr) {
247 MEDIA_ERR_LOG("rdbStore is nullptr!");
248 return { NativeRdb::E_ERROR, needUpdateFileIds };
249 }
250
251 const std::string sql = ""
252 "SELECT"
253 " file_id "
254 "FROM"
255 " Photos "
256 "WHERE"
257 " date_added = 0 "
258 " OR date_taken = 0 "
259 " OR date_day <> strftime( '%Y%m%d', date_taken / 1000, 'unixepoch', 'localtime' ) "
260 " LIMIT " +
261 std::to_string(batchSize) + ";";
262
263 auto resultSet = rdbStore->QueryByStep(sql);
264 if (resultSet == nullptr) {
265 MEDIA_ERR_LOG("query need update fileIds by step failed!");
266 return { NativeRdb::E_ERROR, needUpdateFileIds };
267 }
268
269 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
270 needUpdateFileIds.push_back(GetStringVal(PhotoColumn::MEDIA_ID, resultSet));
271 }
272 resultSet->Close();
273
274 return { NativeRdb::E_OK, needUpdateFileIds };
275 }
276
UpdateAbnormalDayMonthYear(std::vector<std::string> & fileIds)277 int32_t PhotoDayMonthYearOperation::UpdateAbnormalDayMonthYear(std::vector<std::string> &fileIds)
278 {
279 MEDIA_DEBUG_LOG("update abnormal day month year data start");
280
281 auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
282 if (rdbStore == nullptr) {
283 MEDIA_ERR_LOG("rdbStore is nullptr!");
284 return NativeRdb::E_ERROR;
285 }
286
287 auto needChangedSize = fileIds.size();
288 CHECK_AND_RETURN_RET(needChangedSize > 0, NativeRdb::E_OK);
289
290 std::stringstream updateSql;
291 updateSql << UPDATE_DAY_MONTH_YEAR;
292 for (size_t i = 0; i < needChangedSize; ++i) {
293 if (i != 0) {
294 updateSql << ", ";
295 }
296 updateSql << fileIds[i];
297 }
298 updateSql << " );";
299 int64_t changedRowCount = 0;
300 auto errCode = rdbStore->ExecuteForChangedRowCount(changedRowCount, updateSql.str());
301 if (errCode != NativeRdb::E_OK) {
302 MEDIA_ERR_LOG("update abnormal day month year data failed, errCode: %{public}d, needChangedSize: %{public}zu",
303 errCode, needChangedSize);
304 return errCode;
305 }
306 MEDIA_DEBUG_LOG(
307 "update abnormal day month year data end, needChangedSize: %{public}zu, changedRowCount: %{public}" PRId64,
308 needChangedSize, changedRowCount);
309 return NativeRdb::E_OK;
310 }
311 } // namespace Media
312 } // namespace OHOS
313