Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,9 @@ protected override async Task GenerateAutoentitiesIntoEntities(IReadOnlyDictiona
continue;
}

// Sanitize the entity name by ensuring all whitespace characters are removed.
entityName = SanitizeGeneratedEntityName(entityName);

// Create the entity using the template settings and permissions from the autoentity configuration.
// Currently the source type is always Table for auto-generated entities from database objects.
Entity generatedEntity = new(
Expand Down Expand Up @@ -386,6 +389,12 @@ protected override async Task GenerateAutoentitiesIntoEntities(IReadOnlyDictiona
_runtimeConfigProvider.AddMergedEntitiesToConfig(entities);
}

/// <summary>
/// Queries the database for autoentities based on the provided autoentity definition.
/// </summary>
/// <param name="autoentityName">The name of the autoentity definition.</param>
/// <param name="autoentity">The autoentity definition containing patterns for inclusion, exclusion, and name.</param>
/// <returns>A JsonArray containing the queried autoentities, or an empty array if none are found.</returns>
public async Task<JsonArray?> QueryAutoentitiesAsync(string autoentityName, Autoentity autoentity)
{
string include = string.Join(",", autoentity.Patterns.Include);
Expand Down
25 changes: 25 additions & 0 deletions src/Core/Services/MetadataProviders/SqlMetadataProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -733,6 +733,31 @@ private void RemoveGeneratedAutoentities()
_runtimeConfigProvider.RemoveGeneratedAutoentitiesFromConfig();
}

/// <summary>
/// Sanitizes the generated entity name by removing whitespace and capitalizing the next character after whitespace.
/// </summary>
/// <param name="name">The entity name to be sanitized.</param>
/// <returns>The sanitized entity name.</returns>
protected static string SanitizeGeneratedEntityName(string name)
{
StringBuilder sanitizedName = new(name.Length);
bool capitalizeNext = false;

foreach (char character in name)
{
if (char.IsWhiteSpace(character))
{
capitalizeNext = true;
continue;
}

sanitizedName.Append(capitalizeNext ? char.ToUpperInvariant(character) : character);
capitalizeNext = false;
}

return sanitizedName.ToString();
}

protected void PopulateDatabaseObjectForEntity(
Entity entity,
string entityName,
Expand Down
39 changes: 30 additions & 9 deletions src/Service.Tests/Configuration/ConfigurationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5759,16 +5759,17 @@ public async Task TestAutoentitiesWithSameObjectDifferentSchemas()
}

/// <summary>
/// Ensures that autoentities are properly generated into in-memory entities when entities have non-default schemas.
/// Ensures that autoentities are properly generated into in-memory entities when entities have unusual elements such as non-default schemas or spaces in their names.
/// </summary>
/// <param name="includePattern">The pattern to include for autoentities</param>
/// <param name="isPatternFoo">Boolean that indicates if the pattern is for the foo schema</param>
/// <param name="patternType">Integer that indicates which input pattern is being used</param>
/// <returns></returns>
Comment thread
RubenCerna2079 marked this conversation as resolved.
[TestCategory(TestCategory.MSSQL)]
[DataTestMethod]
[DataRow("foo.%", true, DisplayName = "Test Autoentities with foo schema")]
[DataRow("bar.%", false, DisplayName = "Test Autoentities with bar schema")]
public async Task TestAutoentitiesGeneratedWithDifferentSchemas(string includePattern, bool isPatternFoo)
[DataRow("foo.%", 0, DisplayName = "Test Autoentities with foo schema")]
[DataRow("bar.%", 1, DisplayName = "Test Autoentities with bar schema")]
[DataRow("dbo.Order Items", 2, DisplayName = "Test Autoentities with object with spaces")]
public async Task TestAutoentitiesGeneratedWithUnusualElements(string includePattern, int patternType)
Comment thread
RubenCerna2079 marked this conversation as resolved.
{
// Arrange
Dictionary<string, Autoentity> autoentityMap = new()
Expand Down Expand Up @@ -5826,11 +5827,33 @@ public async Task TestAutoentitiesGeneratedWithDifferentSchemas(string includePa
using (HttpClient client = server.CreateClient())
{
// Act
string path = isPatternFoo ? "foo_magazines" : "bar_magazines";
string path;
string item;
string expectedResponseFragment;
switch (patternType)
{
case 0:
path = "foo_magazines";
item = "title";
expectedResponseFragment = @"""title"":""Vogue""";
break;
case 1:
path = "bar_magazines";
item = "comic_name";
expectedResponseFragment = @"""comic_name"":""NotVogue""";
break;
case 2:
path = "dbo_OrderItems";
item = "productname";
expectedResponseFragment = @"""productname"":""Sample Product""";
break;
default:
throw new ArgumentException("Invalid pattern type");
}

using HttpRequestMessage restRequest = new(HttpMethod.Get, $"/api/{path}");
using HttpResponseMessage restResponse = await client.SendAsync(restRequest);

string item = isPatternFoo ? "title" : "comic_name";
string graphqlQuery = $@"
{{
{path} {{
Expand All @@ -5848,8 +5871,6 @@ public async Task TestAutoentitiesGeneratedWithDifferentSchemas(string includePa
HttpResponseMessage graphqlResponse = await client.SendAsync(graphqlRequest);

// Assert
string expectedResponseFragment = isPatternFoo ? @"""title"":""Vogue""" : @"""comic_name"":""NotVogue""";

// Verify REST response
Assert.AreEqual(HttpStatusCode.OK, restResponse.StatusCode, "REST request to auto-generated entity should succeed");

Expand Down
37 changes: 24 additions & 13 deletions src/Service.Tests/DatabaseSchema-MsSql.sql
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ DROP TABLE IF EXISTS date_only_table;
DROP TABLE IF EXISTS users;
DROP TABLE IF EXISTS user_profiles;
DROP TABLE IF EXISTS default_books;
DROP TABLE IF EXISTS [Order Items];
DROP SCHEMA IF EXISTS [foo];
DROP SCHEMA IF EXISTS [bar];
COMMIT;
Expand Down Expand Up @@ -321,21 +322,23 @@ CREATE TABLE mappedbookmarks
bkname nvarchar(50) NOT NULL
)

create Table fte_data(
id int IDENTITY(5001,1),
u_id int DEFAULT 2,
name varchar(50),
position varchar(20),
salary int default 20,
PRIMARY KEY(id, u_id)
create Table fte_data
(
id int IDENTITY(5001,1),
u_id int DEFAULT 2,
name varchar(50),
position varchar(20),
salary int default 20,
PRIMARY KEY(id, u_id)
);

create Table intern_data(
id int,
months int default 2 NOT NULL,
name varchar(50),
salary int default 15,
PRIMARY KEY(id, months)
create Table intern_data
(
id int,
months int default 2 NOT NULL,
name varchar(50),
salary int default 15,
PRIMARY KEY(id, months)
);

create table books_sold
Expand Down Expand Up @@ -394,6 +397,11 @@ CREATE TABLE default_books(
title NVARCHAR(100)
);

CREATE TABLE [Order Items](
id INT PRIMARY KEY,
productname VARCHAR(100)
);
Comment thread
RubenCerna2079 marked this conversation as resolved.

ALTER TABLE books
ADD CONSTRAINT book_publisher_fk
FOREIGN KEY (publisher_id)
Expand Down Expand Up @@ -826,3 +834,6 @@ INSERT INTO date_only_table( event_date, event_time, event_timestamp)
VALUES ('2023-01-01', '08:30:00', '2023-01-01 08:30:00'),
('2023-02-15', '12:45:00', '2023-02-15 12:45:00'),
('2023-03-30', '17:15:00', '2023-03-30 17:15:00');

INSERT INTO [Order Items](id, productname)
VALUES (1, 'Sample Product');