111 if (!nameSpace.startsWith(
"org.qt-project."_L1))
116 const QChar dot(u'.');
117 QString &tail = result.tail;
118 for (
int i = nameSpace.size(); i > 0; --i) {
119 const QChar c = nameSpace.at(i - 1);
120 if (c.isDigit() || c == dot)
127 if (!tail.startsWith(dot) && tail.count(dot) == 1) {
130 const int dotIndex = tail.indexOf(dot);
132 tail = tail.mid(dotIndex);
136 while (tail.startsWith(dot))
140 while (tail.endsWith(dot))
143 if (tail.size() >= 3 && tail.size() <= 5 && tail.count(dot) == 0) {
147 QStringView tail{result.tail};
148 result
.major = tail.left(1).toInt();
149 result
.minor = tail.size() == 3 ? tail.mid(1, 1).toInt() : tail.mid(1, 2).toInt();
150 result
.patch = tail.size() == 5 ? tail.right(2).toInt() : tail.right(1).toInt();
197 m_query->setForwardOnly(
true);
199 QMap<
int, QString> attributeIds;
200 m_query->exec(
"SELECT DISTINCT Id, Name FROM FilterAttributeTable ORDER BY Id"_L1);
201 while (m_query->next())
202 attributeIds.insert(m_query->value(0).toInt(), m_query->value(1).toString());
206 QList<
int> usedAttributeIds;
207 for (
auto it = attributeIds.cbegin(), end = attributeIds.cend(); it != end; ++it) {
208 const int attributeId = it.key();
209 if (isAttributeUsed(m_query.get(),
"IndexFilterTable"_L1, attributeId)
210 || isAttributeUsed(m_query.get(),
"ContentsFilterTable"_L1, attributeId)
211 || isAttributeUsed(m_query.get(),
"FileFilterTable"_L1, attributeId)) {
212 usedAttributeIds.append(attributeId);
217 m_query->exec(
"SELECT * FROM pragma_table_info('IndexTable') WHERE name='ContextName'"_L1);
221 const QString identifierColumnName = legacy ?
"ContextName"_L1 :
"Identifier"_L1;
222 const int usedAttributeCount = usedAttributeIds.size();
224 QMap<
int, IndexItem> idToIndexItem;
225 m_query->exec(QString::fromLatin1(
"SELECT Name, %1, FileId, Anchor, Id "
227 "ORDER BY Id").arg(identifierColumnName));
228 while (m_query->next()) {
230 indexItem.name = m_query->value(0).toString();
231 indexItem.identifier = m_query->value(1).toString();
232 indexItem.fileId = m_query->value(2).toInt();
233 indexItem.anchor = m_query->value(3).toString();
234 const int indexId = m_query->value(4).toInt();
236 idToIndexItem.insert(indexId, indexItem);
239 QMap<
int, FileItem> idToFileItem;
240 QMap<
int,
int> originalFileIdToNewFileId;
245 "FileNameTable.FileId, "
246 "FileNameTable.Name, "
247 "FileNameTable.Title "
248 "FROM FileNameTable, FolderTable "
249 "WHERE FileNameTable.FolderId = FolderTable.Id "
250 "ORDER BY FileId"_L1);
251 while (m_query->next()) {
252 const int fileId = m_query->value(0).toInt();
254 fileItem.name = m_query->value(1).toString();
255 fileItem.title = m_query->value(2).toString();
257 idToFileItem.insert(fileId, fileItem);
258 originalFileIdToNewFileId.insert(fileId, filesCount);
262 QMap<
int, ContentsItem> idToContentsItem;
264 m_query->exec(
"SELECT Data, Id FROM ContentsTable ORDER BY Id"_L1);
265 while (m_query->next()) {
267 contentsItem.data = m_query->value(0).toByteArray();
268 const int contentsId = m_query->value(1).toInt();
270 idToContentsItem.insert(contentsId, contentsItem);
273 bool optimized =
true;
275 if (usedAttributeCount) {
284 const bool mayOptimizeIndexTable = filterDataCount(m_query.get(),
"IndexFilterTable"_L1)
285 == idToIndexItem.size() * usedAttributeCount;
286 const bool mayOptimizeFileTable = filterDataCount(m_query.get(),
"FileFilterTable"_L1)
287 == idToFileItem.size() * usedAttributeCount;
288 const bool mayOptimizeContentsTable =
289 filterDataCount(m_query.get(),
"ContentsFilterTable"_L1)
290 == idToContentsItem.size() * usedAttributeCount;
291 optimized = mayOptimizeIndexTable && mayOptimizeFileTable && mayOptimizeContentsTable;
296 "IndexFilterTable.IndexId, "
297 "FilterAttributeTable.Name "
300 "FilterAttributeTable "
302 "IndexFilterTable.FilterAttributeId = FilterAttributeTable.Id"_L1);
303 while (m_query->next()) {
304 const int indexId = m_query->value(0).toInt();
305 auto it = idToIndexItem.find(indexId);
306 if (it != idToIndexItem.end())
307 it.value().filterAttributes.append(m_query->value(1).toString());
312 "FileFilterTable.FileId, "
313 "FilterAttributeTable.Name "
316 "FilterAttributeTable "
318 "FileFilterTable.FilterAttributeId = FilterAttributeTable.Id"_L1);
319 while (m_query->next()) {
320 const int fileId = m_query->value(0).toInt();
321 auto it = idToFileItem.find(fileId);
322 if (it != idToFileItem.end())
323 it.value().filterAttributes.append(m_query->value(1).toString());
328 "ContentsFilterTable.ContentsId, "
329 "FilterAttributeTable.Name "
331 "ContentsFilterTable, "
332 "FilterAttributeTable "
334 "ContentsFilterTable.FilterAttributeId = FilterAttributeTable.Id"_L1);
335 while (m_query->next()) {
336 const int contentsId = m_query->value(0).toInt();
337 auto it = idToContentsItem.find(contentsId);
338 if (it != idToContentsItem.end())
339 it.value().filterAttributes.append(m_query->value(1).toString());
345 for (
auto it = idToIndexItem.cbegin(), end = idToIndexItem.cend(); it != end; ++it) {
346 IndexItem item = it.value();
348 item.fileId = originalFileIdToNewFileId.value(item.fileId, -1);
349 table.indexItems.append(item);
352 table.fileItems = idToFileItem.values();
353 table.contentsItems = idToContentsItem.values();
356 for (
int attributeId : std::as_const(usedAttributeIds))
357 table.usedFilterAttributes.append(attributeIds.value(attributeId));
360 m_query->setForwardOnly(
false);
460 const QStringList &extensionFilters,
461 const std::function<
bool(
const QString &fileName,
462 const QByteArray &data)> &handler)
const
469 if (!extensionFilters.isEmpty()) {
470 QStringList conditions;
471 for (
const QString &extensionFilter : extensionFilters)
472 conditions.append(
"FileNameTable.Name LIKE \'%.%1\'"_L1.arg(extensionFilter));
473 extension =
"AND (%1)"_L1.arg(conditions.join(
" OR "_L1));
476 if (filterAttributes.isEmpty()) {
479 "FileNameTable.Name, "
480 "FileDataTable.Data "
485 "WHERE FileDataTable.Id = FileNameTable.FileId "
486 "AND FileNameTable.FolderId = FolderTable.Id %1"_L1.arg(extension);
488 for (
int i = 0; i < filterAttributes.size(); ++i) {
490 query.append(
" INTERSECT "_L1);
493 "FileNameTable.Name, "
494 "FileDataTable.Data "
500 "FilterAttributeTable "
501 "WHERE FileDataTable.Id = FileNameTable.FileId "
502 "AND FileNameTable.FolderId = FolderTable.Id "
503 "AND FileNameTable.FileId = FileFilterTable.FileId "
504 "AND FileFilterTable.FilterAttributeId = FilterAttributeTable.Id "
505 "AND FilterAttributeTable.Name = \'%1\' %2"_L1
506 .arg(quote(filterAttributes.at(i)), extension));
511 m_query->setForwardOnly(
true);
512 m_query->exec(query);
513 while (m_query->next()) {
514 if (!handler(m_query->value(0).toString(),
515 qUncompress(m_query->value(1).toByteArray()))) {
520 m_query->setForwardOnly(
false);