Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
14807c5
change BranchCreationEntity to use only one operationalLimitGroups li…
basseche Jul 10, 2025
a26b6b9
temp
basseche Jul 15, 2025
84c8642
migration Ko
basseche Jul 16, 2025
706b64c
migration Ok
basseche Jul 17, 2025
6db0de0
Fix missing applicability
basseche Jul 17, 2025
1e22de3
Fix migration
basseche Jul 18, 2025
55a8df4
Change Specs : No Set Rename when content is different between origin…
basseche Jul 18, 2025
f1db561
Merge branch 'main' into change_Branch_Creation_Entities
Mathieu-Deharbe Jul 23, 2025
f367e95
tmp pom in order to use the lib
Mathieu-Deharbe Jul 28, 2025
d9a42da
Fix case in migration
basseche Jul 29, 2025
3bfe39a
Apply suggestions from code review
basseche Jul 29, 2025
aec4fb5
delete todo
basseche Jul 29, 2025
a5866b2
Merge branch 'main' into change_Branch_Creation_Entities
basseche Jul 29, 2025
ab61985
Merge branch 'main' into change_Branch_Creation_Entities
Mathieu-Deharbe Jul 31, 2025
d9a367b
reset pom.xml
basseche Jul 31, 2025
15c7c48
fix migration
basseche Aug 1, 2025
a996771
Fix tests + Fix migration ConstraintName
basseche Aug 4, 2025
04d53c1
Merge branch 'main' into change_Branch_Creation_Entities
basseche Aug 5, 2025
2791c9d
fix commit
basseche Aug 5, 2025
66f97bb
fix delete
basseche Aug 6, 2025
cb1e5f4
update network-modification lib version
basseche Aug 7, 2025
00dcc63
Merge branch 'main' into change_Branch_Creation_Entities
basseche Aug 7, 2025
1223c9c
fix hotspots
basseche Aug 7, 2025
8d253cf
Revert "fix hotspots"
basseche Aug 8, 2025
6a7819c
security hotspots
basseche Aug 8, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
<sonar.organization>gridsuite</sonar.organization>
<sonar.projectKey>org.gridsuite:network-modification-server</sonar.projectKey>
<!-- TODO network-modification.version remove when upgrading gridsuite dependencies -->
<network-modification.version>0.28.0</network-modification.version>
<network-modification.version>0.29.0</network-modification.version>
<powsybl-balances-adjustment.version>2.14.1</powsybl-balances-adjustment.version>
</properties>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,16 +71,9 @@ public class BranchCreationEntity extends EquipmentCreationEntity {
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@JoinTable(
joinColumns = @JoinColumn(name = "branch_id"), foreignKey = @ForeignKey(name = "branch_id_fk"),
inverseJoinColumns = @JoinColumn(name = "operational_limits_groups_id"), inverseForeignKey = @ForeignKey(name = "operational_limits_groups_id1_fk"))
inverseJoinColumns = @JoinColumn(name = "operational_limits_groups_id"), inverseForeignKey = @ForeignKey(name = "operational_limits_groups_id_fk"))
@OrderColumn(name = "pos_operationalLimitsGroups")
private List<OperationalLimitsGroupEntity> operationalLimitsGroups1;

@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@JoinTable(
joinColumns = @JoinColumn(name = "branch_id"), foreignKey = @ForeignKey(name = "branch_id_fk"),
inverseJoinColumns = @JoinColumn(name = "operational_limits_groups_id"), inverseForeignKey = @ForeignKey(name = "operational_limits_groups_id2_fk"))
@OrderColumn(name = "pos_operationalLimitsGroups")
private List<OperationalLimitsGroupEntity> operationalLimitsGroups2;
private List<OperationalLimitsGroupEntity> operationalLimitsGroups;

