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 bool cond = (rdbStore == nullptr || !rdbStore->CheckRdbStore());
102 CHECK_AND_RETURN_RET_LOG(!cond, NativeRdb::E_ERROR,
103 "Pointer rdbStore_ is nullptr. Maybe it didn't init successfully.");
104 auto resultSet = rdbStore->QueryByStep(QUERY_NEED_UPDATE_FILE_IDS);
105 CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, NativeRdb::E_ERROR, "query photos by step failed");
106
107 std::vector<std::string> needUpdateFileIds;
108 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
109 needUpdateFileIds.push_back(GetStringVal(PhotoColumn::MEDIA_ID, resultSet));
110 }
111 resultSet->Close();
112 auto needChangedSize = needUpdateFileIds.size();
113 CHECK_AND_RETURN_RET(needChangedSize > 0, NativeRdb::E_OK);
114
115 int32_t ret = NativeRdb::E_OK;
116 int64_t totalChanged = 0;
117 for (size_t start = 0; start < needChangedSize; start += UPDATE_BATCH_SIZE) {
118 size_t end = std::min(start + UPDATE_BATCH_SIZE, needChangedSize);
119 std::stringstream updateSql;
120 updateSql << UPDATE_DAY_MONTH_YEAR;
121 for (size_t i = start; i < end; ++i) {
122 if (i != start) {
123 updateSql << ", ";
124 }
125 updateSql << needUpdateFileIds[i];
126 }
127 updateSql << " );";
128 int64_t batchStart = MediaFileUtils::UTCTimeMilliSeconds();
129 int64_t changedRowCount = 0;
130 auto errCode = rdbStore->ExecuteForChangedRowCount(changedRowCount, updateSql.str());
131 if (errCode != NativeRdb::E_OK) {
132 ret = errCode;
133 MEDIA_ERR_LOG("update photos date failed, errCode: %{public}d, batchStart: %{public}" PRId64
134 ", cost: %{public}" PRId64,
135 errCode, batchStart, MediaFileUtils::UTCTimeMilliSeconds() - batchStart);
136 } else {
137 totalChanged += changedRowCount;
138 MEDIA_DEBUG_LOG("update photos date, batchStart: %{public}" PRId64 ", cost: %{public}" PRId64
139 ", changedRowCount: %{public}" PRId64,
140 batchStart, MediaFileUtils::UTCTimeMilliSeconds() - batchStart, changedRowCount);
141 }
142 }
143
144 MEDIA_INFO_LOG("update photos date end, startTime: %{public}" PRId64 ", cost: %{public}" PRId64
145 ", needChangedSize: %{public}zu, totalChanged: %{public}" PRId64,
146 startTime, MediaFileUtils::UTCTimeMilliSeconds() - startTime, needChangedSize, totalChanged);
147 return ret;
148 }
149
UpdatePhotosDateAndIdx(const std::shared_ptr<MediaLibraryRdbStore> rdbStore)150 int32_t PhotoDayMonthYearOperation::UpdatePhotosDateAndIdx(const std::shared_ptr<MediaLibraryRdbStore> rdbStore)
151 {
152 MEDIA_INFO_LOG("update phots date start");
153 int64_t startTime = MediaFileUtils::UTCTimeMilliSeconds();
154 bool cond = (rdbStore == nullptr || !rdbStore->CheckRdbStore());
155 CHECK_AND_RETURN_RET_LOG(!cond, NativeRdb::E_ERROR,
156 "Pointer rdbStore_ is nullptr. Maybe it didn't init successfully.");
157
158 auto ret = UpdatePhotosDate(rdbStore);
159 CHECK_AND_RETURN_RET_LOG(ret == NativeRdb::E_OK, ret, "update day month year failed, ret=%{public}d", ret);
160 MEDIA_INFO_LOG("update phots date end, startTime: %{public}" PRId64 ", cost: %{public}" PRId64, startTime,
161 (MediaFileUtils::UTCTimeMilliSeconds() - startTime));
162 return NativeRdb::E_OK;
163 }
164
UpdatePhotosDate(NativeRdb::RdbStore & rdbStore)165 int32_t PhotoDayMonthYearOperation::UpdatePhotosDate(NativeRdb::RdbStore &rdbStore)
166 {
167 MEDIA_INFO_LOG("update photos date start");
168 int64_t startTime = MediaFileUtils::UTCTimeMilliSeconds();
169
170 auto resultSet = rdbStore.QueryByStep(QUERY_NEED_UPDATE_FILE_IDS);
171 CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, NativeRdb::E_ERROR, "query photos by step failed");
172
173 std::vector<std::string> needUpdateFileIds;
174 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
175 needUpdateFileIds.push_back(GetStringVal(PhotoColumn::MEDIA_ID, resultSet));
176 }
177 resultSet->Close();
178 auto needChangedSize = needUpdateFileIds.size();
179 CHECK_AND_RETURN_RET(needChangedSize > 0, NativeRdb::E_OK);
180
181 std::stringstream updateSql;
182 updateSql << UPDATE_DAY_MONTH_YEAR;
183 for (size_t i = 0; i < needChangedSize; ++i) {
184 if (i != 0) {
185 updateSql << ", ";
186 }
187 updateSql << needUpdateFileIds[i];
188 }
189 updateSql << " );";
190 int64_t changedRowCount = 0;
191 auto errCode = rdbStore.ExecuteForChangedRowCount(changedRowCount, updateSql.str());
192 CHECK_AND_RETURN_RET_LOG(errCode == NativeRdb::E_OK, errCode,
193 "update photos date failed, errCode: %{public}d, startTime: %{public}" PRId64
194 ", cost: %{public}" PRId64 ", needChangedSize: %{public}zu",
195 errCode, startTime, MediaFileUtils::UTCTimeMilliSeconds() - startTime, needChangedSize);
196
197 MEDIA_INFO_LOG("update photos date end, startTime: %{public}" PRId64 ", cost: %{public}" PRId64
198 ", needChangedSize: %{public}zu, changedRowCount: %{public}" PRId64,
199 startTime, MediaFileUtils::UTCTimeMilliSeconds() - startTime, needChangedSize, changedRowCount);
200 return NativeRdb::E_OK;
201 }
202
UpdatePhotosDateIdx(const std::shared_ptr<MediaLibraryRdbStore> rdbStore)203 int32_t PhotoDayMonthYearOperation::UpdatePhotosDateIdx(const std::shared_ptr<MediaLibraryRdbStore> rdbStore)
204 {
205 MEDIA_INFO_LOG("update photos date idx start");
206 int64_t startTime = MediaFileUtils::UTCTimeMilliSeconds();
207 bool cond = (rdbStore == nullptr || !rdbStore->CheckRdbStore());
208 CHECK_AND_RETURN_RET_LOG(!cond, NativeRdb::E_ERROR,
209 "Pointer rdbStore_ is nullptr. Maybe it didn't init successfully.");
210
211 auto ret = rdbStore->ExecuteSql(PhotoColumn::DROP_SCHPT_DAY_INDEX);
212 CHECK_AND_PRINT_LOG(ret == NativeRdb::E_OK, "drop idx date_day failed, ret=%{public}d", ret);
213
214 ret = rdbStore->ExecuteSql(PhotoColumn::CREATE_SCHPT_DAY_INDEX);
215 CHECK_AND_PRINT_LOG(ret == NativeRdb::E_OK, "create idx date_day failed, ret=%{public}d", ret);
216
217 ret = rdbStore->ExecuteSql(PhotoColumn::DROP_SCHPT_MONTH_COUNT_READY_INDEX);
218 CHECK_AND_PRINT_LOG(ret == NativeRdb::E_OK, "drop idx date_month failed, ret=%{public}d", ret);
219
220 ret = rdbStore->ExecuteSql(PhotoColumn::CREATE_SCHPT_MONTH_COUNT_READY_INDEX);
221 CHECK_AND_PRINT_LOG(ret == NativeRdb::E_OK, "create idx date_month failed, ret=%{public}d", ret);
222
223 ret = rdbStore->ExecuteSql(PhotoColumn::DROP_SCHPT_YEAR_COUNT_READY_INDEX);
224 CHECK_AND_PRINT_LOG(ret == NativeRdb::E_OK, "drop idx date_year failed, ret=%{public}d", ret);
225
226 ret = rdbStore->ExecuteSql(PhotoColumn::CREATE_SCHPT_YEAR_COUNT_READY_INDEX);
227 CHECK_AND_RETURN_RET_LOG(ret == NativeRdb::E_OK, ret, "create idx date_year failed, ret=%{public}d", ret);
228
229 MEDIA_INFO_LOG("update photos date idx end, startTime: %{public}" PRId64 ", cost: %{public}" PRId64, startTime,
230 (MediaFileUtils::UTCTimeMilliSeconds() - startTime));
231 return NativeRdb::E_OK;
232 }
233
QueryNeedUpdateFileIds(const int32_t batchSize)234 std::pair<int32_t, std::vector<std::string>> PhotoDayMonthYearOperation::QueryNeedUpdateFileIds(const int32_t batchSize)
235 {
236 MEDIA_DEBUG_LOG("Query need update fileIds start");
237
238 std::vector<std::string> needUpdateFileIds;
239 auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
240 if (rdbStore == nullptr) {
241 MEDIA_ERR_LOG("rdbStore is nullptr!");
242 return { NativeRdb::E_ERROR, needUpdateFileIds };
243 }
244
245 const std::string sql = ""
246 "SELECT"
247 " file_id "
248 "FROM"
249 " Photos "
250 "WHERE"
251 " date_added = 0 "
252 " OR date_taken = 0 "
253 " OR date_day <> strftime( '%Y%m%d', date_taken / 1000, 'unixepoch', 'localtime' ) "
254 " LIMIT " +
255 std::to_string(batchSize) + ";";
256
257 auto resultSet = rdbStore->QueryByStep(sql);
258 if (resultSet == nullptr) {
259 MEDIA_ERR_LOG("query need update fileIds by step failed!");
260 return { NativeRdb::E_ERROR, needUpdateFileIds };
261 }
262
263 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
264 needUpdateFileIds.push_back(GetStringVal(PhotoColumn::MEDIA_ID, resultSet));
265 }
266 resultSet->Close();
267
268 return { NativeRdb::E_OK, needUpdateFileIds };
269 }
270
UpdateAbnormalDayMonthYear(std::vector<std::string> & fileIds)271 int32_t PhotoDayMonthYearOperation::UpdateAbnormalDayMonthYear(std::vector<std::string> &fileIds)
272 {
273 MEDIA_DEBUG_LOG("update abnormal day month year data start");
274
275 auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
276 CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, NativeRdb::E_ERROR, "rdbStore is nullptr!");
277
278 auto needChangedSize = fileIds.size();
279 CHECK_AND_RETURN_RET(needChangedSize > 0, NativeRdb::E_OK);
280
281 std::stringstream updateSql;
282 updateSql << UPDATE_DAY_MONTH_YEAR;
283 for (size_t i = 0; i < needChangedSize; ++i) {
284 if (i != 0) {
285 updateSql << ", ";
286 }
287 updateSql << fileIds[i];
288 }
289 updateSql << " );";
290 int64_t changedRowCount = 0;
291
292 auto errCode = rdbStore->ExecuteForChangedRowCount(changedRowCount, updateSql.str());
293 CHECK_AND_RETURN_RET_LOG(errCode == NativeRdb::E_OK, errCode,
294 "update abnormal day month year data failed, errCode: %{public}d, needChangedSize: %{public}zu",
295 errCode, needChangedSize);
296 MEDIA_DEBUG_LOG(
297 "update abnormal day month year data end, needChangedSize: %{public}zu, changedRowCount: %{public}" PRId64,
298 needChangedSize, changedRowCount);
299 return NativeRdb::E_OK;
300 }
301 } // namespace Media
302 } // namespace OHOS
303