File indexing completed on 2024-05-19 05:42:09
0001 // ct_lvtldr_sociutils.h -*-C++-*- 0002 0003 /* 0004 // Copyright 2023 Codethink Ltd <codethink@codethink.co.uk> 0005 // SPDX-License-Identifier: Apache-2.0 0006 // 0007 // Licensed under the Apache License, Version 2.0 (the "License"); 0008 // you may not use this file except in compliance with the License. 0009 // You may obtain a copy of the License at 0010 // 0011 // http://www.apache.org/licenses/LICENSE-2.0 0012 // 0013 // Unless required by applicable law or agreed to in writing, software 0014 // distributed under the License is distributed on an "AS IS" BASIS, 0015 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 0016 // See the License for the specific language governing permissions and 0017 // limitations under the License. 0018 */ 0019 0020 #ifndef DIAGRAM_SERVER_CT_LVTLDR_SOCIUTILS_H 0021 #define DIAGRAM_SERVER_CT_LVTLDR_SOCIUTILS_H 0022 0023 #include <ct_lvtldr_componentnodefields.h> 0024 #include <ct_lvtldr_databasehandler.h> 0025 #include <ct_lvtshr_uniqueid.h> 0026 0027 #include <soci/soci.h> 0028 #include <soci/sqlite3/soci-sqlite3.h> 0029 0030 #include <QString> 0031 0032 #include <iostream> 0033 #include <variant> 0034 0035 namespace { 0036 template<typename T> 0037 std::string optionalToDb(std::optional<T> data) 0038 { 0039 if (!data) { 0040 return "NULL"; 0041 } 0042 return std::to_string(*data); 0043 } 0044 } // namespace 0045 0046 namespace Codethink::lvtldr { 0047 0048 class SociDatabaseHandler : public DatabaseHandler { 0049 using RecordNumberType = Codethink::lvtshr::UniqueId::RecordNumberType; 0050 0051 public: 0052 explicit SociDatabaseHandler(std::string const& path) 0053 { 0054 d_db.open(*soci::factory_sqlite3(), path); 0055 } 0056 0057 void close() override 0058 { 0059 d_db.close(); 0060 } 0061 0062 std::vector<lvtshr::UniqueId> getTopLevelEntityIds() override 0063 { 0064 auto out = std::vector<lvtshr::UniqueId>{}; 0065 { 0066 soci::rowset<RecordNumberType> rs = (d_db.prepare << "select id from source_repository where name != ''"); 0067 for (auto&& i : rs) { 0068 out.emplace_back(lvtshr::UniqueId{lvtshr::DiagramType::RepositoryType, i}); 0069 } 0070 } 0071 { 0072 soci::rowset<RecordNumberType> rs = 0073 (d_db.prepare 0074 << "select id from source_package where parent_id is NULL and source_repository_id is NULL"); 0075 for (auto&& i : rs) { 0076 out.emplace_back(lvtshr::UniqueId{lvtshr::DiagramType::PackageType, i}); 0077 } 0078 } 0079 return out; 0080 } 0081 0082 RepositoryNodeFields getRepositoryFieldsByQualifiedName(std::string const& qualifiedName) override 0083 { 0084 return getRepositoryFields("qualified_name", qualifiedName); 0085 } 0086 0087 RepositoryNodeFields getRepositoryFieldsById(RecordNumberType id) override 0088 { 0089 return getRepositoryFields("id", id); 0090 } 0091 0092 void updateFields(RepositoryNodeFields const& dao) override 0093 { 0094 } 0095 0096 TypeNodeFields getUdtFieldsByQualifiedName(std::string const& qualifiedName) override 0097 { 0098 return getUdtFields("qualified_name", qualifiedName); 0099 } 0100 0101 TypeNodeFields getUdtFieldsById(RecordNumberType id) override 0102 { 0103 return getUdtFields("id", id); 0104 } 0105 0106 void addFields(TypeNodeFields& dao) override 0107 { 0108 soci::transaction tr(d_db); 0109 d_db << "insert into class_declaration (version, qualified_name, name, kind, access, class_namespace_id, " 0110 "parent_package_id) " 0111 "values " 0112 << "(" << dao.version << ", " 0113 << "'" << dao.qualifiedName << "', " 0114 << "'" << dao.name << "', " 0115 << "" << static_cast<int>(dao.kind) << ", " 0116 << "" << dao.access << ", " 0117 << "" << optionalToDb(dao.classNamespaceId) << ", " 0118 << "" << optionalToDb(dao.parentPackageId) << "" 0119 << ")"; 0120 0121 d_db.get_last_insert_id("class_declaration", dao.id); 0122 0123 for (auto&& id : dao.componentIds) { 0124 d_db << "insert into udt_component (component_id, udt_id) values " 0125 << "(" << id << ", " << dao.id << ")"; 0126 } 0127 tr.commit(); 0128 } 0129 0130 void updateFields(TypeNodeFields const& dao) override 0131 { 0132 soci::transaction tr(d_db); 0133 d_db << "update class_declaration set " 0134 << "version = " << dao.version << ", " 0135 << "name = '" << dao.name << "', " 0136 << "qualified_name = '" << dao.qualifiedName << "', " 0137 << "kind = " << static_cast<int>(dao.kind) << ", " 0138 << "access = " << dao.access << ", " 0139 << "class_namespace_id = " << optionalToDb(dao.classNamespaceId) << " " 0140 << "where id = :k", 0141 soci::use(dao.id); 0142 tr.commit(); 0143 } 0144 0145 void removeUdtFieldsById(RecordNumberType id) override 0146 { 0147 soci::transaction tr(d_db); 0148 d_db << "delete from class_declaration where id = " << id; 0149 tr.commit(); 0150 } 0151 0152 ComponentNodeFields getComponentFieldsByQualifiedName(std::string const& qualifiedName) override 0153 { 0154 return getComponentFields("qualified_name", qualifiedName); 0155 } 0156 0157 ComponentNodeFields getComponentFieldsById(RecordNumberType id) override 0158 { 0159 return getComponentFields("id", id); 0160 } 0161 0162 void addFields(ComponentNodeFields& dao) override 0163 { 0164 soci::transaction tr(d_db); 0165 d_db << "insert into source_component (version, qualified_name, name, package_id) " 0166 "values " 0167 << "(" << dao.version << ", " 0168 << "'" << dao.qualifiedName << "', " 0169 << "'" << dao.name << "', " 0170 << "" << optionalToDb(dao.packageId) << "" 0171 << ")"; 0172 d_db.get_last_insert_id("source_component", dao.id); 0173 tr.commit(); 0174 } 0175 0176 void updateFields(ComponentNodeFields const& dao) override 0177 { 0178 soci::transaction tr(d_db); 0179 d_db << "update source_component set " 0180 << "version = " << dao.version << ", " 0181 << "qualified_name = '" << dao.qualifiedName << "', " 0182 << "name = '" << dao.name << "', " 0183 << "package_id = " << optionalToDb(dao.packageId) << " " 0184 << "where id = :k", 0185 soci::use(dao.id); 0186 tr.commit(); 0187 } 0188 0189 void removeComponentFieldsById(RecordNumberType id) override 0190 { 0191 soci::transaction tr(d_db); 0192 d_db << "delete from source_component where id = " << id; 0193 tr.commit(); 0194 } 0195 0196 PackageNodeFields getPackageFieldsByQualifiedName(std::string const& qualifiedName) override 0197 { 0198 return getPackageFields("qualified_name", qualifiedName); 0199 } 0200 0201 PackageNodeFields getPackageFieldsById(RecordNumberType id) override 0202 { 0203 return getPackageFields("id", id); 0204 } 0205 0206 void updateFields(FreeFunctionNodeFields const& dao) override 0207 { 0208 // Intentionally not implemented 0209 } 0210 0211 FreeFunctionNodeFields getFreeFunctionFieldsByQualifiedName(std::string const& qualifiedName) override 0212 { 0213 return getFreeFunctionFields("qualified_name", qualifiedName); 0214 } 0215 0216 FreeFunctionNodeFields getFreeFunctionFieldsById(RecordNumberType id) override 0217 { 0218 return getFreeFunctionFields("id", id); 0219 } 0220 0221 void addFields(PackageNodeFields& dao) override 0222 { 0223 soci::transaction tr(d_db); 0224 d_db 0225 << "insert into source_package (version, qualified_name, name, disk_path, parent_id, source_repository_id) " 0226 "values " 0227 << "(" << dao.version << ", " 0228 << "'" << dao.qualifiedName << "', " 0229 << "'" << dao.name << "', " 0230 << "'" << dao.diskPath << "', " 0231 << "" << optionalToDb(dao.parentId) << ", " 0232 << "" << optionalToDb(dao.sourceRepositoryId) << " " 0233 << ")"; 0234 d_db.get_last_insert_id("source_package", dao.id); 0235 tr.commit(); 0236 } 0237 0238 void updateFields(PackageNodeFields const& dao) override 0239 { 0240 soci::transaction tr(d_db); 0241 d_db << "update source_package set " 0242 << "version = " << dao.version << ", " 0243 << "parent_id = " << optionalToDb(dao.parentId) << ", " 0244 << "source_repository_id = " << optionalToDb(dao.sourceRepositoryId) << ", " 0245 << "name = '" << dao.name << "', " 0246 << "qualified_name = '" << dao.qualifiedName << "', " 0247 << "disk_path = '" << dao.diskPath << "' " 0248 << "where id = :k", 0249 soci::use(dao.id); 0250 tr.commit(); 0251 } 0252 0253 void removePackageFieldsById(RecordNumberType id) override 0254 { 0255 soci::transaction tr(d_db); 0256 d_db << "delete from source_package where id = " << id; 0257 d_db << "delete from cad_notes where entity_id = " << id 0258 << " and entity_type = " << static_cast<int>(lvtshr::DiagramType::PackageType); 0259 tr.commit(); 0260 } 0261 0262 void addConcreteDependency(RecordNumberType idFrom, RecordNumberType idTo) override 0263 { 0264 soci::transaction tr(d_db); 0265 d_db << "insert into dependencies (source_id, target_id) values (" << idFrom << ", " << idTo << ")"; 0266 tr.commit(); 0267 } 0268 0269 void removeConcreteDependency(RecordNumberType idFrom, RecordNumberType idTo) override 0270 { 0271 soci::transaction tr(d_db); 0272 d_db << "delete from dependencies where source_id = " << idFrom << " and target_id = " << idTo; 0273 tr.commit(); 0274 } 0275 0276 void addComponentDependency(RecordNumberType idFrom, RecordNumberType idTo) override 0277 { 0278 soci::transaction tr(d_db); 0279 d_db << "insert into component_relation (source_id, target_id) values (" << idFrom << ", " << idTo << ")"; 0280 tr.commit(); 0281 } 0282 0283 void removeComponentDependency(RecordNumberType idFrom, RecordNumberType idTo) override 0284 { 0285 soci::transaction tr(d_db); 0286 d_db << "delete from component_relation where source_id = " << idFrom << " and target_id = " << idTo; 0287 tr.commit(); 0288 } 0289 0290 void addClassHierarchy(RecordNumberType idFrom, RecordNumberType idTo) override 0291 { 0292 soci::transaction tr(d_db); 0293 d_db << "insert into class_hierarchy (source_id, target_id) values (" << idFrom << ", " << idTo << ")"; 0294 tr.commit(); 0295 } 0296 0297 void removeClassHierarchy(RecordNumberType idFrom, RecordNumberType idTo) override 0298 { 0299 soci::transaction tr(d_db); 0300 d_db << "delete from class_hierarchy where source_id = " << idFrom << " and target_id = " << idTo; 0301 tr.commit(); 0302 } 0303 0304 void addImplementationRelationship(RecordNumberType idFrom, RecordNumberType idTo) override 0305 { 0306 soci::transaction tr(d_db); 0307 d_db << "insert into uses_in_the_implementation (source_id, target_id) values (" << idFrom << ", " << idTo 0308 << ")"; 0309 tr.commit(); 0310 } 0311 0312 void removeImplementationRelationship(RecordNumberType idFrom, RecordNumberType idTo) override 0313 { 0314 soci::transaction tr(d_db); 0315 d_db << "delete from uses_in_the_implementation where source_id = " << idFrom << " and target_id = " << idTo; 0316 tr.commit(); 0317 } 0318 0319 void addInterfaceRelationship(RecordNumberType idFrom, RecordNumberType idTo) override 0320 { 0321 soci::transaction tr(d_db); 0322 d_db << "insert into uses_in_the_interface (source_id, target_id) values (" << idFrom << ", " << idTo << ")"; 0323 tr.commit(); 0324 } 0325 0326 void removeInterfaceRelationship(RecordNumberType idFrom, RecordNumberType idTo) override 0327 { 0328 soci::transaction tr(d_db); 0329 d_db << "delete from uses_in_the_interface where source_id = " << idFrom << " and target_id = " << idTo; 0330 tr.commit(); 0331 } 0332 0333 std::string getNotesFromId(lvtshr::UniqueId uid) override 0334 { 0335 try { 0336 std::string notes; 0337 soci::transaction tr(d_db); 0338 d_db << "select notes from cad_notes where entity_id = " << uid.recordNumber() 0339 << " and entity_type = " << static_cast<int>(uid.diagramType()), 0340 soci::into(notes); 0341 tr.commit(); 0342 return notes; 0343 } catch (...) { 0344 return ""; 0345 } 0346 } 0347 0348 bool hasNotes(lvtshr::UniqueId uid) override 0349 { 0350 try { 0351 int n; 0352 soci::transaction tr(d_db); 0353 d_db << "select count(*) from cad_notes where entity_id = " << uid.recordNumber() 0354 << " and entity_type = " << static_cast<int>(uid.diagramType()), 0355 soci::into(n); 0356 tr.commit(); 0357 return n > 0; 0358 } catch (...) { 0359 return false; 0360 } 0361 } 0362 0363 void addNotes(lvtshr::UniqueId uid, std::string const& notes) override 0364 { 0365 std::string our_notes = QString::fromStdString(notes).replace("'", "''").toStdString(); 0366 soci::transaction tr(d_db); 0367 d_db << "insert into cad_notes (version, entity_id, entity_type, notes) values (" << 0 << ", " 0368 << uid.recordNumber() << ", " << static_cast<int>(uid.diagramType()) << ", " 0369 << "'" << our_notes << "')"; 0370 tr.commit(); 0371 } 0372 0373 void setNotes(lvtshr::UniqueId uid, std::string const& notes) override 0374 { 0375 std::string our_notes = QString::fromStdString(notes).replace("'", "''").toStdString(); 0376 soci::transaction tr(d_db); 0377 d_db << "update cad_notes set notes = '" << our_notes << "' where " 0378 << "entity_id = " << uid.recordNumber() << " and " 0379 << "entity_type = " << static_cast<int>(uid.diagramType()); 0380 tr.commit(); 0381 } 0382 0383 soci::session& getSession() 0384 { 0385 return d_db; 0386 } 0387 0388 private: 0389 template<typename T> 0390 RepositoryNodeFields getRepositoryFields(std::string const& uniqueKeyColumnName, T const& keyValue) 0391 { 0392 decltype(getRepositoryFields(uniqueKeyColumnName, keyValue)) dao; 0393 d_db << "select * from source_repository where " + uniqueKeyColumnName + " = :k", soci::into(dao.id), 0394 soci::into(dao.version), soci::into(dao.name), soci::into(dao.qualifiedName), soci::into(dao.diskPath), 0395 soci::use(keyValue); 0396 0397 { 0398 soci::rowset<RecordNumberType> rs = 0399 (d_db.prepare << "select id from source_package where source_repository_id = :k and parent_id is NULL", 0400 soci::use(dao.id)); 0401 for (auto&& i : rs) { 0402 dao.childPackagesIds.emplace_back(i); 0403 } 0404 } 0405 0406 return dao; 0407 } 0408 0409 template<typename T> 0410 TypeNodeFields getUdtFields(std::string const& uniqueKeyColumnName, T const& keyValue) 0411 { 0412 decltype(getUdtFields(uniqueKeyColumnName, keyValue)) dao; 0413 soci::indicator parentNamespaceIdIndicator = soci::indicator::i_null; 0414 typename std::remove_reference<decltype(dao.parentNamespaceId.value())>::type maybeParentNamespaceId = 0; 0415 soci::indicator classNamespaceIdIndicator = soci::indicator::i_null; 0416 typename std::remove_reference<decltype(dao.classNamespaceId.value())>::type maybeClassNamespaceId = 0; 0417 soci::indicator parentPackageIdIndicator = soci::indicator::i_null; 0418 typename std::remove_reference<decltype(dao.parentPackageId.value())>::type maybeParentPackageId = 0; 0419 0420 int kindAsInt = -1; 0421 0422 d_db << "select * from class_declaration where " + uniqueKeyColumnName + " = :k", soci::into(dao.id), 0423 soci::into(dao.version), soci::into(maybeParentNamespaceId, parentNamespaceIdIndicator), 0424 soci::into(maybeClassNamespaceId, classNamespaceIdIndicator), 0425 soci::into(maybeParentPackageId, parentPackageIdIndicator), soci::into(dao.name), 0426 soci::into(dao.qualifiedName), soci::into(kindAsInt), soci::into(dao.access), soci::use(keyValue); 0427 0428 dao.kind = static_cast<lvtshr::UDTKind>(kindAsInt); 0429 0430 if (parentNamespaceIdIndicator == soci::indicator::i_ok) { 0431 dao.parentNamespaceId = maybeParentNamespaceId; 0432 } else { 0433 dao.parentNamespaceId = std::nullopt; 0434 } 0435 0436 if (classNamespaceIdIndicator == soci::indicator::i_ok) { 0437 dao.classNamespaceId = maybeClassNamespaceId; 0438 } else { 0439 dao.classNamespaceId = std::nullopt; 0440 } 0441 0442 if (parentPackageIdIndicator == soci::indicator::i_ok) { 0443 dao.parentPackageId = maybeParentPackageId; 0444 } else { 0445 dao.parentPackageId = std::nullopt; 0446 } 0447 0448 { 0449 soci::rowset<RecordNumberType> rs = 0450 (d_db.prepare << "select component_id from udt_component where udt_id = :k", soci::use(dao.id)); 0451 for (auto&& i : rs) { 0452 dao.componentIds.emplace_back(i); 0453 } 0454 } 0455 { 0456 soci::rowset<RecordNumberType> rs = 0457 (d_db.prepare << "select id from class_declaration where class_namespace_id = :k", soci::use(dao.id)); 0458 for (auto&& i : rs) { 0459 dao.nestedTypeIds.emplace_back(i); 0460 } 0461 } 0462 { 0463 soci::rowset<RecordNumberType> rs = 0464 (d_db.prepare << "select source_id from class_hierarchy where target_id = :k", soci::use(dao.id)); 0465 for (auto&& i : rs) { 0466 dao.isAIds.emplace_back(i); 0467 } 0468 } 0469 { 0470 soci::rowset<RecordNumberType> rs = 0471 (d_db.prepare << "select target_id from uses_in_the_interface where source_id = :k", soci::use(dao.id)); 0472 for (auto&& i : rs) { 0473 dao.usesInInterfaceIds.emplace_back(i); 0474 } 0475 } 0476 { 0477 soci::rowset<RecordNumberType> rs = 0478 (d_db.prepare << "select target_id from uses_in_the_implementation where source_id = :k", 0479 soci::use(dao.id)); 0480 for (auto&& i : rs) { 0481 dao.usesInImplementationIds.emplace_back(i); 0482 } 0483 } 0484 0485 { 0486 soci::rowset<RecordNumberType> rs = 0487 (d_db.prepare << "select target_id from class_hierarchy where source_id = :k", soci::use(dao.id)); 0488 for (auto&& i : rs) { 0489 dao.isBaseOfIds.emplace_back(i); 0490 } 0491 } 0492 { 0493 soci::rowset<RecordNumberType> rs = 0494 (d_db.prepare << "select source_id from uses_in_the_interface where target_id = :k", soci::use(dao.id)); 0495 for (auto&& i : rs) { 0496 dao.usedByInterfaceIds.emplace_back(i); 0497 } 0498 } 0499 { 0500 soci::rowset<RecordNumberType> rs = 0501 (d_db.prepare << "select source_id from uses_in_the_implementation where target_id = :k", 0502 soci::use(dao.id)); 0503 for (auto&& i : rs) { 0504 dao.usedByImplementationIds.emplace_back(i); 0505 } 0506 } 0507 0508 { 0509 soci::rowset<RecordNumberType> rs = 0510 (d_db.prepare << "select id from field_declaration where class_id = :k", soci::use(dao.id)); 0511 for (auto&& i : rs) { 0512 dao.fieldIds.emplace_back(i); 0513 } 0514 } 0515 0516 { 0517 soci::rowset<std::string> rs = 0518 (d_db.prepare << "select name from field_declaration where class_id = :k", soci::use(dao.id)); 0519 for (auto&& i : rs) { 0520 dao.fieldNames.emplace_back(i); 0521 } 0522 } 0523 0524 return dao; 0525 } 0526 0527 template<typename T> 0528 ComponentNodeFields getComponentFields(std::string const& uniqueKeyColumnName, T const& keyValue) 0529 { 0530 decltype(getComponentFields(uniqueKeyColumnName, keyValue)) dao; 0531 soci::indicator parentIdIndicator = soci::indicator::i_null; 0532 typename std::remove_reference<decltype(dao.packageId.value())>::type maybeParentId = 0; 0533 d_db << "select * from source_component where " + uniqueKeyColumnName + " = :k", soci::into(dao.id), 0534 soci::into(dao.version), soci::into(dao.qualifiedName), soci::into(dao.name), 0535 soci::into(maybeParentId, parentIdIndicator), soci::use(keyValue); 0536 0537 if (parentIdIndicator == soci::indicator::i_ok) { 0538 dao.packageId = maybeParentId; 0539 } else { 0540 dao.packageId = std::nullopt; 0541 } 0542 0543 { 0544 soci::rowset<RecordNumberType> rs = 0545 (d_db.prepare << "select target_id from component_relation where source_id = :k", soci::use(dao.id)); 0546 for (auto&& i : rs) { 0547 dao.providerIds.emplace_back(i); 0548 } 0549 } 0550 { 0551 soci::rowset<RecordNumberType> rs = 0552 (d_db.prepare << "select source_id from component_relation where target_id = :k", soci::use(dao.id)); 0553 for (auto&& i : rs) { 0554 dao.clientIds.emplace_back(i); 0555 } 0556 } 0557 { 0558 soci::rowset<RecordNumberType> rs = 0559 (d_db.prepare << "select udt_id from udt_component where component_id = :k", soci::use(dao.id)); 0560 for (auto&& i : rs) { 0561 dao.childUdtIds.emplace_back(i); 0562 } 0563 } 0564 try { 0565 soci::rowset<RecordNumberType> files_rs = 0566 (d_db.prepare << "select id from source_file where component_id = :k", soci::use(dao.id)); 0567 for (auto const& source_id : files_rs) { 0568 soci::rowset<RecordNumberType> rs = 0569 (d_db.prepare << "select function_id from global_function_source_file where source_file_id = :k", 0570 soci::use(source_id)); 0571 for (auto const& i : rs) { 0572 dao.childGlobalFunctionIds.emplace_back(i); 0573 } 0574 } 0575 } catch (soci::sqlite3_soci_error const&) { 0576 /* Ignore missing data on old databases */ 0577 } 0578 0579 return dao; 0580 } 0581 0582 template<typename T> 0583 PackageNodeFields getPackageFields(std::string const& uniqueKeyColumnName, T const& keyValue) 0584 { 0585 decltype(getPackageFields(uniqueKeyColumnName, keyValue)) dao; 0586 soci::indicator parentIdIndicator = soci::indicator::i_null; 0587 typename std::remove_reference<decltype(dao.parentId.value())>::type maybeParentId = 0; 0588 soci::indicator sourceRepositoryIdIndicator = soci::indicator::i_null; 0589 typename std::remove_reference<decltype(dao.sourceRepositoryId.value())>::type maybeSourceRepositoryId = 0; 0590 d_db << "select * from source_package where " + uniqueKeyColumnName + " = :k", soci::into(dao.id), 0591 soci::into(dao.version), soci::into(maybeParentId, parentIdIndicator), 0592 soci::into(maybeSourceRepositoryId, sourceRepositoryIdIndicator), soci::into(dao.name), 0593 soci::into(dao.qualifiedName), soci::use(keyValue); 0594 0595 if (parentIdIndicator == soci::indicator::i_ok) { 0596 dao.parentId = maybeParentId; 0597 } else { 0598 dao.parentId = std::nullopt; 0599 } 0600 0601 if (sourceRepositoryIdIndicator == soci::indicator::i_ok) { 0602 dao.sourceRepositoryId = maybeSourceRepositoryId; 0603 } else { 0604 dao.sourceRepositoryId = std::nullopt; 0605 } 0606 0607 { 0608 soci::rowset<RecordNumberType> rs = 0609 (d_db.prepare << "select id from source_package where parent_id = :k", soci::use(dao.id)); 0610 for (auto&& i : rs) { 0611 dao.childPackagesIds.emplace_back(i); 0612 } 0613 } 0614 { 0615 soci::rowset<RecordNumberType> rs = 0616 (d_db.prepare << "select id from source_component where package_id = :k", soci::use(dao.id)); 0617 for (auto&& i : rs) { 0618 dao.childComponentsIds.emplace_back(i); 0619 } 0620 } 0621 { 0622 soci::rowset<RecordNumberType> rs = 0623 (d_db.prepare << "select target_id from dependencies where source_id = :k", soci::use(dao.id)); 0624 for (auto&& i : rs) { 0625 dao.providerIds.emplace_back(i); 0626 } 0627 } 0628 { 0629 soci::rowset<RecordNumberType> rs = 0630 (d_db.prepare << "select source_id from dependencies where target_id = :k", soci::use(dao.id)); 0631 for (auto&& i : rs) { 0632 dao.clientIds.emplace_back(i); 0633 } 0634 } 0635 0636 return dao; 0637 } 0638 0639 template<typename T> 0640 FreeFunctionNodeFields getFreeFunctionFields(std::string const& uniqueKeyColumnName, T const& keyValue) 0641 { 0642 decltype(getFreeFunctionFields(uniqueKeyColumnName, keyValue)) dao; 0643 d_db << "select id, version, name, qualified_name from function_declaration where " + uniqueKeyColumnName 0644 + " = :k limit 1", 0645 soci::into(dao.id), soci::into(dao.version), soci::into(dao.name), soci::into(dao.qualifiedName), 0646 soci::use(keyValue); 0647 0648 { 0649 auto source_id = -1; 0650 d_db << "select source_file_id from global_function_source_file where function_id = :k limit 1", 0651 soci::into(source_id), soci::use(dao.id); 0652 0653 auto component_id = -1; 0654 d_db << "select component_id from source_file where id = :k limit 1", soci::into(component_id), 0655 soci::use(source_id); 0656 dao.componentId = component_id; 0657 } 0658 0659 { 0660 soci::rowset<RecordNumberType> rs = 0661 (d_db.prepare << "select callee_id from function_calls where caller_id = :k", soci::use(dao.id)); 0662 for (auto&& i : rs) { 0663 dao.calleeIds.emplace_back(i); 0664 } 0665 } 0666 0667 { 0668 soci::rowset<RecordNumberType> rs = 0669 (d_db.prepare << "select caller_id from function_calls where callee_id = :k", soci::use(dao.id)); 0670 for (auto&& i : rs) { 0671 dao.callerIds.emplace_back(i); 0672 } 0673 } 0674 0675 return dao; 0676 } 0677 0678 soci::session d_db; 0679 }; 0680 0681 } // namespace Codethink::lvtldr 0682 0683 #endif // DIAGRAM_SERVER_CT_LVTLDR_SOCIUTILS_H