@Column(name = "selectedOperationalLimitsGroupId1")
private String selectedOperationalLimitsGroupId1;
Expand All @@ -107,8 +100,7 @@ private void assignAttributes(BranchCreationInfos branchCreationInfos) {
voltageLevelId2 = branchCreationInfos.getVoltageLevelId2();
busOrBusbarSectionId1 = branchCreationInfos.getBusOrBusbarSectionId1();
busOrBusbarSectionId2 = branchCreationInfos.getBusOrBusbarSectionId2();
operationalLimitsGroups1 = assignOperationalLimitsGroups(branchCreationInfos.getOperationalLimitsGroups1(), operationalLimitsGroups1);
operationalLimitsGroups2 = assignOperationalLimitsGroups(branchCreationInfos.getOperationalLimitsGroups2(), operationalLimitsGroups2);
operationalLimitsGroups = assignOperationalLimitsGroups(branchCreationInfos.getOperationalLimitsGroups(), operationalLimitsGroups);
connectionDirection1 = branchCreationInfos.getConnectionDirection1();
connectionName1 = branchCreationInfos.getConnectionName1();
connectionDirection2 = branchCreationInfos.getConnectionDirection2();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,7 @@ public LineCreationInfos toModificationInfos() {
getProperties().stream()
.map(FreePropertyEntity::toInfos)
.toList())
.operationalLimitsGroups1(OperationalLimitsGroupEntity.fromOperationalLimitsGroupsEntities(getOperationalLimitsGroups1()))
.operationalLimitsGroups2(OperationalLimitsGroupEntity.fromOperationalLimitsGroupsEntities(getOperationalLimitsGroups2()));
.operationalLimitsGroups(OperationalLimitsGroupEntity.fromOperationalLimitsGroupsEntities(getOperationalLimitsGroups()));

return builder;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ public class OperationalLimitsGroupEntity {
@Column(name = "id")
private String id;

@Column(name = "applicability")
@Enumerated(EnumType.STRING)
private OperationalLimitsGroupInfos.Applicability applicability;

@OneToOne(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
@JoinColumn(name = "current_limits_id",
referencedColumnName = "id",
Expand All @@ -49,6 +53,7 @@ public static List<OperationalLimitsGroupEntity> toOperationalLimitsGroupsEntiti
new OperationalLimitsGroupEntity(
null,
limitsGroup.getId(),
limitsGroup.getApplicability(),
new CurrentLimitsEntity(limitsGroup.getCurrentLimits())
)
)
Expand All @@ -61,6 +66,7 @@ public static List<OperationalLimitsGroupInfos> fromOperationalLimitsGroupsEntit
.map(limitsGroupEntity ->
OperationalLimitsGroupInfos.builder()
.id(limitsGroupEntity.getId())
.applicability(limitsGroupEntity.getApplicability())
.currentLimits(limitsGroupEntity.getCurrentLimits().toCurrentLimitsInfos())
.build()
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,8 +211,7 @@ public TwoWindingsTransformerCreationInfos toModificationInfos() {
getProperties().stream()
.map(FreePropertyEntity::toInfos)
.toList())
.operationalLimitsGroups1(OperationalLimitsGroupEntity.fromOperationalLimitsGroupsEntities(getOperationalLimitsGroups1()))
.operationalLimitsGroups2(OperationalLimitsGroupEntity.fromOperationalLimitsGroupsEntities(getOperationalLimitsGroups2()));
.operationalLimitsGroups(OperationalLimitsGroupEntity.fromOperationalLimitsGroupsEntities(getOperationalLimitsGroups()));

if (!ratioTapChangerSteps.isEmpty()) {
List<TapChangerStepCreationInfos> ratioTapChangerStepCreationInfos = ratioTapChangerSteps.stream().map(TapChangerStepCreationEmbeddable::toModificationInfos).collect(Collectors.toList());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
package org.gridsuite.modification.server.migration;

import liquibase.change.custom.CustomSqlChange;
import liquibase.database.Database;
import liquibase.database.jvm.JdbcConnection;
import liquibase.exception.CustomChangeException;
import liquibase.exception.DatabaseException;
import liquibase.exception.SetupException;
import liquibase.exception.ValidationErrors;
import liquibase.resource.ResourceAccessor;
import liquibase.statement.SqlStatement;
import liquibase.statement.core.DeleteStatement;
import liquibase.statement.core.InsertStatement;
import liquibase.statement.core.UpdateStatement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

public class MergeLimitSetsGroupsTables implements CustomSqlChange {

private static final Logger LOGGER = LoggerFactory.getLogger(MergeLimitSetsGroupsTables.class);
private static final String UUID_COL = "uuid";
private static final String ID_COL = "id";
private static final String OPERATIONAL_LG_ID_COL = "operational_limits_groups_id";
private static final String CURRENT_LIMITS_ID_COL = "current_limits_id";
private static final String POS_OP_LG_COL = "pos_operational_limits_groups";
private static final String OPERATIONAL_LIMITS_GROUPS_TABLE = "operational_limits_group";
private static final String BRANCH_ID_COL = "branch_id";

private String createQueryLineOpLimitsGroups(String id, String tableName) {
return "select * from " + tableName + " where branch_id = '" + id + "'";
}

private String createQueryLineOpLimitsGroupsWithPos(String tableName, String id, String pos) {
return "select * from " + tableName + " where branch_id = '" + id + "' and pos_operational_limits_groups = " + pos;
}

private int getLength(ResultSet resultSet) throws SQLException {
resultSet.last();
int length = resultSet.getRow();
resultSet.beforeFirst();
return length;
}

private boolean compareOperationalLimitsInfos(JdbcConnection connection, String operationalLimitsIds1, String operationalLimitsIds2) throws DatabaseException, SQLException {
final String query = "select current_limits_id from operational_limits_group where uuid ='<id>'";
ResultSet currentLimits1 = connection.createStatement().executeQuery(query.replace("<id>", operationalLimitsIds1));
ResultSet currentLimits2 = connection.createStatement().executeQuery(query.replace("<id>", operationalLimitsIds2));

if (currentLimits1.next() && currentLimits2.next()) {
String currentLimitsQuery = "select permanent_limit from current_limits where id = '<id>'";
String currentLimitsId1 = currentLimits1.getString(CURRENT_LIMITS_ID_COL);
String currentLimitsId2 = currentLimits2.getString(CURRENT_LIMITS_ID_COL);
ResultSet permanentLimit = connection.createStatement().executeQuery(currentLimitsQuery.replace("<id>", currentLimitsId1));
ResultSet permanentLimit2 = connection.createStatement().executeQuery(currentLimitsQuery.replace("<id>", currentLimitsId2));

boolean haspermanentLimit = permanentLimit.next();
boolean haspermanentLimit2 = permanentLimit2.next();
if (haspermanentLimit != haspermanentLimit2) {
return false;
}
if (haspermanentLimit && !Objects.equals(permanentLimit.getString("permanent_limit"),
permanentLimit2.getString("permanent_limit"))) {
return false;
}

final String queryTemporary = "select * from current_temporary_limits where id ='<id>'";
Statement statement1 = connection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY);
Statement statement2 = connection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY);
ResultSet temporaryLimit = statement1.executeQuery(queryTemporary.replace("<id>", currentLimitsId1));
ResultSet temporaryLimit2 = statement2.executeQuery(queryTemporary.replace("<id>", currentLimitsId2));
if (getLength(temporaryLimit) != getLength(temporaryLimit2)) {
return false;
}

while (temporaryLimit.next()) {
String name = temporaryLimit.getString("name");
boolean found = false;
temporaryLimit2.beforeFirst();
while (temporaryLimit2.next()) {
if (Objects.equals(temporaryLimit2.getString("name"), name)) {
if (!Objects.equals(temporaryLimit.getString("value_"), temporaryLimit2.getString("value_")) ||
!Objects.equals(temporaryLimit.getString("acceptable_duration"), temporaryLimit2.getString("acceptable_duration"))) {
return false;
}
found = true;
break;
}
}
// temporary limit not found
if (!found) {
return false;
}
}
}

return true;
}

private void addOperationalLimitsGroupApplicability(Database database, ResultSet operationalLimitsGroups,
List<SqlStatement> statements, String applicability) throws SQLException {

if (operationalLimitsGroups.next()) {
statements.add(new UpdateStatement(database.getDefaultCatalogName(), database.getDefaultSchemaName(), OPERATIONAL_LIMITS_GROUPS_TABLE)
.setWhereClause(UUID_COL + " = '" + operationalLimitsGroups.getString(UUID_COL) + "'")
.addNewColumnValue("applicability", applicability));
}
}

@Override
public SqlStatement[] generateStatements(Database database) throws CustomChangeException {
JdbcConnection connection = (JdbcConnection) database.getConnection();

List<SqlStatement> statements = new ArrayList<>();

try {
for (int i = 0; i < 2; i++) {
// Define tables names ( i= 0 => lines, i=1 => twoWindingsTransformers)
final String branchCreationTable = i == 0 ? "line_creation" : "two_windings_transformer_creation";
final String branchCreationOpLimitsGroups1Table = i == 0 ? "line_creation_operational_limits_groups1"
: "two_windings_transformer_creation_operational_limits_groups1";
final String branchCreationOpLimitsGroups2Table = i == 0 ? "line_creation_operational_limits_groups2"
: "two_windings_transformer_creation_operational_limits_groups2";
final String branchCreationOpLimitsGroupsTable = i == 0 ? "line_creation_operational_limits_groups"
: "two_windings_transformer_creation_operational_limits_groups";

String branchesToProcess = "Select id, selected_operational_limits_group_id1, selected_operational_limits_group_id2 from <Table>";
try (ResultSet branches = connection.createStatement().executeQuery(branchesToProcess.replace("<Table>", branchCreationTable))) {
while (branches.next()) {
int position = 0;
//get operational limits groups1
ResultSet branchCreationOpLimitsGroups1 = connection.createStatement()
.executeQuery(createQueryLineOpLimitsGroups(branches.getString(ID_COL), branchCreationOpLimitsGroups1Table));

while (branchCreationOpLimitsGroups1.next()) {
String branchCreationOpLimitsGroup1Id = branchCreationOpLimitsGroups1.getString(OPERATIONAL_LG_ID_COL);
String branchCreationOpLimitsGroup1Pos = branchCreationOpLimitsGroups1.getString(POS_OP_LG_COL);

ResultSet branchCreationOpLimitsGroups2 = connection.createStatement()
.executeQuery(createQueryLineOpLimitsGroupsWithPos(branchCreationOpLimitsGroups2Table, branches.getString(ID_COL),
branchCreationOpLimitsGroup1Pos));

branchCreationOpLimitsGroups2.next();
String branchCreationOpLimitsGroup2Id = branchCreationOpLimitsGroups2.getString(OPERATIONAL_LG_ID_COL);

// Compare Both limitsGroups 1 and 2 limits
String query = "select * from operational_limits_group where uuid = '<id>'";
ResultSet operationalLimitsGroups1 = connection.createStatement().executeQuery(query.replace("<id>", branchCreationOpLimitsGroup1Id));

if (compareOperationalLimitsInfos(connection, branchCreationOpLimitsGroup1Id, branchCreationOpLimitsGroup2Id)) {
String query2 = "select current_limits_id from operational_limits_group where uuid = '<id>'";
ResultSet operationalLimitsGroups2 = connection.createStatement().executeQuery(query2.replace("<id>", branchCreationOpLimitsGroup2Id));

// - remove line from operational_limits_group
// - remove related permanent limit from current_limits
// - remove all other related limits from current_temporary_limits
if (operationalLimitsGroups2.next()) {
statements.add(new DeleteStatement(database.getDefaultCatalogName(), database.getDefaultSchemaName(), OPERATIONAL_LIMITS_GROUPS_TABLE)
.setWhere(UUID_COL + " = '" + branchCreationOpLimitsGroup2Id + "'"));
String currentLimitId = operationalLimitsGroups2.getString(CURRENT_LIMITS_ID_COL);
statements.add(new DeleteStatement(database.getDefaultCatalogName(), database.getDefaultSchemaName(), "current_temporary_limits")
.setWhere(ID_COL + " = '" + currentLimitId + "'"));
statements.add(new DeleteStatement(database.getDefaultCatalogName(), database.getDefaultSchemaName(), "current_limits")
.setWhere(ID_COL + " = '" + currentLimitId + "'"));
}

addOperationalLimitsGroupApplicability(database, operationalLimitsGroups1, statements, "EQUIPMENT");

// if they are equal then add only one limitGroup in new Table with application side = equipment (both)
statements.add(new InsertStatement(database.getDefaultCatalogName(), database.getDefaultSchemaName(), branchCreationOpLimitsGroupsTable)
.addColumnValue(BRANCH_ID_COL, branches.getString(ID_COL))
.addColumnValue(OPERATIONAL_LG_ID_COL, branchCreationOpLimitsGroup1Id)
.addColumnValue(POS_OP_LG_COL, position++));
} else {
// change Applicability side 1
addOperationalLimitsGroupApplicability(database, operationalLimitsGroups1, statements, "SIDE1");

// Add to merged table
statements.add(new InsertStatement(database.getDefaultCatalogName(), database.getDefaultSchemaName(), branchCreationOpLimitsGroupsTable)
.addColumnValue(BRANCH_ID_COL, branches.getString(ID_COL))
.addColumnValue(OPERATIONAL_LG_ID_COL, branchCreationOpLimitsGroup1Id)
.addColumnValue(POS_OP_LG_COL, position++));

// Change Applicability side 2
String query3 = "select * from operational_limits_group where uuid = '<id>'";
ResultSet operationalLimitsGroups2 = connection.createStatement().executeQuery(query3.replace("<id>", branchCreationOpLimitsGroup2Id));
addOperationalLimitsGroupApplicability(database, operationalLimitsGroups2, statements, "SIDE2");

// Add to merged table
statements.add(new InsertStatement(database.getDefaultCatalogName(), database.getDefaultSchemaName(), branchCreationOpLimitsGroupsTable)
.addColumnValue(BRANCH_ID_COL, branches.getString(ID_COL))
.addColumnValue(OPERATIONAL_LG_ID_COL, branchCreationOpLimitsGroup2Id)
.addColumnValue(POS_OP_LG_COL, position++));
}
}
}
}
}
} catch (Exception throwables) {
LOGGER.error(throwables.getMessage());
return new SqlStatement[0]; // If any exception occurs don't do any migration
}
return statements.toArray(new SqlStatement[0]);
}

@Override
public String getConfirmationMessage() {
return "tables line_creation_operational_limits_group1 and 2, merged successfully into line_creation_operational_limits_group";
}

@Override
public void setUp() throws SetupException {

}

@Override
public void setFileOpener(ResourceAccessor resourceAccessor) {

}

@Override
public ValidationErrors validate(Database database) {
return null;
}
}
Loading