QmlDesigner: Add importId to types

If we now try to synchrize to an inconsistent type model we get an
exception.

Task-number: QDS-4458
Change-Id: I86f7ce90d14b18227a66314fb341f5b528bdfb95
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Marco Bubke
2021-06-03 13:06:23 +02:00
parent fc0668882d
commit f32207c930
5 changed files with 565 additions and 827 deletions

View File

@@ -67,9 +67,12 @@ public:
if (!type.sourceId)
throw TypeHasInvalidSourceId{};
updatedTypeIds.push_back(syncType(type));
updatedTypeIds.push_back(declareType(type));
}
for (auto &&type : types)
syncType(type);
deleteNotUpdatedTypes(updatedTypeIds, sourceIds);
transaction.commit();
@@ -85,27 +88,18 @@ public:
transaction.commit();
}
TypeId upsertType(Utils::SmallStringView name,
TypeId prototypeId,
Storage::TypeAccessSemantics accessSemantics,
const Storage::ExportedTypes &exportedTypes)
ImportIds fetchImportIds(const Storage::Imports &imports)
{
Sqlite::ImmediateTransaction transaction{database};
ImportIds importIds;
auto typeId = upsertTypeStatement.template value<TypeId>(name,
static_cast<int>(accessSemantics),
&prototypeId);
Sqlite::DeferredTransaction transaction{database};
for (auto &&exportedType : exportedTypes) {
upsertExportedTypesStatement.write(exportedType.qualifiedTypeName,
exportedType.version.major.version,
exportedType.version.minor.version,
&typeId);
}
for (auto &&import : imports)
importIds.push_back(fetchImportId(import));
transaction.commit();
return typeId;
return importIds;
}
PropertyDeclarationId upsertPropertyDeclaration(TypeId typeId,
@@ -344,6 +338,7 @@ private:
auto remove = [&](const Storage::ImportView &importView) {
deleteImportStatement.write(&importView.importId);
deleteTypesForImportId(importView.importId);
};
Sqlite::insertUpdateDelete(range, imports, compareKey, insert, update, remove);
@@ -408,6 +403,16 @@ private:
return selectImportIdByNameStatement.template value<ImportId>(import.name);
}
void deleteType(TypeId typeId)
{
deleteExportTypesByTypeIdStatement.write(&typeId);
deleteEnumerationDeclarationByTypeIdStatement.write(&typeId);
deletePropertyDeclarationByTypeIdStatement.write(&typeId);
deleteFunctionDeclarationByTypeIdStatement.write(&typeId);
deleteSignalDeclarationByTypeIdStatement.write(&typeId);
deleteTypeStatement.write(&typeId);
}
void deleteNotUpdatedTypes(const TypeIds &updatedTypeIds, const SourceIds &sourceIds)
{
auto updatedTypeIdValues = Utils::transform<std::vector>(updatedTypeIds, [](TypeId typeId) {
@@ -418,17 +423,24 @@ private:
return &sourceId;
});
auto removedTypeIds = selectNotUpdatedTypesInSourcesStatement.template range<TypeId>(
Utils::span(sourceIdValues), Utils::span(updatedTypeIdValues));
auto callback = [&](long long typeId) {
deleteType(TypeId{typeId});
return Sqlite::CallbackControl::Continue;
};
for (TypeId typeId : removedTypeIds) {
resetTypeStatement.write(&typeId);
deleteExportTypesByTypeIdStatement.write(&typeId);
deleteEnumerationDeclarationByTypeIdStatement.write(&typeId);
deletePropertyDeclarationByTypeIdStatement.write(&typeId);
deleteFunctionDeclarationByTypeIdStatement.write(&typeId);
deleteSignalDeclarationByTypeIdStatement.write(&typeId);
}
selectNotUpdatedTypesInSourcesStatement.readCallback(callback,
Utils::span(sourceIdValues),
Utils::span(updatedTypeIdValues));
}
void deleteTypesForImportId(ImportId importId)
{
auto callback = [&](long long typeId) {
deleteType(TypeId{typeId});
return Sqlite::CallbackControl::Continue;
};
selectTypeIdsForImportIdStatement.readCallback(callback, &importId);
}
void upsertExportedType(Utils::SmallStringView qualifiedName, Storage::Version version, TypeId typeId)
@@ -654,14 +666,23 @@ private:
Sqlite::insertUpdateDelete(range, enumerationDeclarations, compareKey, insert, update, remove);
}
TypeId syncType(Storage::Type &type)
TypeId declareType(Storage::Type &type)
{
type.typeId = upsertTypeStatement.template value<TypeId>(&type.importId,
type.typeName,
static_cast<int>(type.accessSemantics),
&type.sourceId);
return type.typeId;
}
void syncType(Storage::Type &type)
{
auto typeId = type.typeId;
auto prototypeId = fetchTypeIdByName(type.prototype);
auto typeId = upsertTypeStatement.template value<TypeId>(type.typeName,
static_cast<int>(type.accessSemantics),
&prototypeId,
&type.sourceId);
updatePrototypeStatement.write(&typeId, &prototypeId);
for (const auto &exportedType : type.exportedTypes)
upsertExportedType(exportedType.qualifiedTypeName, exportedType.version, typeId);
@@ -670,8 +691,6 @@ private:
synchronizeFunctionDeclarations(typeId, type.functionDeclarations);
synchronizeSignalDeclarations(typeId, type.signalDeclarations);
synchronizeEnumerationDeclarations(typeId, type.enumerationDeclarations);
return typeId;
}
TypeId fetchTypeIdByName(Utils::SmallStringView name)
@@ -679,12 +698,7 @@ private:
if (name.isEmpty())
return TypeId{};
auto typeId = selectTypeIdByNameStatement.template value<TypeId>(name);
if (!typeId)
return insertTypeStatement.template value<TypeId>(name);
return typeId;
return selectTypeIdByNameStatement.template value<TypeId>(name);
}
SourceContextId readSourceContextId(Utils::SmallStringView sourceContextPath)
@@ -794,9 +808,8 @@ private:
createImportDependeciesTable(database);
createSourceContextsTable(database);
createSourcesTable(database);
createTypesTable(database);
createTypesAndePropertyDeclarationsTables(database);
createExportedTypesTable(database);
createPropertyDeclarationsTable(database);
createEnumerationsTable(database);
createFunctionsTable(database);
createSignalsTable(database);
@@ -840,44 +853,46 @@ private:
table.initialize(database);
}
void createTypesTable(Database &database)
void createTypesAndePropertyDeclarationsTables(Database &database)
{
Sqlite::Table table;
table.setUseIfNotExists(true);
table.setName("types");
auto &typeIdColumn = table.addColumn("typeId",
Sqlite::ColumnType::Integer,
{Sqlite::PrimaryKey{}});
auto &nameColumn = table.addColumn("name");
table.addColumn("accessSemantics");
table.addColumn("sourceId");
table.addForeignKeyColumn("prototypeId",
typeIdColumn,
Sqlite::ForeignKeyAction::Restrict,
Sqlite::ForeignKeyAction::Restrict,
Sqlite::Enforment::Deferred);
Sqlite::Table typesTable;
typesTable.setUseIfNotExists(true);
typesTable.setName("types");
typesTable.addColumn("typeId", Sqlite::ColumnType::Integer, {Sqlite::PrimaryKey{}});
auto &importIdColumn = typesTable.addColumn("importId");
auto &typesNameColumn = typesTable.addColumn("name");
typesTable.addColumn("accessSemantics");
typesTable.addColumn("sourceId");
typesTable.addForeignKeyColumn("prototypeId",
typesTable,
Sqlite::ForeignKeyAction::NoAction,
Sqlite::ForeignKeyAction::Restrict,
Sqlite::Enforment::Deferred);
table.addUniqueIndex({nameColumn});
typesTable.addUniqueIndex({importIdColumn, typesNameColumn});
table.initialize(database);
}
typesTable.initialize(database);
void createPropertyDeclarationsTable(Database &database)
{
Sqlite::Table table;
table.setUseIfNotExists(true);
table.setName("propertyDeclarations");
table.addColumn("propertyDeclarationId",
Sqlite::ColumnType::Integer,
{Sqlite::PrimaryKey{}});
auto &typeIdColumn = table.addColumn("typeId");
auto &nameColumn = table.addColumn("name");
table.addColumn("propertyTypeId");
table.addColumn("propertyTraits");
{
Sqlite::Table propertyDeclarationTable;
propertyDeclarationTable.setUseIfNotExists(true);
propertyDeclarationTable.setName("propertyDeclarations");
propertyDeclarationTable.addColumn("propertyDeclarationId",
Sqlite::ColumnType::Integer,
{Sqlite::PrimaryKey{}});
auto &typeIdColumn = propertyDeclarationTable.addColumn("typeId");
auto &nameColumn = propertyDeclarationTable.addColumn("name");
propertyDeclarationTable.addForeignKeyColumn("propertyTypeId",
typesTable,
Sqlite::ForeignKeyAction::NoAction,
Sqlite::ForeignKeyAction::Restrict,
Sqlite::Enforment::Deferred);
propertyDeclarationTable.addColumn("propertyTraits");
table.addUniqueIndex({typeIdColumn, nameColumn});
propertyDeclarationTable.addUniqueIndex({typeIdColumn, nameColumn});
table.initialize(database);
propertyDeclarationTable.initialize(database);
}
}
void createExportedTypesTable(Database &database)
@@ -980,11 +995,13 @@ public:
Database &database;
Initializer initializer;
ReadWriteStatement<1> upsertTypeStatement{
"INSERT INTO types(name, accessSemantics, prototypeId, sourceId) VALUES(?1, ?2, "
"nullif(?3, -1), nullif(?4, -1)) ON "
"INSERT INTO types(importId, name, accessSemantics, sourceId) VALUES(?1, ?2, "
"?3, nullif(?4, -1)) ON "
"CONFLICT DO UPDATE SET prototypeId=excluded.prototypeId, "
"accessSemantics=excluded.accessSemantics, sourceId=excluded.sourceId RETURNING typeId",
database};
WriteStatement updatePrototypeStatement{
"UPDATE types SET prototypeId=nullif(?2, -1) WHERE typeId=?1", database};
mutable ReadStatement<1> selectTypeIdByQualifiedNameStatement{
"SELECT typeId FROM exportedTypes WHERE qualifiedName=?1 AND majorVersion=?2 AND "
"minorVersion<=?3 ORDER BY minorVersion DESC LIMIT 1",
@@ -1044,20 +1061,19 @@ public:
"INSERT INTO sources(sourceContextId, sourceName) VALUES (?,?)", database};
mutable ReadStatement<3> selectAllSourcesStatement{
"SELECT sourceName, sourceContextId, sourceId FROM sources", database};
ReadWriteStatement<1> insertTypeStatement{"INSERT INTO types(name) VALUES(?) RETURNING typeId",
database};
mutable ReadStatement<1> selectTypeIdByNameStatement{"SELECT typeId FROM types WHERE name=?",
database};
mutable ReadStatement<4> selectTypeByTypeIdStatement{
"SELECT name, (SELECT name FROM types WHERE typeId=outerTypes.prototypeId), "
mutable ReadStatement<5> selectTypeByTypeIdStatement{
"SELECT importId, name, (SELECT name FROM types WHERE typeId=outerTypes.prototypeId), "
"accessSemantics, ifnull(sourceId, -1) FROM types AS outerTypes WHERE typeId=?",
database};
mutable ReadStatement<3> selectExportedTypesByTypeIdStatement{
"SELECT qualifiedName, majorVersion, minorVersion FROM exportedTypes WHERE typeId=?",
database};
mutable ReadStatement<5> selectTypesStatement{
"SELECT name, typeId, (SELECT name FROM types WHERE typeId=outerTypes.prototypeId),"
"accessSemantics, ifnull(sourceId, -1) FROM types AS outerTypes",
mutable ReadStatement<6> selectTypesStatement{
"SELECT importId, name, typeId, (SELECT name FROM types WHERE "
"typeId=outerTypes.prototypeId), accessSemantics, ifnull(sourceId, -1) FROM types AS "
"outerTypes",
database};
ReadStatement<1> selectNotUpdatedTypesInSourcesStatement{
"SELECT typeId FROM types WHERE (sourceId IN carray(?1) AND typeId NOT IN carray(?2))",
@@ -1072,9 +1088,7 @@ public:
"DELETE FROM functionDeclarations WHERE typeId=?", database};
WriteStatement deleteSignalDeclarationByTypeIdStatement{
"DELETE FROM signalDeclarations WHERE typeId=?", database};
WriteStatement resetTypeStatement{
"UPDATE types SET accessSemantics=NULL, sourceId=NULL, prototypeId=NULL WHERE typeId=?",
database};
WriteStatement deleteTypeStatement{"DELETE FROM types WHERE typeId=?", database};
mutable ReadStatement<3> selectPropertyDeclarationsByTypeIdStatement{
"SELECT name, (SELECT name FROM types WHERE typeId=propertyDeclarations.propertyTypeId),"
"propertyTraits FROM propertyDeclarations WHERE typeId=?",
@@ -1179,6 +1193,8 @@ public:
"SELECT name, version FROM importDependencies JOIN imports ON "
"importDependencies.parentImportId = imports.importId WHERE importDependencies.importId=?",
database};
mutable ReadStatement<1> selectTypeIdsForImportIdStatement{
"SELECT typeId FROM types WHERE importId=?", database};
};
} // namespace QmlDesigner

