From 1a8edbe0d6687b90750d1700d711febb71400fac Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 26 Jun 2026 08:09:03 +0000 Subject: [PATCH 1/8] Initial plan From 4467e790ad121c834fcec93a1b42c0731a9e086e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 26 Jun 2026 08:11:48 +0000 Subject: [PATCH 2/8] Mark stored procedure params without defaults as required in OpenAPI --- src/Core/Services/OpenAPI/OpenApiDocumentor.cs | 5 ++++- .../OpenApiDocumentor/StoredProcedureGeneration.cs | 7 +++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/Core/Services/OpenAPI/OpenApiDocumentor.cs b/src/Core/Services/OpenAPI/OpenApiDocumentor.cs index 979da52eb6..3a3f2de7ca 100644 --- a/src/Core/Services/OpenAPI/OpenApiDocumentor.cs +++ b/src/Core/Services/OpenAPI/OpenApiDocumentor.cs @@ -1422,7 +1422,10 @@ private static OpenApiSchema CreateSpRequestComponentSchema(Dictionary requiredParameters = _openApiDocument.Components.Schemas[expectedSchemaReferenceId].Required; + CollectionAssert.AreEquivalent( + expectedParameters, + requiredParameters.ToArray(), + message: "Unexpected required parameters in request body schema component."); } } From d6bef3b5b471e8eab0923bc9a666b853512f7dc4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 7 Jul 2026 10:31:17 +0000 Subject: [PATCH 3/8] Add tests for SP parameter required logic in OpenAPI schema --- .../StoredProcedureGeneration.cs | 58 +++++++++++++++++-- 1 file changed, 53 insertions(+), 5 deletions(-) diff --git a/src/Service.Tests/OpenApiDocumentor/StoredProcedureGeneration.cs b/src/Service.Tests/OpenApiDocumentor/StoredProcedureGeneration.cs index a2655d7dcb..6e675a41a0 100644 --- a/src/Service.Tests/OpenApiDocumentor/StoredProcedureGeneration.cs +++ b/src/Service.Tests/OpenApiDocumentor/StoredProcedureGeneration.cs @@ -63,9 +63,51 @@ public static void CreateEntities() Relationships: null, Description: "Represents a stored procedure for books"); + // Entity whose "title" parameter has a config-provided default value. + // Because a default is available, "title" must not be flagged as required, while + // "publisher_id" (no default) must remain required. + Entity entity2 = new( + Source: new( + Object: "insert_book", + EntitySourceType.StoredProcedure, + Parameters: new List + { + new() { Name = "title", Default = "Sample Title" } + }, + KeyFields: null), + Fields: null, + GraphQL: new(Singular: null, Plural: null, Enabled: false), + Rest: new(Methods: EntityRestOptions.DEFAULT_SUPPORTED_VERBS), + Permissions: OpenApiTestBootstrap.CreateBasicPermissions(), + Mappings: null, + Relationships: null, + Description: "Stored procedure with a parameter default"); + + // Entity whose "title" parameter is explicitly marked required: false in config. + // Even though it has no default value, the explicit override must be honored so that only + // "id" (no default, no override) remains required. + Entity entity3 = new( + Source: new( + Object: "update_book_title", + EntitySourceType.StoredProcedure, + Parameters: new List + { + new() { Name = "title", Required = false } + }, + KeyFields: null), + Fields: null, + GraphQL: new(Singular: null, Plural: null, Enabled: false), + Rest: new(Methods: EntityRestOptions.DEFAULT_SUPPORTED_VERBS), + Permissions: OpenApiTestBootstrap.CreateBasicPermissions(), + Mappings: null, + Relationships: null, + Description: "Stored procedure with an explicit required override"); + Dictionary entities = new() { - { "sp1", entity1 } + { "sp1", entity1 }, + { "sp2", entity2 }, + { "sp3", entity3 } }; _runtimeEntities = new(entities); @@ -74,13 +116,19 @@ public static void CreateEntities() /// /// Validates that the generated request body references stored procedure parameters /// and not result set columns. + /// Also validates that the request body schema component flags the expected parameters + /// as required: a parameter is required when it has no default value and is not explicitly + /// marked required: false in the runtime config. /// /// Entity name /// Expected parameters in request body /// Expected parameter value types in request body. - [DataRow("sp1", new string[] { "title", "publisher_name" }, new string[] { "string", "string" }, DisplayName = "Validate request body parameters and parameter Json data types.")] + /// Expected parameters flagged as required in the schema component. + [DataRow("sp1", new string[] { "title", "publisher_name" }, new string[] { "string", "string" }, new string[] { "title", "publisher_name" }, DisplayName = "Parameters without defaults are all required.")] + [DataRow("sp2", new string[] { "title", "publisher_id" }, new string[] { "string", "integer" }, new string[] { "publisher_id" }, DisplayName = "Parameter with a config default is not required.")] + [DataRow("sp3", new string[] { "id", "title" }, new string[] { "integer", "string" }, new string[] { "id" }, DisplayName = "Parameter explicitly marked required:false is not required.")] [DataTestMethod] - public void ValidateRequestBodyContents(string entityName, string[] expectedParameters, string[] expectedParametersJsonTypes) + public void ValidateRequestBodyContents(string entityName, string[] expectedParameters, string[] expectedParametersJsonTypes, string[] expectedRequiredParameters) { Dictionary configuredOperations = ResolveConfiguredOperations(_runtimeEntities[entityName]); foreach (OperationType opType in configuredOperations.Keys) @@ -102,10 +150,10 @@ public void ValidateRequestBodyContents(string entityName, string[] expectedPara ValidateOpenApiReferenceContents(schemaComponentReference, expectedSchemaReferenceId, expectedParameters, expectedParametersJsonTypes); - // Validate that parameters without a default value are marked as required in the schema component. + // Validate that the expected parameters are marked as required in the schema component. ISet requiredParameters = _openApiDocument.Components.Schemas[expectedSchemaReferenceId].Required; CollectionAssert.AreEquivalent( - expectedParameters, + expectedRequiredParameters, requiredParameters.ToArray(), message: "Unexpected required parameters in request body schema component."); } From 9f797d507e727389fec29741e56e811e56c1ba3b Mon Sep 17 00:00:00 2001 From: Souvik Ghosh Date: Thu, 9 Jul 2026 15:58:59 +0530 Subject: [PATCH 4/8] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../OpenApiDocumentor/StoredProcedureGeneration.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Service.Tests/OpenApiDocumentor/StoredProcedureGeneration.cs b/src/Service.Tests/OpenApiDocumentor/StoredProcedureGeneration.cs index 6e675a41a0..4af657ef72 100644 --- a/src/Service.Tests/OpenApiDocumentor/StoredProcedureGeneration.cs +++ b/src/Service.Tests/OpenApiDocumentor/StoredProcedureGeneration.cs @@ -151,7 +151,7 @@ public void ValidateRequestBodyContents(string entityName, string[] expectedPara ValidateOpenApiReferenceContents(schemaComponentReference, expectedSchemaReferenceId, expectedParameters, expectedParametersJsonTypes); // Validate that the expected parameters are marked as required in the schema component. - ISet requiredParameters = _openApiDocument.Components.Schemas[expectedSchemaReferenceId].Required; +ISet requiredParameters = _openApiDocument.Components.Schemas[expectedSchemaReferenceId].Required ?? new HashSet(); CollectionAssert.AreEquivalent( expectedRequiredParameters, requiredParameters.ToArray(), From 8154a7ad88bfb56e300098173f1ea559e217c14c Mon Sep 17 00:00:00 2001 From: Souvik Ghosh Date: Thu, 9 Jul 2026 15:59:11 +0530 Subject: [PATCH 5/8] Update src/Service.Tests/OpenApiDocumentor/StoredProcedureGeneration.cs Co-authored-by: RubenCerna2079 <32799214+RubenCerna2079@users.noreply.github.com> --- .../OpenApiDocumentor/StoredProcedureGeneration.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Service.Tests/OpenApiDocumentor/StoredProcedureGeneration.cs b/src/Service.Tests/OpenApiDocumentor/StoredProcedureGeneration.cs index 4af657ef72..b38fa06fe7 100644 --- a/src/Service.Tests/OpenApiDocumentor/StoredProcedureGeneration.cs +++ b/src/Service.Tests/OpenApiDocumentor/StoredProcedureGeneration.cs @@ -126,7 +126,7 @@ public static void CreateEntities() /// Expected parameters flagged as required in the schema component. [DataRow("sp1", new string[] { "title", "publisher_name" }, new string[] { "string", "string" }, new string[] { "title", "publisher_name" }, DisplayName = "Parameters without defaults are all required.")] [DataRow("sp2", new string[] { "title", "publisher_id" }, new string[] { "string", "integer" }, new string[] { "publisher_id" }, DisplayName = "Parameter with a config default is not required.")] - [DataRow("sp3", new string[] { "id", "title" }, new string[] { "integer", "string" }, new string[] { "id" }, DisplayName = "Parameter explicitly marked required:false is not required.")] + [DataRow("sp3", new string[] { "id", "title" }, new string[] { "integer", "string" }, new string[] { "id" }, DisplayName = "Parameter explicitly marked required: false is not required.")] [DataTestMethod] public void ValidateRequestBodyContents(string entityName, string[] expectedParameters, string[] expectedParametersJsonTypes, string[] expectedRequiredParameters) { From e68102a051d490967d29a5a931b6c4f4ae639367 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 9 Jul 2026 10:36:03 +0000 Subject: [PATCH 6/8] Fix IsRequestBodyRequired stored-procedure branch to honor Required=false --- src/Core/Services/OpenAPI/OpenApiDocumentor.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Core/Services/OpenAPI/OpenApiDocumentor.cs b/src/Core/Services/OpenAPI/OpenApiDocumentor.cs index 3a3f2de7ca..afb1657d1a 100644 --- a/src/Core/Services/OpenAPI/OpenApiDocumentor.cs +++ b/src/Core/Services/OpenAPI/OpenApiDocumentor.cs @@ -1135,9 +1135,9 @@ private static bool IsRequestBodyRequired(SourceDefinition sourceDef, bool consi StoredProcedureDefinition spDef = (StoredProcedureDefinition)sourceDef; foreach (KeyValuePair parameterMetadata in spDef.Parameters) { - // A parameter which does not have any of the following properties + // A parameter which is explicitly marked required or has no default value // results in the body being required so that a value can be provided. - if (!parameterMetadata.Value.HasConfigDefault) + if (parameterMetadata.Value.Required ?? !parameterMetadata.Value.HasConfigDefault) { requestBodyRequired = true; break; From ac1774b6550d2ee413c5433f0a76b1a0e34b38d9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 10 Jul 2026 08:42:15 +0000 Subject: [PATCH 7/8] Fix whitespace formatting in StoredProcedureGeneration.cs --- .../OpenApiDocumentor/StoredProcedureGeneration.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Service.Tests/OpenApiDocumentor/StoredProcedureGeneration.cs b/src/Service.Tests/OpenApiDocumentor/StoredProcedureGeneration.cs index b38fa06fe7..94493e2bf0 100644 --- a/src/Service.Tests/OpenApiDocumentor/StoredProcedureGeneration.cs +++ b/src/Service.Tests/OpenApiDocumentor/StoredProcedureGeneration.cs @@ -151,7 +151,7 @@ public void ValidateRequestBodyContents(string entityName, string[] expectedPara ValidateOpenApiReferenceContents(schemaComponentReference, expectedSchemaReferenceId, expectedParameters, expectedParametersJsonTypes); // Validate that the expected parameters are marked as required in the schema component. -ISet requiredParameters = _openApiDocument.Components.Schemas[expectedSchemaReferenceId].Required ?? new HashSet(); + ISet requiredParameters = _openApiDocument.Components.Schemas[expectedSchemaReferenceId].Required ?? new HashSet(); CollectionAssert.AreEquivalent( expectedRequiredParameters, requiredParameters.ToArray(), From 2d432dcd1755012590cb730f85c5160d4b136ff3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 29 Jul 2026 15:27:51 +0000 Subject: [PATCH 8/8] Fix GET SP query params required field; add requestBody.Required assertions and GET query param tests Co-authored-by: souvikghosh04 <210500244+souvikghosh04@users.noreply.github.com> --- .../Services/OpenAPI/OpenApiDocumentor.cs | 4 +- .../StoredProcedureGeneration.cs | 69 +++++++++++++++++-- 2 files changed, 66 insertions(+), 7 deletions(-) diff --git a/src/Core/Services/OpenAPI/OpenApiDocumentor.cs b/src/Core/Services/OpenAPI/OpenApiDocumentor.cs index 61813db48d..0b090f4335 100644 --- a/src/Core/Services/OpenAPI/OpenApiDocumentor.cs +++ b/src/Core/Services/OpenAPI/OpenApiDocumentor.cs @@ -680,7 +680,7 @@ private static void AddCustomHeadersToOperation(OpenApiOperation operation) /// /// This method adds the input parameters from the stored procedure definition to the OpenApi operation parameters. - /// A input parameter will be marked REQUIRED if default value is not available. + /// A input parameter will be marked REQUIRED when it is explicitly flagged in config or when no default value is available. /// private static void AddStoredProcedureInputParameters(OpenApiOperation operation, StoredProcedureDefinition spDefinition) { @@ -690,7 +690,7 @@ private static void AddStoredProcedureInputParameters(OpenApiOperation operation GetOpenApiQueryParameter( name: paramKey, description: "Input parameter for stored procedure arguments", - required: false, + required: parameterDefinition.Required ?? !parameterDefinition.HasConfigDefault, type: TypeHelper.GetJsonDataTypeFromSystemType(parameterDefinition.SystemType).ToString().ToLower() ) ); diff --git a/src/Service.Tests/OpenApiDocumentor/StoredProcedureGeneration.cs b/src/Service.Tests/OpenApiDocumentor/StoredProcedureGeneration.cs index 94493e2bf0..714829ef23 100644 --- a/src/Service.Tests/OpenApiDocumentor/StoredProcedureGeneration.cs +++ b/src/Service.Tests/OpenApiDocumentor/StoredProcedureGeneration.cs @@ -103,11 +103,32 @@ public static void CreateEntities() Relationships: null, Description: "Stored procedure with an explicit required override"); + // Entity whose only parameter is explicitly marked required: false in config. + // Because no parameter is required, requestBody.Required and the GET query parameter's + // required flag must both be false, and the schema-level required set must be empty. + Entity entity4 = new( + Source: new( + Object: "get_publisher_by_id", + EntitySourceType.StoredProcedure, + Parameters: new List + { + new() { Name = "id", Required = false } + }, + KeyFields: null), + Fields: null, + GraphQL: new(Singular: null, Plural: null, Enabled: false), + Rest: new(Methods: EntityRestOptions.DEFAULT_SUPPORTED_VERBS), + Permissions: OpenApiTestBootstrap.CreateBasicPermissions(), + Mappings: null, + Relationships: null, + Description: "Stored procedure with all parameters marked required: false"); + Dictionary entities = new() { { "sp1", entity1 }, { "sp2", entity2 }, - { "sp3", entity3 } + { "sp3", entity3 }, + { "sp4", entity4 } }; _runtimeEntities = new(entities); @@ -119,16 +140,20 @@ public static void CreateEntities() /// Also validates that the request body schema component flags the expected parameters /// as required: a parameter is required when it has no default value and is not explicitly /// marked required: false in the runtime config. + /// Also validates the body-level required flag on the OpenApiRequestBody object, which + /// should be true when any parameter is required and false when all parameters are optional. /// /// Entity name /// Expected parameters in request body /// Expected parameter value types in request body. /// Expected parameters flagged as required in the schema component. - [DataRow("sp1", new string[] { "title", "publisher_name" }, new string[] { "string", "string" }, new string[] { "title", "publisher_name" }, DisplayName = "Parameters without defaults are all required.")] - [DataRow("sp2", new string[] { "title", "publisher_id" }, new string[] { "string", "integer" }, new string[] { "publisher_id" }, DisplayName = "Parameter with a config default is not required.")] - [DataRow("sp3", new string[] { "id", "title" }, new string[] { "integer", "string" }, new string[] { "id" }, DisplayName = "Parameter explicitly marked required: false is not required.")] + /// Expected value of the body-level required flag. + [DataRow("sp1", new string[] { "title", "publisher_name" }, new string[] { "string", "string" }, new string[] { "title", "publisher_name" }, true, DisplayName = "Parameters without defaults are all required.")] + [DataRow("sp2", new string[] { "title", "publisher_id" }, new string[] { "string", "integer" }, new string[] { "publisher_id" }, true, DisplayName = "Parameter with a config default is not required.")] + [DataRow("sp3", new string[] { "id", "title" }, new string[] { "integer", "string" }, new string[] { "id" }, true, DisplayName = "Parameter explicitly marked required: false is not required.")] + [DataRow("sp4", new string[] { "id" }, new string[] { "integer" }, new string[] { }, false, DisplayName = "All parameters marked required: false produces empty required set and optional request body.")] [DataTestMethod] - public void ValidateRequestBodyContents(string entityName, string[] expectedParameters, string[] expectedParametersJsonTypes, string[] expectedRequiredParameters) + public void ValidateRequestBodyContents(string entityName, string[] expectedParameters, string[] expectedParametersJsonTypes, string[] expectedRequiredParameters, bool expectedRequestBodyRequired) { Dictionary configuredOperations = ResolveConfiguredOperations(_runtimeEntities[entityName]); foreach (OperationType opType in configuredOperations.Keys) @@ -148,6 +173,9 @@ public void ValidateRequestBodyContents(string entityName, string[] expectedPara OpenApiReference schemaComponentReference = GetRequestBodyReference(requestBody); string expectedSchemaReferenceId = $"{entityName}{OpenApiDocumentor.SP_REQUEST_SUFFIX}"; + // Validate the body-level required flag. + Assert.AreEqual(expectedRequestBodyRequired, requestBody.Required, message: "Unexpected request body required value."); + ValidateOpenApiReferenceContents(schemaComponentReference, expectedSchemaReferenceId, expectedParameters, expectedParametersJsonTypes); // Validate that the expected parameters are marked as required in the schema component. @@ -204,6 +232,37 @@ public void OpenApiDocumentor_TagsIncludeEntityDescription() $"Expected tag for '{entityName}' with description '{expectedDescription}' not found."); } + /// + /// Validates that the generated GET operation query parameters for stored procedure entities + /// have the correct required flag: a parameter without a config default and not explicitly + /// marked required: false is required; a parameter explicitly marked required: false is not. + /// + /// Entity name. + /// Expected query parameter names. + /// Whether each corresponding query parameter is expected to be required. + [DataRow("sp1", new string[] { "title", "publisher_name" }, new bool[] { true, true }, DisplayName = "GET parameters without defaults are required.")] + [DataRow("sp4", new string[] { "id" }, new bool[] { false }, DisplayName = "GET parameter explicitly marked required: false is not required.")] + [DataTestMethod] + public void ValidateGetQueryParameters(string entityName, string[] expectedParameters, bool[] expectedRequired) + { + OpenApiOperation getOperation = _openApiDocument.Paths["/" + entityName].Operations[OperationType.Get]; + Assert.IsNotNull(getOperation, "GET operation not found."); + + // Filter to query parameters only (excludes the Authorization and X-MS-API-ROLE header parameters). + List spParams = getOperation.Parameters + .Where(p => p.In == ParameterLocation.Query) + .ToList(); + + Assert.AreEqual(expectedParameters.Length, spParams.Count, "Unexpected number of GET query parameters."); + + for (int i = 0; i < expectedParameters.Length; i++) + { + OpenApiParameter param = spParams.FirstOrDefault(p => p.Name == expectedParameters[i]); + Assert.IsNotNull(param, $"Parameter '{expectedParameters[i]}' not found in GET query parameters."); + Assert.AreEqual(expectedRequired[i], param.Required, $"Unexpected required value for GET query parameter '{expectedParameters[i]}'."); + } + } + /// /// Validates that the provided OpenApiReference object has the expected schema reference id /// and that that id is present in the list of component schema in the OpenApi document.