1 /**************************************************************************** 2 ** 3 ** Copyright (C) 2021 The Qt Company Ltd. 4 ** Contact: https://www.qt.io/licensing/ 5 ** 6 ** This file is part of Qt Creator. 7 ** 8 ** Commercial License Usage 9 ** Licensees holding valid commercial Qt licenses may use this file in 10 ** accordance with the commercial license agreement provided with the 11 ** Software or, alternatively, in accordance with the terms contained in 12 ** a written agreement between you and The Qt Company. For licensing terms 13 ** and conditions see https://www.qt.io/terms-conditions. For further 14 ** information use the contact form at https://www.qt.io/contact-us. 15 ** 16 ** GNU General Public License Usage 17 ** Alternatively, this file may be used under the terms of the GNU 18 ** General Public License version 3 as published by the Free Software 19 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT 20 ** included in the packaging of this file. Please review the following 21 ** information to ensure the GNU General Public License requirements will 22 ** be met: https://www.gnu.org/licenses/gpl-3.0.html. 23 ** 24 ****************************************************************************/ 25 26 #pragma once 27 28 #include "projectstorageexceptions.h" 29 #include "projectstorageids.h" 30 #include "projectstoragetypes.h" 31 #include "sourcepathcachetypes.h" 32 33 #include <sqlitealgorithms.h> 34 #include <sqlitetable.h> 35 #include <sqlitetransaction.h> 36 37 #include <utils/algorithm.h> 38 #include <utils/optional.h> 39 40 #include <tuple> 41 42 namespace QmlDesigner { 43 44 template<typename Database> 45 class ProjectStorage 46 { 47 public: 48 template<int ResultCount> 49 using ReadStatement = typename Database::template ReadStatement<ResultCount>; 50 template<int ResultCount> 51 using ReadWriteStatement = typename Database::template ReadWriteStatement<ResultCount>; 52 using WriteStatement = typename Database::WriteStatement; 53 ProjectStorage(Database & database,bool isInitialized)54 ProjectStorage(Database &database, bool isInitialized) 55 : database{database} 56 , initializer{database, isInitialized} 57 {} 58 synchronizeTypes(Storage::Types types,SourceIds sourceIds)59 void synchronizeTypes(Storage::Types types, SourceIds sourceIds) 60 { 61 Sqlite::ImmediateTransaction transaction{database}; 62 63 TypeIds updatedTypeIds; 64 updatedTypeIds.reserve(types.size()); 65 66 for (auto &&type : types) { 67 if (!type.sourceId) 68 throw TypeHasInvalidSourceId{}; 69 70 updatedTypeIds.push_back(declareType(type)); 71 } 72 73 for (auto &&type : types) 74 synchronizeAliasPropertyDeclarationsRemoval(type); 75 76 for (auto &&type : types) 77 syncType(type); 78 79 for (auto &&type : types) 80 synchronizeAliasPropertyDeclarations(type); 81 82 deleteNotUpdatedTypes(updatedTypeIds, sourceIds); 83 84 transaction.commit(); 85 } 86 synchronizeImports(Storage::Imports imports)87 void synchronizeImports(Storage::Imports imports) 88 { 89 Sqlite::ImmediateTransaction transaction{database}; 90 91 synchronizeImportsAndUpdatesImportIds(imports); 92 synchronizeImportDependencies(createSortedImportDependecies(imports)); 93 94 transaction.commit(); 95 } 96 fetchImportIds(const Storage::Imports & imports)97 ImportIds fetchImportIds(const Storage::Imports &imports) 98 { 99 ImportIds importIds; 100 101 Sqlite::DeferredTransaction transaction{database}; 102 103 for (auto &&import : imports) 104 importIds.push_back(fetchImportId(import)); 105 106 transaction.commit(); 107 108 return importIds; 109 } 110 fetchImportDependencyIds(ImportIds importIds)111 ImportIds fetchImportDependencyIds(ImportIds importIds) const 112 { 113 return fetchImportDependencyIdsStatement.template valuesWithTransaction<ImportId>( 114 16, static_cast<void *>(importIds.data()), static_cast<long long>(importIds.size())); 115 } 116 fetchPropertyDeclarationByTypeIdAndName(TypeId typeId,Utils::SmallStringView name)117 PropertyDeclarationId fetchPropertyDeclarationByTypeIdAndName(TypeId typeId, 118 Utils::SmallStringView name) 119 { 120 return selectPropertyDeclarationIdByTypeIdAndNameStatement 121 .template valueWithTransaction<PropertyDeclarationId>(&typeId, name); 122 } 123 fetchTypeIdByExportedName(Utils::SmallStringView name)124 TypeId fetchTypeIdByExportedName(Utils::SmallStringView name) const 125 { 126 return selectTypeIdByExportedNameStatement.template valueWithTransaction<TypeId>(name); 127 } 128 fetchTypeIdByImportIdsAndExportedName(ImportIds importIds,Utils::SmallStringView name)129 TypeId fetchTypeIdByImportIdsAndExportedName(ImportIds importIds, Utils::SmallStringView name) const 130 { 131 return selectTypeIdByImportIdsAndExportedNameStatement.template valueWithTransaction<TypeId>( 132 static_cast<void *>(importIds.data()), static_cast<long long>(importIds.size()), name); 133 } 134 fetchTypeIdByName(ImportId importId,Utils::SmallStringView name)135 TypeId fetchTypeIdByName(ImportId importId, Utils::SmallStringView name) 136 { 137 return selectTypeIdByImportIdAndNameStatement.template valueWithTransaction<TypeId>(&importId, 138 name); 139 } 140 fetchTypeByTypeId(TypeId typeId)141 Storage::Type fetchTypeByTypeId(TypeId typeId) 142 { 143 Sqlite::DeferredTransaction transaction{database}; 144 145 auto type = selectTypeByTypeIdStatement.template value<Storage::Type>(&typeId); 146 147 type.exportedTypes = fetchExportedTypes(typeId); 148 149 transaction.commit(); 150 151 return type; 152 } 153 fetchTypes()154 Storage::Types fetchTypes() 155 { 156 Sqlite::DeferredTransaction transaction{database}; 157 158 auto types = selectTypesStatement.template values<Storage::Type>(64); 159 160 for (Storage::Type &type : types) { 161 type.exportedTypes = fetchExportedTypes(type.typeId); 162 type.propertyDeclarations = fetchPropertyDeclarations(type.typeId); 163 type.functionDeclarations = fetchFunctionDeclarations(type.typeId); 164 type.signalDeclarations = fetchSignalDeclarations(type.typeId); 165 type.enumerationDeclarations = fetchEnumerationDeclarations(type.typeId); 166 } 167 168 transaction.commit(); 169 170 return types; 171 } 172 fetchIsProtype(TypeId type,TypeId prototype)173 bool fetchIsProtype(TypeId type, TypeId prototype) 174 { 175 return bool( 176 selectPrototypeIdStatement.template valueWithTransaction<TypeId>(&type, &prototype)); 177 } 178 fetchPrototypes(TypeId type)179 auto fetchPrototypes(TypeId type) 180 { 181 return selectPrototypeIdsStatement.template rangeWithTransaction<TypeId>(&type); 182 } 183 fetchSourceContextIdUnguarded(Utils::SmallStringView sourceContextPath)184 SourceContextId fetchSourceContextIdUnguarded(Utils::SmallStringView sourceContextPath) 185 { 186 auto sourceContextId = readSourceContextId(sourceContextPath); 187 188 return sourceContextId ? sourceContextId : writeSourceContextId(sourceContextPath); 189 } 190 fetchSourceContextId(Utils::SmallStringView sourceContextPath)191 SourceContextId fetchSourceContextId(Utils::SmallStringView sourceContextPath) 192 { 193 try { 194 Sqlite::DeferredTransaction transaction{database}; 195 196 auto sourceContextId = fetchSourceContextIdUnguarded(sourceContextPath); 197 198 transaction.commit(); 199 200 return sourceContextId; 201 } catch (const Sqlite::ConstraintPreventsModification &) { 202 return fetchSourceContextId(sourceContextPath); 203 } 204 } 205 fetchSourceContextPath(SourceContextId sourceContextId)206 Utils::PathString fetchSourceContextPath(SourceContextId sourceContextId) const 207 { 208 Sqlite::DeferredTransaction transaction{database}; 209 210 auto optionalSourceContextPath = selectSourceContextPathFromSourceContextsBySourceContextIdStatement 211 .template optionalValue<Utils::PathString>( 212 &sourceContextId); 213 214 if (!optionalSourceContextPath) 215 throw SourceContextIdDoesNotExists(); 216 217 transaction.commit(); 218 219 return std::move(*optionalSourceContextPath); 220 } 221 fetchAllSourceContexts()222 auto fetchAllSourceContexts() const 223 { 224 return selectAllSourceContextsStatement.template valuesWithTransaction<Cache::SourceContext>( 225 128); 226 } 227 fetchSourceId(SourceContextId sourceContextId,Utils::SmallStringView sourceName)228 SourceId fetchSourceId(SourceContextId sourceContextId, Utils::SmallStringView sourceName) 229 { 230 Sqlite::DeferredTransaction transaction{database}; 231 232 auto sourceId = fetchSourceIdUnguarded(sourceContextId, sourceName); 233 234 transaction.commit(); 235 236 return sourceId; 237 } 238 fetchSourceNameAndSourceContextId(SourceId sourceId)239 auto fetchSourceNameAndSourceContextId(SourceId sourceId) const 240 { 241 auto value = selectSourceNameAndSourceContextIdFromSourcesBySourceIdStatement 242 .template valueWithTransaction<Cache::SourceNameAndSourceContextId>(&sourceId); 243 244 if (!value.sourceContextId) 245 throw SourceIdDoesNotExists(); 246 247 return value; 248 } 249 fetchSourceContextId(SourceId sourceId)250 SourceContextId fetchSourceContextId(SourceId sourceId) const 251 { 252 auto sourceContextId = selectSourceContextIdFromSourcesBySourceIdStatement 253 .template valueWithTransaction<SourceContextId>(sourceId.id); 254 255 if (!sourceContextId) 256 throw SourceIdDoesNotExists(); 257 258 return sourceContextId; 259 } 260 fetchAllSources()261 auto fetchAllSources() const 262 { 263 return selectAllSourcesStatement.template valuesWithTransaction<Cache::Source>(1024); 264 } 265 fetchSourceIdUnguarded(SourceContextId sourceContextId,Utils::SmallStringView sourceName)266 SourceId fetchSourceIdUnguarded(SourceContextId sourceContextId, Utils::SmallStringView sourceName) 267 { 268 auto sourceId = readSourceId(sourceContextId, sourceName); 269 270 if (sourceId) 271 return sourceId; 272 273 return writeSourceId(sourceContextId, sourceName); 274 } 275 fetchAllImports()276 auto fetchAllImports() const 277 { 278 Storage::Imports imports; 279 imports.reserve(128); 280 281 auto callback = [&](Utils::SmallStringView name, int version, int sourceId, long long importId) { 282 auto &lastImport = imports.emplace_back(name, 283 Storage::VersionNumber{version}, 284 SourceId{sourceId}); 285 286 lastImport.importDependencies = selectImportsForThatDependentOnThisImportIdStatement 287 .template values<Storage::BasicImport>(6, importId); 288 289 return Sqlite::CallbackControl::Continue; 290 }; 291 292 selectAllImportsStatement.readCallbackWithTransaction(callback); 293 294 return imports; 295 } 296 297 private: 298 struct ImportDependency 299 { ImportDependencyImportDependency300 ImportDependency(ImportId id, ImportId dependencyId) 301 : id{id} 302 , dependencyId{dependencyId} 303 {} 304 ImportDependencyImportDependency305 ImportDependency(long long id, long long dependencyId) 306 : id{id} 307 , dependencyId{dependencyId} 308 {} 309 310 ImportId id; 311 ImportId dependencyId; 312 313 friend bool operator<(ImportDependency first, ImportDependency second) 314 { 315 return std::tie(first.id, first.dependencyId) < std::tie(second.id, second.dependencyId); 316 } 317 318 friend bool operator==(ImportDependency first, ImportDependency second) 319 { 320 return first.id == second.id && first.dependencyId == second.dependencyId; 321 } 322 }; 323 synchronizeImportsAndUpdatesImportIds(Storage::Imports & imports)324 void synchronizeImportsAndUpdatesImportIds(Storage::Imports &imports) 325 { 326 auto compareKey = [](auto &&first, auto &&second) { 327 auto nameCompare = Sqlite::compare(first.name, second.name); 328 329 if (nameCompare != 0) 330 return nameCompare; 331 332 return first.version.version - second.version.version; 333 }; 334 335 std::sort(imports.begin(), imports.end(), [&](auto &&first, auto &&second) { 336 return compareKey(first, second) < 0; 337 }); 338 339 auto range = selectAllImportsStatement.template range<Storage::ImportView>(); 340 341 auto insert = [&](Storage::Import &import) { 342 import.importId = insertImportStatement.template value<ImportId>(import.name, 343 import.version.version, 344 &import.sourceId); 345 }; 346 347 auto update = [&](const Storage::ImportView &importView, Storage::Import &import) { 348 if (importView.sourceId.id != import.sourceId.id) 349 updateImportStatement.write(&importView.importId, &import.sourceId); 350 import.importId = importView.importId; 351 }; 352 353 auto remove = [&](const Storage::ImportView &importView) { 354 deleteImportStatement.write(&importView.importId); 355 deleteTypesForImportId(importView.importId); 356 }; 357 358 Sqlite::insertUpdateDelete(range, imports, compareKey, insert, update, remove); 359 } 360 createSortedImportDependecies(const Storage::Imports & imports)361 std::vector<ImportDependency> createSortedImportDependecies(const Storage::Imports &imports) const 362 { 363 std::vector<ImportDependency> importDependecies; 364 importDependecies.reserve(imports.size() * 5); 365 366 for (const Storage::Import &import : imports) { 367 for (const Storage::BasicImport &importDependency : import.importDependencies) { 368 auto importIdForDependency = fetchImportId(importDependency); 369 370 if (!importIdForDependency) 371 throw ImportDoesNotExists{}; 372 373 importDependecies.emplace_back(import.importId, importIdForDependency); 374 } 375 } 376 377 std::sort(importDependecies.begin(), importDependecies.end()); 378 importDependecies.erase(std::unique(importDependecies.begin(), importDependecies.end()), 379 importDependecies.end()); 380 381 return importDependecies; 382 } 383 synchronizeImportDependencies(const std::vector<ImportDependency> & importDependecies)384 void synchronizeImportDependencies(const std::vector<ImportDependency> &importDependecies) 385 { 386 auto compareKey = [](ImportDependency first, ImportDependency second) { 387 auto idCompare = first.id.id - second.id.id; 388 389 if (idCompare != 0) 390 return idCompare; 391 392 return first.dependencyId.id - second.dependencyId.id; 393 }; 394 395 auto range = selectAllImportDependenciesStatement.template range<ImportDependency>(); 396 397 auto insert = [&](ImportDependency dependency) { 398 insertImportDependencyStatement.write(&dependency.id, &dependency.dependencyId); 399 }; 400 401 auto update = [](ImportDependency, ImportDependency) {}; 402 403 auto remove = [&](ImportDependency dependency) { 404 deleteImportDependencyStatement.write(&dependency.id, &dependency.dependencyId); 405 }; 406 407 Sqlite::insertUpdateDelete(range, importDependecies, compareKey, insert, update, remove); 408 } 409 fetchImportId(const Storage::BasicImport & import)410 ImportId fetchImportId(const Storage::BasicImport &import) const 411 { 412 if (import.version) { 413 return selectImportIdByNameAndVersionStatement 414 .template value<ImportId>(import.name, import.version.version); 415 } 416 417 return selectImportIdByNameStatement.template value<ImportId>(import.name); 418 } 419 deleteType(TypeId typeId)420 void deleteType(TypeId typeId) 421 { 422 deleteExportTypesByTypeIdStatement.write(&typeId); 423 deleteEnumerationDeclarationByTypeIdStatement.write(&typeId); 424 deletePropertyDeclarationByTypeIdStatement.write(&typeId); 425 deleteFunctionDeclarationByTypeIdStatement.write(&typeId); 426 deleteSignalDeclarationByTypeIdStatement.write(&typeId); 427 deleteTypeStatement.write(&typeId); 428 } 429 deleteNotUpdatedTypes(const TypeIds & updatedTypeIds,const SourceIds & sourceIds)430 void deleteNotUpdatedTypes(const TypeIds &updatedTypeIds, const SourceIds &sourceIds) 431 { 432 auto updatedTypeIdValues = Utils::transform<std::vector>(updatedTypeIds, [](TypeId typeId) { 433 return &typeId; 434 }); 435 436 auto sourceIdValues = Utils::transform<std::vector>(sourceIds, [](SourceId sourceId) { 437 return &sourceId; 438 }); 439 440 auto callback = [&](long long typeId) { 441 deleteType(TypeId{typeId}); 442 return Sqlite::CallbackControl::Continue; 443 }; 444 445 selectNotUpdatedTypesInSourcesStatement.readCallback(callback, 446 Utils::span(sourceIdValues), 447 Utils::span(updatedTypeIdValues)); 448 } 449 deleteTypesForImportId(ImportId importId)450 void deleteTypesForImportId(ImportId importId) 451 { 452 auto callback = [&](long long typeId) { 453 deleteType(TypeId{typeId}); 454 return Sqlite::CallbackControl::Continue; 455 }; 456 457 selectTypeIdsForImportIdStatement.readCallback(callback, &importId); 458 } 459 upsertExportedType(ImportId importId,Utils::SmallStringView name,TypeId typeId)460 void upsertExportedType(ImportId importId, Utils::SmallStringView name, TypeId typeId) 461 { 462 upsertExportedTypesStatement.write(&importId, name, &typeId); 463 } 464 synchronizePropertyDeclarations(TypeId typeId,Storage::PropertyDeclarations & propertyDeclarations,ImportIds & importIds)465 void synchronizePropertyDeclarations(TypeId typeId, 466 Storage::PropertyDeclarations &propertyDeclarations, 467 ImportIds &importIds) 468 { 469 std::sort(propertyDeclarations.begin(), 470 propertyDeclarations.end(), 471 [](auto &&first, auto &&second) { 472 return Sqlite::compare(first.name, second.name) < 0; 473 }); 474 475 auto range = selectPropertyDeclarationsForTypeIdStatement 476 .template range<Storage::PropertyDeclarationView>(&typeId); 477 478 auto compareKey = [](const Storage::PropertyDeclarationView &view, 479 const Storage::PropertyDeclaration &value) { 480 return Sqlite::compare(view.name, value.name); 481 }; 482 483 auto insert = [&](const Storage::PropertyDeclaration &value) { 484 auto propertyTypeId = fetchTypeIdByNameUngarded(value.typeName, importIds); 485 486 insertPropertyDeclarationStatement.write(&typeId, 487 value.name, 488 &propertyTypeId, 489 static_cast<int>(value.traits)); 490 }; 491 492 auto update = [&](const Storage::PropertyDeclarationView &view, 493 const Storage::PropertyDeclaration &value) { 494 auto propertyTypeId = fetchTypeIdByNameUngarded(value.typeName, importIds); 495 496 if (view.traits == value.traits && propertyTypeId == view.typeId) 497 return; 498 499 updatePropertyDeclarationStatement.write(&view.id, 500 &propertyTypeId, 501 static_cast<int>(value.traits)); 502 }; 503 504 auto remove = [&](const Storage::PropertyDeclarationView &view) { 505 deletePropertyDeclarationStatement.write(&view.id); 506 }; 507 508 Sqlite::insertUpdateDelete(range, propertyDeclarations, compareKey, insert, update, remove); 509 } 510 synchronizeAliasPropertyDeclarationsRemoval(Storage::Type & type)511 void synchronizeAliasPropertyDeclarationsRemoval(Storage::Type &type) 512 { 513 auto &aliasDeclarations = type.aliasDeclarations; 514 TypeId typeId = type.typeId; 515 516 std::sort(aliasDeclarations.begin(), aliasDeclarations.end(), [](auto &&first, auto &&second) { 517 return Sqlite::compare(first.name, second.name) < 0; 518 }); 519 520 auto range = selectPropertyDeclarationsWithAliasForTypeIdStatement 521 .template range<Storage::AliasPropertyDeclarationView>(&typeId); 522 523 auto compareKey = [](const Storage::AliasPropertyDeclarationView &view, 524 const Storage::AliasPropertyDeclaration &value) { 525 return Sqlite::compare(view.name, value.name); 526 }; 527 528 auto insert = [&](const Storage::AliasPropertyDeclaration &) {}; 529 530 auto update = [&](const Storage::AliasPropertyDeclarationView &, 531 const Storage::AliasPropertyDeclaration &) {}; 532 533 auto remove = [&](const Storage::AliasPropertyDeclarationView &view) { 534 deletePropertyDeclarationStatement.write(&view.id); 535 }; 536 537 Sqlite::insertUpdateDelete(range, aliasDeclarations, compareKey, insert, update, remove); 538 } 539 synchronizeAliasPropertyDeclarations(Storage::Type & type)540 void synchronizeAliasPropertyDeclarations(Storage::Type &type) 541 { 542 auto &aliasDeclarations = type.aliasDeclarations; 543 TypeId typeId = type.typeId; 544 ImportIds &importIds = type.importIds; 545 546 std::sort(aliasDeclarations.begin(), aliasDeclarations.end(), [](auto &&first, auto &&second) { 547 return Sqlite::compare(first.name, second.name) < 0; 548 }); 549 550 auto range = selectPropertyDeclarationsWithAliasForTypeIdStatement 551 .template range<Storage::AliasPropertyDeclarationView>(&typeId); 552 553 auto compareKey = [](const Storage::AliasPropertyDeclarationView &view, 554 const Storage::AliasPropertyDeclaration &value) { 555 return Sqlite::compare(view.name, value.name); 556 }; 557 558 auto insert = [&](const Storage::AliasPropertyDeclaration &value) { 559 auto [aliasTypeId, aliasId, propertyTraits] = fetchPropertyDeclarationByTypeNameAndName( 560 value.aliasTypeName, value.aliasPropertyName, importIds); 561 562 insertPropertyDeclarationWithAliasStatement.write(&typeId, 563 value.name, 564 &aliasTypeId, 565 propertyTraits, 566 &aliasId); 567 }; 568 569 auto update = [&](const Storage::AliasPropertyDeclarationView &view, 570 const Storage::AliasPropertyDeclaration &value) { 571 auto [aliasTypeId, aliasId, propertyTraits] = fetchPropertyDeclarationByTypeNameAndName( 572 value.aliasTypeName, value.aliasPropertyName, importIds); 573 574 if (view.aliasId == aliasId) 575 return; 576 577 updatePropertyDeclarationWithAliasStatement.write(&view.id, 578 &aliasTypeId, 579 propertyTraits, 580 &aliasId); 581 }; 582 583 auto remove = [&](const Storage::AliasPropertyDeclarationView &) {}; 584 585 Sqlite::insertUpdateDelete(range, aliasDeclarations, compareKey, insert, update, remove); 586 } 587 createJson(const Storage::ParameterDeclarations & parameters)588 Utils::PathString createJson(const Storage::ParameterDeclarations ¶meters) 589 { 590 Utils::PathString json; 591 json.append("["); 592 593 Utils::SmallStringView comma{""}; 594 595 for (const auto ¶meter : parameters) { 596 json.append(comma); 597 comma = ","; 598 json.append("{\"n\":\""); 599 json.append(parameter.name); 600 json.append("\",\"tn\":\""); 601 json.append(parameter.typeName); 602 if (parameter.traits == Storage::PropertyDeclarationTraits::Non) { 603 json.append("\"}"); 604 } else { 605 json.append("\",\"tr\":"); 606 json.append(Utils::SmallString::number(static_cast<int>(parameter.traits))); 607 json.append("}"); 608 } 609 } 610 611 json.append("]"); 612 613 return json; 614 } 615 synchronizeFunctionDeclarations(TypeId typeId,Storage::FunctionDeclarations & functionsDeclarations)616 void synchronizeFunctionDeclarations(TypeId typeId, 617 Storage::FunctionDeclarations &functionsDeclarations) 618 { 619 std::sort(functionsDeclarations.begin(), 620 functionsDeclarations.end(), 621 [](auto &&first, auto &&second) { 622 return Sqlite::compare(first.name, second.name) < 0; 623 }); 624 625 auto range = selectFunctionDeclarationsForTypeIdStatement 626 .template range<Storage::FunctionDeclarationView>(&typeId); 627 628 auto compareKey = [](const Storage::FunctionDeclarationView &view, 629 const Storage::FunctionDeclaration &value) { 630 return Sqlite::compare(view.name, value.name); 631 }; 632 633 auto insert = [&](const Storage::FunctionDeclaration &value) { 634 Utils::PathString signature{createJson(value.parameters)}; 635 636 insertFunctionDeclarationStatement.write(&typeId, value.name, value.returnTypeName, signature); 637 }; 638 639 auto update = [&](const Storage::FunctionDeclarationView &view, 640 const Storage::FunctionDeclaration &value) { 641 Utils::PathString signature{createJson(value.parameters)}; 642 643 if (value.returnTypeName == view.returnTypeName && signature == view.signature) 644 return; 645 646 updateFunctionDeclarationStatement.write(&view.id, value.returnTypeName, signature); 647 }; 648 649 auto remove = [&](const Storage::FunctionDeclarationView &view) { 650 deleteFunctionDeclarationStatement.write(&view.id); 651 }; 652 653 Sqlite::insertUpdateDelete(range, functionsDeclarations, compareKey, insert, update, remove); 654 } 655 synchronizeSignalDeclarations(TypeId typeId,Storage::SignalDeclarations & signalDeclarations)656 void synchronizeSignalDeclarations(TypeId typeId, Storage::SignalDeclarations &signalDeclarations) 657 { 658 std::sort(signalDeclarations.begin(), signalDeclarations.end(), [](auto &&first, auto &&second) { 659 return Sqlite::compare(first.name, second.name) < 0; 660 }); 661 662 auto range = selectSignalDeclarationsForTypeIdStatement 663 .template range<Storage::SignalDeclarationView>(&typeId); 664 665 auto compareKey = [](const Storage::SignalDeclarationView &view, 666 const Storage::SignalDeclaration &value) { 667 return Sqlite::compare(view.name, value.name); 668 }; 669 670 auto insert = [&](const Storage::SignalDeclaration &value) { 671 Utils::PathString signature{createJson(value.parameters)}; 672 673 insertSignalDeclarationStatement.write(&typeId, value.name, signature); 674 }; 675 676 auto update = [&](const Storage::SignalDeclarationView &view, 677 const Storage::SignalDeclaration &value) { 678 Utils::PathString signature{createJson(value.parameters)}; 679 680 if (signature == view.signature) 681 return; 682 683 updateSignalDeclarationStatement.write(&view.id, signature); 684 }; 685 686 auto remove = [&](const Storage::SignalDeclarationView &view) { 687 deleteSignalDeclarationStatement.write(&view.id); 688 }; 689 690 Sqlite::insertUpdateDelete(range, signalDeclarations, compareKey, insert, update, remove); 691 } 692 createJson(const Storage::EnumeratorDeclarations & enumeratorDeclarations)693 Utils::PathString createJson(const Storage::EnumeratorDeclarations &enumeratorDeclarations) 694 { 695 Utils::PathString json; 696 json.append("{"); 697 698 Utils::SmallStringView comma{"\""}; 699 700 for (const auto &enumerator : enumeratorDeclarations) { 701 json.append(comma); 702 comma = ",\""; 703 json.append(enumerator.name); 704 if (enumerator.hasValue) { 705 json.append("\":\""); 706 json.append(Utils::SmallString::number(enumerator.value)); 707 json.append("\""); 708 } else { 709 json.append("\":null"); 710 } 711 } 712 713 json.append("}"); 714 715 return json; 716 } 717 synchronizeEnumerationDeclarations(TypeId typeId,Storage::EnumerationDeclarations & enumerationDeclarations)718 void synchronizeEnumerationDeclarations(TypeId typeId, 719 Storage::EnumerationDeclarations &enumerationDeclarations) 720 { 721 std::sort(enumerationDeclarations.begin(), 722 enumerationDeclarations.end(), 723 [](auto &&first, auto &&second) { 724 return Sqlite::compare(first.name, second.name) < 0; 725 }); 726 727 auto range = selectEnumerationDeclarationsForTypeIdStatement 728 .template range<Storage::EnumerationDeclarationView>(&typeId); 729 730 auto compareKey = [](const Storage::EnumerationDeclarationView &view, 731 const Storage::EnumerationDeclaration &value) { 732 return Sqlite::compare(view.name, value.name); 733 }; 734 735 auto insert = [&](const Storage::EnumerationDeclaration &value) { 736 Utils::PathString signature{createJson(value.enumeratorDeclarations)}; 737 738 insertEnumerationDeclarationStatement.write(&typeId, value.name, signature); 739 }; 740 741 auto update = [&](const Storage::EnumerationDeclarationView &view, 742 const Storage::EnumerationDeclaration &value) { 743 Utils::PathString enumeratorDeclarations{createJson(value.enumeratorDeclarations)}; 744 745 if (enumeratorDeclarations == view.enumeratorDeclarations) 746 return; 747 748 updateEnumerationDeclarationStatement.write(&view.id, enumeratorDeclarations); 749 }; 750 751 auto remove = [&](const Storage::EnumerationDeclarationView &view) { 752 deleteEnumerationDeclarationStatement.write(&view.id); 753 }; 754 755 Sqlite::insertUpdateDelete(range, enumerationDeclarations, compareKey, insert, update, remove); 756 } 757 declareType(Storage::Type & type)758 TypeId declareType(Storage::Type &type) 759 { 760 type.typeId = upsertTypeStatement.template value<TypeId>(&type.importId, 761 type.typeName, 762 static_cast<int>(type.accessSemantics), 763 &type.sourceId); 764 765 for (const auto &exportedType : type.exportedTypes) 766 upsertExportedType(type.importId, exportedType.name, type.typeId); 767 768 return type.typeId; 769 } 770 syncType(Storage::Type & type)771 void syncType(Storage::Type &type) 772 { 773 auto typeId = type.typeId; 774 775 auto prototypeId = fetchTypeIdByNameUngarded(type.prototype, type.importIds); 776 777 updatePrototypeStatement.write(&typeId, &prototypeId); 778 779 synchronizePropertyDeclarations(typeId, type.propertyDeclarations, type.importIds); 780 synchronizeFunctionDeclarations(typeId, type.functionDeclarations); 781 synchronizeSignalDeclarations(typeId, type.signalDeclarations); 782 synchronizeEnumerationDeclarations(typeId, type.enumerationDeclarations); 783 } 784 fetchTypeIdByNameUngarded(const Storage::TypeName & name,ImportIds & importIds)785 TypeId fetchTypeIdByNameUngarded(const Storage::TypeName &name, ImportIds &importIds) 786 { 787 if (Utils::visit([](auto &&type) -> bool { return type.name.isEmpty(); }, name)) 788 return TypeId{}; 789 790 struct Inspect 791 { 792 TypeId operator()(const Storage::NativeType &nativeType) 793 { 794 return storage.selectTypeIdByImportIdsAndNameStatement 795 .template value<TypeId>(static_cast<void *>(importIds.data()), 796 static_cast<long long>(importIds.size()), 797 nativeType.name); 798 } 799 800 TypeId operator()(const Storage::ExportedType &exportedType) 801 { 802 return storage.selectTypeIdByImportIdsAndExportedNameStatement 803 .template value<TypeId>(static_cast<void *>(importIds.data()), 804 static_cast<long long>(importIds.size()), 805 exportedType.name); 806 } 807 808 TypeId operator()(const Storage::ExplicitExportedType &exportedType) 809 { 810 return storage.selectTypeIdByImportIdAndExportedNameStatement 811 .template value<TypeId>(&exportedType.importId, exportedType.name); 812 } 813 814 ProjectStorage &storage; 815 ImportIds &importIds; 816 }; 817 818 auto typeId = Utils::visit(Inspect{*this, importIds}, name); 819 820 if (typeId) 821 return typeId; 822 823 throw TypeNameDoesNotExists{}; 824 } 825 826 using PropertyDeclarationViewTuple = std::tuple<TypeId, PropertyDeclarationId, long long>; 827 fetchPropertyDeclarationByTypeNameAndName(const Storage::TypeName & typeName,Utils::SmallStringView name,ImportIds & importIds)828 PropertyDeclarationViewTuple fetchPropertyDeclarationByTypeNameAndName( 829 const Storage::TypeName &typeName, Utils::SmallStringView name, ImportIds &importIds) 830 { 831 TypeId typeId = fetchTypeIdByNameUngarded(typeName, importIds); 832 833 auto propertyDeclaration = selectPropertyDeclarationByTypeIdAndNameStatement 834 .template value<PropertyDeclarationViewTuple>(&typeId, name); 835 836 if (auto id = std::get<PropertyDeclarationId>(propertyDeclaration); id) 837 return propertyDeclaration; 838 839 throw PropertyNameDoesNotExists{}; 840 } 841 readSourceContextId(Utils::SmallStringView sourceContextPath)842 SourceContextId readSourceContextId(Utils::SmallStringView sourceContextPath) 843 { 844 return selectSourceContextIdFromSourceContextsBySourceContextPathStatement 845 .template value<SourceContextId>(sourceContextPath); 846 } 847 writeSourceContextId(Utils::SmallStringView sourceContextPath)848 SourceContextId writeSourceContextId(Utils::SmallStringView sourceContextPath) 849 { 850 insertIntoSourceContextsStatement.write(sourceContextPath); 851 852 return SourceContextId(database.lastInsertedRowId()); 853 } 854 writeSourceId(SourceContextId sourceContextId,Utils::SmallStringView sourceName)855 SourceId writeSourceId(SourceContextId sourceContextId, Utils::SmallStringView sourceName) 856 { 857 insertIntoSourcesStatement.write(&sourceContextId, sourceName); 858 859 return SourceId(database.lastInsertedRowId()); 860 } 861 readSourceId(SourceContextId sourceContextId,Utils::SmallStringView sourceName)862 SourceId readSourceId(SourceContextId sourceContextId, Utils::SmallStringView sourceName) 863 { 864 return selectSourceIdFromSourcesBySourceContextIdAndSourceNameStatement 865 .template value<SourceId>(&sourceContextId, sourceName); 866 } 867 fetchExportedTypes(TypeId typeId)868 auto fetchExportedTypes(TypeId typeId) 869 { 870 return selectExportedTypesByTypeIdStatement.template values<Storage::ExportedType>(12, 871 &typeId); 872 } 873 fetchPropertyDeclarations(TypeId typeId)874 auto fetchPropertyDeclarations(TypeId typeId) 875 { 876 return selectPropertyDeclarationsByTypeIdStatement 877 .template values<Storage::PropertyDeclaration>(24, &typeId); 878 } 879 fetchFunctionDeclarations(TypeId typeId)880 auto fetchFunctionDeclarations(TypeId typeId) 881 { 882 Storage::FunctionDeclarations functionDeclarations; 883 884 auto callback = [&](Utils::SmallStringView name, 885 Utils::SmallStringView returnType, 886 long long functionDeclarationId) { 887 auto &functionDeclaration = functionDeclarations.emplace_back(name, returnType); 888 functionDeclaration.parameters = selectFunctionParameterDeclarationsStatement 889 .template values<Storage::ParameterDeclaration>( 890 8, functionDeclarationId); 891 892 return Sqlite::CallbackControl::Continue; 893 }; 894 895 selectFunctionDeclarationsForTypeIdWithoutSignatureStatement.readCallback(callback, &typeId); 896 897 return functionDeclarations; 898 } 899 fetchSignalDeclarations(TypeId typeId)900 auto fetchSignalDeclarations(TypeId typeId) 901 { 902 Storage::SignalDeclarations signalDeclarations; 903 904 auto callback = [&](Utils::SmallStringView name, long long signalDeclarationId) { 905 auto &signalDeclaration = signalDeclarations.emplace_back(name); 906 signalDeclaration.parameters = selectSignalParameterDeclarationsStatement 907 .template values<Storage::ParameterDeclaration>( 908 8, signalDeclarationId); 909 910 return Sqlite::CallbackControl::Continue; 911 }; 912 913 selectSignalDeclarationsForTypeIdWithoutSignatureStatement.readCallback(callback, &typeId); 914 915 return signalDeclarations; 916 } 917 fetchEnumerationDeclarations(TypeId typeId)918 auto fetchEnumerationDeclarations(TypeId typeId) 919 { 920 Storage::EnumerationDeclarations enumerationDeclarations; 921 922 auto callback = [&](Utils::SmallStringView name, long long enumerationDeclarationId) { 923 enumerationDeclarations.emplace_back( 924 name, 925 selectEnumeratorDeclarationStatement 926 .template values<Storage::EnumeratorDeclaration>(8, enumerationDeclarationId)); 927 928 return Sqlite::CallbackControl::Continue; 929 }; 930 931 selectEnumerationDeclarationsForTypeIdWithoutEnumeratorDeclarationsStatement 932 .readCallback(callback, &typeId); 933 934 return enumerationDeclarations; 935 } 936 937 class Initializer 938 { 939 public: Initializer(Database & database,bool isInitialized)940 Initializer(Database &database, bool isInitialized) 941 { 942 if (!isInitialized) { 943 Sqlite::ExclusiveTransaction transaction{database}; 944 945 createImportsTable(database); 946 createImportDependeciesTable(database); 947 createSourceContextsTable(database); 948 createSourcesTable(database); 949 createTypesAndePropertyDeclarationsTables(database); 950 createExportedTypesTable(database); 951 createEnumerationsTable(database); 952 createFunctionsTable(database); 953 createSignalsTable(database); 954 955 transaction.commit(); 956 957 database.walCheckpointFull(); 958 } 959 } 960 createSourceContextsTable(Database & database)961 void createSourceContextsTable(Database &database) 962 { 963 Sqlite::Table table; 964 table.setUseIfNotExists(true); 965 table.setName("sourceContexts"); 966 table.addColumn("sourceContextId", Sqlite::ColumnType::Integer, {Sqlite::PrimaryKey{}}); 967 const Sqlite::Column &sourceContextPathColumn = table.addColumn("sourceContextPath"); 968 969 table.addUniqueIndex({sourceContextPathColumn}); 970 971 table.initialize(database); 972 } 973 createSourcesTable(Database & database)974 void createSourcesTable(Database &database) 975 { 976 Sqlite::Table table; 977 table.setUseIfNotExists(true); 978 table.setName("sources"); 979 table.addColumn("sourceId", Sqlite::ColumnType::Integer, {Sqlite::PrimaryKey{}}); 980 const Sqlite::Column &sourceContextIdColumn = table.addColumn( 981 "sourceContextId", 982 Sqlite::ColumnType::Integer, 983 {Sqlite::NotNull{}, 984 Sqlite::ForeignKey{"sourceContexts", 985 "sourceContextId", 986 Sqlite::ForeignKeyAction::NoAction, 987 Sqlite::ForeignKeyAction::Cascade}}); 988 const Sqlite::Column &sourceNameColumn = table.addColumn("sourceName"); 989 table.addUniqueIndex({sourceContextIdColumn, sourceNameColumn}); 990 991 table.initialize(database); 992 } 993 createTypesAndePropertyDeclarationsTables(Database & database)994 void createTypesAndePropertyDeclarationsTables(Database &database) 995 { 996 Sqlite::Table typesTable; 997 typesTable.setUseIfNotExists(true); 998 typesTable.setName("types"); 999 typesTable.addColumn("typeId", Sqlite::ColumnType::Integer, {Sqlite::PrimaryKey{}}); 1000 auto &importIdColumn = typesTable.addColumn("importId"); 1001 auto &typesNameColumn = typesTable.addColumn("name"); 1002 typesTable.addColumn("accessSemantics"); 1003 typesTable.addColumn("sourceId"); 1004 typesTable.addForeignKeyColumn("prototypeId", 1005 typesTable, 1006 Sqlite::ForeignKeyAction::NoAction, 1007 Sqlite::ForeignKeyAction::Restrict); 1008 1009 typesTable.addUniqueIndex({importIdColumn, typesNameColumn}); 1010 1011 typesTable.initialize(database); 1012 1013 { 1014 Sqlite::Table propertyDeclarationTable; 1015 propertyDeclarationTable.setUseIfNotExists(true); 1016 propertyDeclarationTable.setName("propertyDeclarations"); 1017 propertyDeclarationTable.addColumn("propertyDeclarationId", 1018 Sqlite::ColumnType::Integer, 1019 {Sqlite::PrimaryKey{}}); 1020 auto &typeIdColumn = propertyDeclarationTable.addColumn("typeId"); 1021 auto &nameColumn = propertyDeclarationTable.addColumn("name"); 1022 propertyDeclarationTable.addForeignKeyColumn("propertyTypeId", 1023 typesTable, 1024 Sqlite::ForeignKeyAction::NoAction, 1025 Sqlite::ForeignKeyAction::Restrict); 1026 propertyDeclarationTable.addColumn("propertyTraits"); 1027 auto &aliasPropertyDeclarationIdColumn = propertyDeclarationTable.addForeignKeyColumn( 1028 "aliasPropertyDeclarationId", 1029 propertyDeclarationTable, 1030 Sqlite::ForeignKeyAction::NoAction, 1031 Sqlite::ForeignKeyAction::Restrict); 1032 1033 propertyDeclarationTable.addUniqueIndex({typeIdColumn, nameColumn}); 1034 propertyDeclarationTable.addIndex({aliasPropertyDeclarationIdColumn}, 1035 "aliasPropertyDeclarationId IS NOT NULL"); 1036 1037 propertyDeclarationTable.initialize(database); 1038 } 1039 } 1040 createExportedTypesTable(Database & database)1041 void createExportedTypesTable(Database &database) 1042 { 1043 Sqlite::Table table; 1044 table.setUseIfNotExists(true); 1045 table.setUseWithoutRowId(true); 1046 table.setName("exportedTypes"); 1047 auto &importIdColumn = table.addColumn("importId"); 1048 auto &nameColumn = table.addColumn("name"); 1049 table.addColumn("typeId"); 1050 1051 table.addPrimaryKeyContraint({importIdColumn, nameColumn}); 1052 1053 table.initialize(database); 1054 } 1055 createEnumerationsTable(Database & database)1056 void createEnumerationsTable(Database &database) 1057 { 1058 Sqlite::Table table; 1059 table.setUseIfNotExists(true); 1060 table.setName("enumerationDeclarations"); 1061 table.addColumn("enumerationDeclarationId", 1062 Sqlite::ColumnType::Integer, 1063 {Sqlite::PrimaryKey{}}); 1064 auto &typeIdColumn = table.addColumn("typeId"); 1065 auto &nameColumn = table.addColumn("name"); 1066 table.addColumn("enumeratorDeclarations"); 1067 1068 table.addUniqueIndex({typeIdColumn, nameColumn}); 1069 1070 table.initialize(database); 1071 } 1072 createFunctionsTable(Database & database)1073 void createFunctionsTable(Database &database) 1074 { 1075 Sqlite::Table table; 1076 table.setUseIfNotExists(true); 1077 table.setName("functionDeclarations"); 1078 table.addColumn("functionDeclarationId", 1079 Sqlite::ColumnType::Integer, 1080 {Sqlite::PrimaryKey{}}); 1081 auto &typeIdColumn = table.addColumn("typeId"); 1082 auto &nameColumn = table.addColumn("name"); 1083 table.addColumn("signature"); 1084 table.addColumn("returnTypeName"); 1085 1086 table.addUniqueIndex({typeIdColumn, nameColumn}); 1087 1088 table.initialize(database); 1089 } 1090 createSignalsTable(Database & database)1091 void createSignalsTable(Database &database) 1092 { 1093 Sqlite::Table table; 1094 table.setUseIfNotExists(true); 1095 table.setName("signalDeclarations"); 1096 table.addColumn("signalDeclarationId", Sqlite::ColumnType::Integer, {Sqlite::PrimaryKey{}}); 1097 auto &typeIdColumn = table.addColumn("typeId"); 1098 auto &nameColumn = table.addColumn("name"); 1099 table.addColumn("signature"); 1100 1101 table.addUniqueIndex({typeIdColumn, nameColumn}); 1102 1103 table.initialize(database); 1104 } 1105 createImportsTable(Database & database)1106 void createImportsTable(Database &database) 1107 { 1108 Sqlite::Table table; 1109 table.setUseIfNotExists(true); 1110 table.setName("imports"); 1111 table.addColumn("importId", Sqlite::ColumnType::Integer, {Sqlite::PrimaryKey{}}); 1112 auto &nameColumn = table.addColumn("name"); 1113 auto &versionColumn = table.addColumn("version"); 1114 table.addColumn("sourceId"); 1115 1116 table.addUniqueIndex({nameColumn, versionColumn}); 1117 1118 table.initialize(database); 1119 } 1120 createImportDependeciesTable(Database & database)1121 void createImportDependeciesTable(Database &database) 1122 { 1123 Sqlite::Table table; 1124 table.setUseIfNotExists(true); 1125 table.setUseWithoutRowId(true); 1126 table.setName("importDependencies"); 1127 auto &importIdColumn = table.addColumn("importId"); 1128 auto &parentImportIdColumn = table.addColumn("parentImportId"); 1129 1130 table.addPrimaryKeyContraint({importIdColumn, parentImportIdColumn}); 1131 1132 table.initialize(database); 1133 } 1134 }; 1135 1136 public: 1137 Database &database; 1138 Initializer initializer; 1139 ReadWriteStatement<1> upsertTypeStatement{ 1140 "INSERT INTO types(importId, name, accessSemantics, sourceId) VALUES(?1, ?2, " 1141 "?3, nullif(?4, -1)) ON " 1142 "CONFLICT DO UPDATE SET prototypeId=excluded.prototypeId, " 1143 "accessSemantics=excluded.accessSemantics, sourceId=excluded.sourceId RETURNING typeId", 1144 database}; 1145 WriteStatement updatePrototypeStatement{ 1146 "UPDATE types SET prototypeId=nullif(?2, -1) WHERE typeId=?1", database}; 1147 mutable ReadStatement<1> selectTypeIdByExportedNameStatement{ 1148 "SELECT typeId FROM exportedTypes WHERE name=?1", database}; 1149 mutable ReadStatement<1> selectPrototypeIdStatement{ 1150 "WITH RECURSIVE " 1151 " typeSelection(typeId) AS (" 1152 " VALUES(?1) " 1153 " UNION ALL " 1154 " SELECT prototypeId FROM types JOIN typeSelection USING(typeId)) " 1155 "SELECT typeId FROM typeSelection WHERE typeId=?2 LIMIT 1", 1156 database}; 1157 mutable ReadStatement<1> selectPropertyDeclarationIdByTypeIdAndNameStatement{ 1158 "WITH RECURSIVE " 1159 " typeSelection(typeId) AS (" 1160 " VALUES(?1) " 1161 " UNION ALL " 1162 " SELECT prototypeId FROM types JOIN typeSelection USING(typeId)) " 1163 "SELECT propertyDeclarationId FROM propertyDeclarations JOIN typeSelection USING(typeId) " 1164 " WHERE name=?2 LIMIT 1", 1165 database}; 1166 mutable ReadStatement<3> selectPropertyDeclarationByTypeIdAndNameStatement{ 1167 "WITH RECURSIVE " 1168 " typeSelection(typeId) AS (" 1169 " VALUES(?1) " 1170 " UNION ALL " 1171 " SELECT prototypeId FROM types JOIN typeSelection USING(typeId)) " 1172 "SELECT propertyTypeId, propertyDeclarationId, propertyTraits FROM propertyDeclarations " 1173 " JOIN typeSelection USING(typeId) " 1174 " WHERE name=?2 LIMIT 1", 1175 database}; 1176 WriteStatement upsertExportedTypesStatement{"INSERT INTO exportedTypes(importId, name, typeId) " 1177 "VALUES(?1, ?2, ?3) ON CONFLICT DO NOTHING", 1178 database}; 1179 mutable ReadStatement<1> selectPrototypeIdsStatement{ 1180 "WITH RECURSIVE " 1181 " typeSelection(typeId) AS (" 1182 " VALUES(?1) " 1183 " UNION ALL " 1184 " SELECT prototypeId FROM types JOIN typeSelection USING(typeId)) " 1185 "SELECT typeId FROM typeSelection", 1186 database}; 1187 mutable ReadStatement<1> selectSourceContextIdFromSourceContextsBySourceContextPathStatement{ 1188 "SELECT sourceContextId FROM sourceContexts WHERE sourceContextPath = ?", database}; 1189 mutable ReadStatement<1> selectSourceContextPathFromSourceContextsBySourceContextIdStatement{ 1190 "SELECT sourceContextPath FROM sourceContexts WHERE sourceContextId = ?", database}; 1191 mutable ReadStatement<2> selectAllSourceContextsStatement{ 1192 "SELECT sourceContextPath, sourceContextId FROM sourceContexts", database}; 1193 WriteStatement insertIntoSourceContextsStatement{ 1194 "INSERT INTO sourceContexts(sourceContextPath) VALUES (?)", database}; 1195 mutable ReadStatement<1> selectSourceIdFromSourcesBySourceContextIdAndSourceNameStatement{ 1196 "SELECT sourceId FROM sources WHERE sourceContextId = ? AND sourceName = ?", database}; 1197 mutable ReadStatement<2> selectSourceNameAndSourceContextIdFromSourcesBySourceIdStatement{ 1198 "SELECT sourceName, sourceContextId FROM sources WHERE sourceId = ?", database}; 1199 mutable ReadStatement<1> selectSourceContextIdFromSourcesBySourceIdStatement{ 1200 "SELECT sourceContextId FROM sources WHERE sourceId = ?", database}; 1201 WriteStatement insertIntoSourcesStatement{ 1202 "INSERT INTO sources(sourceContextId, sourceName) VALUES (?,?)", database}; 1203 mutable ReadStatement<3> selectAllSourcesStatement{ 1204 "SELECT sourceName, sourceContextId, sourceId FROM sources", database}; 1205 mutable ReadStatement<1> selectTypeIdByImportIdsAndNameStatement{ 1206 "SELECT typeId FROM types WHERE importId IN carray(?1, ?2, 'int64') AND name=?3", database}; 1207 mutable ReadStatement<5> selectTypeByTypeIdStatement{ 1208 "SELECT importId, name, (SELECT name FROM types WHERE typeId=outerTypes.prototypeId), " 1209 "accessSemantics, ifnull(sourceId, -1) FROM types AS outerTypes WHERE typeId=?", 1210 database}; 1211 mutable ReadStatement<1> selectExportedTypesByTypeIdStatement{ 1212 "SELECT name FROM exportedTypes WHERE typeId=?", database}; 1213 mutable ReadStatement<6> selectTypesStatement{ 1214 "SELECT importId, name, typeId, (SELECT name FROM types WHERE " 1215 "typeId=outerTypes.prototypeId), accessSemantics, ifnull(sourceId, -1) FROM types AS " 1216 "outerTypes", 1217 database}; 1218 ReadStatement<1> selectNotUpdatedTypesInSourcesStatement{ 1219 "SELECT typeId FROM types WHERE (sourceId IN carray(?1) AND typeId NOT IN carray(?2))", 1220 database}; 1221 WriteStatement deleteExportTypesByTypeIdStatement{"DELETE FROM exportedTypes WHERE typeId=?", 1222 database}; 1223 WriteStatement deleteEnumerationDeclarationByTypeIdStatement{ 1224 "DELETE FROM enumerationDeclarations WHERE typeId=?", database}; 1225 WriteStatement deletePropertyDeclarationByTypeIdStatement{ 1226 "DELETE FROM propertyDeclarations WHERE typeId=?", database}; 1227 WriteStatement deleteFunctionDeclarationByTypeIdStatement{ 1228 "DELETE FROM functionDeclarations WHERE typeId=?", database}; 1229 WriteStatement deleteSignalDeclarationByTypeIdStatement{ 1230 "DELETE FROM signalDeclarations WHERE typeId=?", database}; 1231 WriteStatement deleteTypeStatement{"DELETE FROM types WHERE typeId=?", database}; 1232 mutable ReadStatement<3> selectPropertyDeclarationsByTypeIdStatement{ 1233 "SELECT name, (SELECT name FROM types WHERE typeId=propertyDeclarations.propertyTypeId)," 1234 "propertyTraits FROM propertyDeclarations WHERE typeId=?", 1235 database}; 1236 ReadStatement<4> selectPropertyDeclarationsForTypeIdStatement{ 1237 "SELECT name, propertyTraits, propertyTypeId, propertyDeclarationId FROM " 1238 "propertyDeclarations WHERE typeId=? AND aliasPropertyDeclarationId IS NULL ORDER BY " 1239 "name", 1240 database}; 1241 WriteStatement insertPropertyDeclarationStatement{ 1242 "INSERT INTO propertyDeclarations(typeId, name, propertyTypeId, propertyTraits) " 1243 "VALUES(?1, ?2, ?3, ?4)", 1244 database}; 1245 WriteStatement updatePropertyDeclarationStatement{ 1246 "UPDATE propertyDeclarations SET propertyTypeId=?2, propertyTraits=?3 WHERE " 1247 "propertyDeclarationId=?1 OR aliasPropertyDeclarationId=?1", 1248 database}; 1249 WriteStatement deletePropertyDeclarationStatement{ 1250 "DELETE FROM propertyDeclarations WHERE propertyDeclarationId=?", database}; 1251 ReadStatement<3> selectPropertyDeclarationsWithAliasForTypeIdStatement{ 1252 "SELECT name, propertyDeclarationId, aliasPropertyDeclarationId FROM propertyDeclarations " 1253 "WHERE typeId=? AND aliasPropertyDeclarationId IS NOT NULL ORDER BY name", 1254 database}; 1255 WriteStatement insertPropertyDeclarationWithAliasStatement{ 1256 "INSERT INTO propertyDeclarations(typeId, name, propertyTypeId, propertyTraits, " 1257 "aliasPropertyDeclarationId) VALUES(?1, ?2, ?3, ?4, ?5) ", 1258 database}; 1259 WriteStatement updatePropertyDeclarationWithAliasStatement{ 1260 "UPDATE propertyDeclarations SET propertyTypeId=?2, propertyTraits=?3, " 1261 "aliasPropertyDeclarationId=?4 WHERE propertyDeclarationId=?1", 1262 database}; 1263 mutable ReadStatement<4> selectFunctionDeclarationsForTypeIdStatement{ 1264 "SELECT name, returnTypeName, signature, functionDeclarationId FROM " 1265 "functionDeclarations WHERE typeId=? ORDER BY name", 1266 database}; 1267 mutable ReadStatement<3> selectFunctionDeclarationsForTypeIdWithoutSignatureStatement{ 1268 "SELECT name, returnTypeName, functionDeclarationId FROM " 1269 "functionDeclarations WHERE typeId=? ORDER BY name", 1270 database}; 1271 mutable ReadStatement<3> selectFunctionParameterDeclarationsStatement{ 1272 "SELECT json_extract(json_each.value, '$.n'), json_extract(json_each.value, '$.tn'), " 1273 "json_extract(json_each.value, '$.tr') FROM functionDeclarations, " 1274 "json_each(functionDeclarations.signature) WHERE functionDeclarationId=?", 1275 database}; 1276 WriteStatement insertFunctionDeclarationStatement{ 1277 "INSERT INTO functionDeclarations(typeId, name, returnTypeName, signature) VALUES(?1, ?2, " 1278 "?3, ?4)", 1279 database}; 1280 WriteStatement updateFunctionDeclarationStatement{ 1281 "UPDATE functionDeclarations SET returnTypeName=?2, signature=?3 WHERE " 1282 "functionDeclarationId=?1", 1283 database}; 1284 WriteStatement deleteFunctionDeclarationStatement{ 1285 "DELETE FROM functionDeclarations WHERE functionDeclarationId=?", database}; 1286 mutable ReadStatement<3> selectSignalDeclarationsForTypeIdStatement{ 1287 "SELECT name, signature, signalDeclarationId FROM signalDeclarations WHERE typeId=? ORDER " 1288 "BY name", 1289 database}; 1290 mutable ReadStatement<2> selectSignalDeclarationsForTypeIdWithoutSignatureStatement{ 1291 "SELECT name, signalDeclarationId FROM signalDeclarations WHERE typeId=? ORDER BY name", 1292 database}; 1293 mutable ReadStatement<3> selectSignalParameterDeclarationsStatement{ 1294 "SELECT json_extract(json_each.value, '$.n'), json_extract(json_each.value, '$.tn'), " 1295 "json_extract(json_each.value, '$.tr') FROM signalDeclarations, " 1296 "json_each(signalDeclarations.signature) WHERE signalDeclarationId=?", 1297 database}; 1298 WriteStatement insertSignalDeclarationStatement{ 1299 "INSERT INTO signalDeclarations(typeId, name, signature) VALUES(?1, ?2, ?3)", database}; 1300 WriteStatement updateSignalDeclarationStatement{ 1301 "UPDATE signalDeclarations SET signature=?2 WHERE signalDeclarationId=?1", database}; 1302 WriteStatement deleteSignalDeclarationStatement{ 1303 "DELETE FROM signalDeclarations WHERE signalDeclarationId=?", database}; 1304 mutable ReadStatement<3> selectEnumerationDeclarationsForTypeIdStatement{ 1305 "SELECT name, enumeratorDeclarations, enumerationDeclarationId FROM " 1306 "enumerationDeclarations WHERE typeId=? ORDER BY name", 1307 database}; 1308 mutable ReadStatement<2> selectEnumerationDeclarationsForTypeIdWithoutEnumeratorDeclarationsStatement{ 1309 "SELECT name, enumerationDeclarationId FROM enumerationDeclarations WHERE typeId=? ORDER " 1310 "BY name", 1311 database}; 1312 mutable ReadStatement<3> selectEnumeratorDeclarationStatement{ 1313 "SELECT json_each.key, json_each.value, json_each.type!='null' FROM " 1314 "enumerationDeclarations, json_each(enumerationDeclarations.enumeratorDeclarations) WHERE " 1315 "enumerationDeclarationId=?", 1316 database}; 1317 WriteStatement insertEnumerationDeclarationStatement{ 1318 "INSERT INTO enumerationDeclarations(typeId, name, enumeratorDeclarations) VALUES(?1, ?2, " 1319 "?3)", 1320 database}; 1321 WriteStatement updateEnumerationDeclarationStatement{ 1322 "UPDATE enumerationDeclarations SET enumeratorDeclarations=?2 WHERE " 1323 "enumerationDeclarationId=?1", 1324 database}; 1325 WriteStatement deleteEnumerationDeclarationStatement{ 1326 "DELETE FROM enumerationDeclarations WHERE enumerationDeclarationId=?", database}; 1327 mutable ReadWriteStatement<1> insertImportStatement{ 1328 "INSERT INTO imports(name, version, sourceId) VALUES(?1, ?2, ?3) RETURNING importId", 1329 database}; 1330 WriteStatement updateImportStatement{"UPDATE imports SET sourceId=?2 WHERE importId=?1", database}; 1331 WriteStatement deleteImportStatement{"DELETE FROM imports WHERE importId=?", database}; 1332 mutable ReadStatement<1> selectImportIdByNameStatement{ 1333 "SELECT importId FROM imports WHERE name=? ORDER BY version DESC LIMIT 1", database}; 1334 mutable ReadStatement<1> selectImportIdByNameAndVersionStatement{ 1335 "SELECT importId FROM imports WHERE name=? AND version=?", database}; 1336 mutable ReadStatement<4> selectAllImportsStatement{ 1337 "SELECT name, version, sourceId, importId FROM imports ORDER BY name, version", database}; 1338 WriteStatement insertImportDependencyStatement{ 1339 "INSERT INTO importDependencies(importId, parentImportId) VALUES(?1, ?2)", database}; 1340 WriteStatement deleteImportDependencyStatement{ 1341 "DELETE FROM importDependencies WHERE importId=?1 AND parentImportId=?2", database}; 1342 mutable ReadStatement<2> selectAllImportDependenciesStatement{ 1343 "SELECT importId, parentImportId FROM importDependencies ORDER BY importId, parentImportId", 1344 database}; 1345 mutable ReadStatement<2> selectImportsForThatDependentOnThisImportIdStatement{ 1346 "SELECT name, version FROM importDependencies JOIN imports ON " 1347 "importDependencies.parentImportId = imports.importId WHERE importDependencies.importId=?", 1348 database}; 1349 mutable ReadStatement<1> selectTypeIdsForImportIdStatement{ 1350 "SELECT typeId FROM types WHERE importId=?", database}; 1351 mutable ReadStatement<1> selectTypeIdByImportIdAndNameStatement{ 1352 "SELECT typeId FROM types WHERE importId=?1 and name=?2", database}; 1353 mutable ReadStatement<1> selectTypeIdByImportIdsAndExportedNameStatement{ 1354 "SELECT typeId FROM exportedTypes WHERE importId IN carray(?1, ?2, 'int64') AND name=?3", 1355 database}; 1356 mutable ReadStatement<1> selectTypeIdByImportIdAndExportedNameStatement{ 1357 "SELECT typeId FROM exportedTypes WHERE importId=?1 AND name=?2", database}; 1358 mutable ReadStatement<1> fetchImportDependencyIdsStatement{ 1359 "WITH RECURSIVE " 1360 " importIds(importId) AS (" 1361 " SELECT value FROM carray(?1, ?2, 'int64') " 1362 " UNION " 1363 " SELECT parentImportId FROM importDependencies JOIN importIds USING(importId)) " 1364 "SELECT importId FROM importIds", 1365 database}; 1366 }; 1367 1368 } // namespace QmlDesigner 1369