diff --git a/src/Cli.Tests/UpdateEntityTests.cs b/src/Cli.Tests/UpdateEntityTests.cs
index cac2db0a83..8c823d8eb3 100644
--- a/src/Cli.Tests/UpdateEntityTests.cs
+++ b/src/Cli.Tests/UpdateEntityTests.cs
@@ -1100,6 +1100,85 @@ public void TestUpdateEntityDescription()
Assert.AreEqual("Updated description", updatedRuntimeConfig.Entities["MyEntity"].Description);
}
+ ///
+ /// Updating a field's description without --fields.primary-key
+ /// should not change its existing primary-key flag.
+ ///
+ [TestMethod]
+ public void TestUpdateFieldDescriptionPreservesPrimaryKeyWhenNoFlagProvided()
+ {
+ string initialConfig = GetInitialConfigString() + "," + @"
+ ""entities"": {
+ ""MyEntity"": {
+ ""source"": ""MyTable"",
+ ""fields"": [
+ {
+ ""name"": ""Id"",
+ ""description"": ""Primary key"",
+ ""primary-key"": true
+ }
+ ],
+ ""permissions"": [
+ {
+ ""role"": ""anonymous"",
+ ""actions"": [""read""]
+ }
+ ]
+ }
+ }
+ }";
+
+ UpdateOptions options = new(
+ source: null,
+ permissions: null,
+ entity: "MyEntity",
+ sourceType: null,
+ sourceParameters: null,
+ sourceKeyFields: null,
+ restRoute: null,
+ graphQLType: null,
+ fieldsToInclude: null,
+ fieldsToExclude: null,
+ policyRequest: null,
+ policyDatabase: null,
+ relationship: null,
+ cardinality: null,
+ targetEntity: null,
+ linkingObject: null,
+ linkingSourceFields: null,
+ linkingTargetFields: null,
+ relationshipFields: null,
+ map: null,
+ cacheEnabled: null,
+ cacheTtl: null,
+ config: TEST_RUNTIME_CONFIG_FILE,
+ restMethodsForStoredProcedure: null,
+ graphQLOperationForStoredProcedure: null,
+ description: null,
+ parametersNameCollection: null,
+ parametersDescriptionCollection: null,
+ parametersRequiredCollection: null,
+ parametersDefaultCollection: null,
+ fieldsNameCollection: new[] { "Id" },
+ fieldsAliasCollection: null,
+ fieldsDescriptionCollection: new[] { "Unique Key" },
+ fieldsPrimaryKeyCollection: null,
+ mcpDmlTools: null,
+ mcpCustomTool: null
+ );
+
+ Assert.IsTrue(RuntimeConfigLoader.TryParseConfig(initialConfig, out RuntimeConfig? runtimeConfig), "Parsed config file.");
+ Assert.IsTrue(TryUpdateExistingEntity(options, runtimeConfig!, out RuntimeConfig updatedRuntimeConfig), "Successfully updated entity in the config.");
+
+ Entity updatedEntity = updatedRuntimeConfig.Entities["MyEntity"];
+ Assert.IsNotNull(updatedEntity.Fields);
+ Assert.AreEqual(1, updatedEntity.Fields!.Count);
+ FieldMetadata field = updatedEntity.Fields[0];
+ Assert.AreEqual("Id", field.Name);
+ Assert.AreEqual("Unique Key", field.Description);
+ Assert.IsTrue(field.PrimaryKey, "Primary key flag should be preserved when --fields.primary-key is not provided.");
+ }
+
private static string GetInitialConfigString()
{
return @"{" +
diff --git a/src/Cli/ConfigGenerator.cs b/src/Cli/ConfigGenerator.cs
index 648edc1950..4e5b72b2c2 100644
--- a/src/Cli/ConfigGenerator.cs
+++ b/src/Cli/ConfigGenerator.cs
@@ -1747,6 +1747,7 @@ public static bool TryUpdateExistingEntity(UpdateOptions options, RuntimeConfig
List updatedFieldsList = ComposeFieldsFromOptions(options);
Dictionary updatedFieldsDict = updatedFieldsList.ToDictionary(f => f.Name, f => f);
List mergedFields = [];
+ bool primaryKeyOptionProvided = options.FieldsPrimaryKeyCollection?.Any() == true;
foreach (FieldMetadata field in existingFields)
{
@@ -1757,7 +1758,10 @@ public static bool TryUpdateExistingEntity(UpdateOptions options, RuntimeConfig
Name = updatedField.Name,
Alias = updatedField.Alias ?? field.Alias,
Description = updatedField.Description ?? field.Description,
- PrimaryKey = updatedField.PrimaryKey
+ // If --fields.primary-key was not provided at all,
+ // keep the existing primary-key flag. Otherwise,
+ // use the value coming from updatedField.
+ PrimaryKey = primaryKeyOptionProvided ? updatedField.PrimaryKey : field.PrimaryKey
});
updatedFieldsDict.Remove(field.Name); // Remove so only new fields remain
}