View File

@@ -371,7 +371,8 @@ class Type
{
public:
explicit Type() = default;
explicit Type(Utils::SmallStringView typeName,
explicit Type(ImportId importId,
Utils::SmallStringView typeName,
Utils::SmallStringView prototype,
TypeAccessSemantics accessSemantics,
SourceId sourceId,
@@ -391,9 +392,11 @@ public:
, accessSemantics{accessSemantics}
, sourceId{sourceId}
, typeId{typeId}
, importId{importId}
{}
explicit Type(Utils::SmallStringView typeName,
explicit Type(long long importId,
Utils::SmallStringView typeName,
Utils::SmallStringView prototype,
int accessSemantics,
int sourceId)
@@ -401,9 +404,12 @@ public:
, prototype{prototype}
, accessSemantics{static_cast<TypeAccessSemantics>(accessSemantics)}
, sourceId{sourceId}
, importId{importId}
{}
explicit Type(Utils::SmallStringView typeName,
explicit Type(long long importId,
Utils::SmallStringView typeName,
long long typeId,
Utils::SmallStringView prototype,
int accessSemantics,
@@ -413,6 +419,7 @@ public:
, accessSemantics{static_cast<TypeAccessSemantics>(accessSemantics)}
, sourceId{sourceId}
, typeId{typeId}
, importId{importId}
{}
public:
@@ -427,6 +434,7 @@ public:
TypeAccessSemantics accessSemantics = TypeAccessSemantics::Invalid;
SourceId sourceId;
TypeId typeId;
ImportId importId;
bool isCreatable = false;
};

View File

@@ -1666,9 +1666,9 @@ std::ostream &operator<<(std::ostream &out, const ExportedType &exportedType)
std::ostream &operator<<(std::ostream &out, const Type &type)
{
return out << "(\"" << type.typeName << "\", \"" << type.prototype << "\", "
<< type.accessSemantics << ", source: " << type.sourceId << ", "
<< type.exportedTypes << ", " << type.propertyDeclarations << ", "
return out << "(import: " << type.importId << ", \"" << type.typeName << "\", \""
<< type.prototype << "\", " << type.accessSemantics << ", source: " << type.sourceId
<< ", " << type.exportedTypes << ", " << type.propertyDeclarations << ", "
<< type.functionDeclarations << ", " << type.signalDeclarations << ")";
}

View File

@@ -385,7 +385,7 @@ std::ostream &operator<<(std::ostream &out, const VariantProperty &property);
template<auto Type, typename InternalIntergerType>
std::ostream &operator<<(std::ostream &out, const BasicId<Type, InternalIntergerType> &id)
{
return out << "(" << &id << ")";
return out << "id=" << &id;
}
namespace Cache {

File diff suppressed because it is too large Load Diff