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 }