From 412ad85baa9e849242b3fcba49c6844f341ed73d Mon Sep 17 00:00:00 2001 From: mysticmind Date: Thu, 20 Nov 2025 06:41:13 +0530 Subject: [PATCH 1/3] Fix removal of table prefix for meta data columns in index --- .../Bug_3778_schema_name_issue.cs | 18 +++++++++------- src/Marten/Util/StringExtensions.cs | 21 +++++++++++++++---- 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/src/DocumentDbTests/Bug_3778_schema_name_issue.cs b/src/DocumentDbTests/Bug_3778_schema_name_issue.cs index 6f6ff4a85b..b4ccadbe94 100644 --- a/src/DocumentDbTests/Bug_3778_schema_name_issue.cs +++ b/src/DocumentDbTests/Bug_3778_schema_name_issue.cs @@ -3,7 +3,6 @@ using JasperFx; using Marten.Testing; using Marten.Testing.Harness; -using Weasel.Postgresql.Tables; using Xunit; namespace DocumentDbTests.Bugs; @@ -65,7 +64,7 @@ public async Task TestSchemaNameEndingWith_d_In_FulltextIndex(string schemaName) [Theory] [InlineData("pprd")] [InlineData("d")] - public async Task TestSchemaNameEndingWith_d_In_DuplicateFields(string schemaName) + public async Task TestSchemaNameEndingWith_d_In_Btree_index(string schemaName) { StoreOptions(options => { @@ -73,15 +72,20 @@ public async Task TestSchemaNameEndingWith_d_In_DuplicateFields(string schemaNam options.AutoCreateSchemaObjects = AutoCreate.All; options.DatabaseSchemaName = schemaName; options.Schema.For() - .Duplicate(d => d.Manager.Name, configure: idx => + .Metadata(m => { - idx.Name = "idx_manager_name"; - idx.Method = IndexMethod.hash; - }); + m.LastModified.MapTo(f => f.LastModifiedOn); + m.CreatedAt.MapTo(f => f.CreatedOn); + m.Revision.MapTo(f => f.Version); + }) + .Index(f => new { f.CreatedOn, f.IsArchived }) + .UseNumericRevisions(true); + }); await theStore.EnsureStorageExistsAsync(typeof(User3778)); } } -public record User3778(Guid Id, string Name, DateTimeOffset D1, DateOnly D2, User3778 Manager); +public record User3778(Guid Id, string Name, DateTimeOffset D1, DateOnly D2, User3778 Manager, + DateTimeOffset LastModifiedOn, DateTimeOffset CreatedOn, int Version, bool IsArchived); diff --git a/src/Marten/Util/StringExtensions.cs b/src/Marten/Util/StringExtensions.cs index a4bd6975dc..fd581f7f5c 100644 --- a/src/Marten/Util/StringExtensions.cs +++ b/src/Marten/Util/StringExtensions.cs @@ -5,6 +5,7 @@ using System.Text.RegularExpressions; using JasperFx.Core; using JasperFx.Core.Reflection; +using Marten.Schema; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; @@ -45,7 +46,7 @@ public static string ToJsonKey(this MemberInfo member, Casing casing) } /// - /// Remove table alias from a SQL string. This is also a candidate to move to Weasel. + /// Remove table alias from a SQL string. /// /// /// @@ -55,9 +56,21 @@ public static string RemoveTableAlias(this string sql, string tableAlias) if (string.IsNullOrEmpty(sql) || string.IsNullOrEmpty(tableAlias)) return sql; - // Remove 'd.' only when it's NOT followed by 'mt_' (anything followed bt mt_ will be schema name) - var regex = _removeTableAliasRegexCache.GetOrAdd(tableAlias, alias => - new Regex(@$"\b{Regex.Escape(alias)}\.(?!mt_)", RegexOptions.Compiled)); + // First pass: remove '.' for any the Marten defined metadata columns + string[] metadataColumns = [SchemaConstants.DocumentTypeColumn, SchemaConstants.LastModifiedColumn, + SchemaConstants.DotNetTypeColumn, SchemaConstants.VersionColumn, SchemaConstants.CreatedAtColumn, + SchemaConstants.DeletedColumn, SchemaConstants.DeletedAtColumn]; + var metadataColumnRegex = _removeTableAliasRegexCache.GetOrAdd(@$"\b{Regex.Escape(tableAlias)}\.({string.Join("|", metadataColumns)})\b", pattern => + new Regex(pattern, RegexOptions.Compiled)); + sql = metadataColumnRegex.Replace(sql, "$1"); + + if (!sql.Contains($"{tableAlias}.")) + return sql; + + // Second pass: remove '.' only when it's NOT followed by 'mt_' (anything followed by mt_ could possibly be schema name for a Marten function) + var regex = _removeTableAliasRegexCache.GetOrAdd(@$"\b{Regex.Escape(tableAlias)}\.(?!mt_)", pattern => + new Regex(pattern, RegexOptions.Compiled)); + return regex.Replace(sql, ""); } } From 85b569f0dc47a261f25a21c973d5253223d3a02f Mon Sep 17 00:00:00 2001 From: mysticmind Date: Thu, 20 Nov 2025 07:39:58 +0530 Subject: [PATCH 2/3] Refactor unit tests --- .../Bug_3778_schema_name_issue.cs | 91 ------------------- .../Bugs/Bug_3778_schema_name_issue.cs | 0 2 files changed, 91 deletions(-) delete mode 100644 src/DocumentDbTests/Bug_3778_schema_name_issue.cs create mode 100644 src/DocumentDbTests/Bugs/Bug_3778_schema_name_issue.cs diff --git a/src/DocumentDbTests/Bug_3778_schema_name_issue.cs b/src/DocumentDbTests/Bug_3778_schema_name_issue.cs deleted file mode 100644 index b4ccadbe94..0000000000 --- a/src/DocumentDbTests/Bug_3778_schema_name_issue.cs +++ /dev/null @@ -1,91 +0,0 @@ -using System; -using System.Threading.Tasks; -using JasperFx; -using Marten.Testing; -using Marten.Testing.Harness; -using Xunit; - -namespace DocumentDbTests.Bugs; - -public class Bug_3778_schema_name__ending_with_d_issue: OneOffConfigurationsContext -{ - [Theory] - [InlineData("pprd")] - [InlineData("d")] - public async Task TestSchemaNameEndingWith_d_In_Index(string schemaName) - { - StoreOptions(options => - { - options.Connection(ConnectionSource.ConnectionString); - options.AutoCreateSchemaObjects = AutoCreate.All; - options.DatabaseSchemaName = schemaName; - options.Schema.For() - .Index(d => d.D1) - .Index(d => d.D2); - }); - - await theStore.EnsureStorageExistsAsync(typeof(User3778)); - } - - [Theory] - [InlineData("pprd")] - [InlineData("d")] - public async Task TestSchemaNameEndingWith_d_In_NGramIndex(string schemaName) - { - StoreOptions(options => - { - options.Connection(ConnectionSource.ConnectionString); - options.AutoCreateSchemaObjects = AutoCreate.All; - options.DatabaseSchemaName = schemaName; - options.Schema.For() - .NgramIndex(d => d.Name); - }); - - await theStore.EnsureStorageExistsAsync(typeof(User3778)); - } - - [Theory] - [InlineData("pprd")] - [InlineData("d")] - public async Task TestSchemaNameEndingWith_d_In_FulltextIndex(string schemaName) - { - StoreOptions(options => - { - options.Connection(ConnectionSource.ConnectionString); - options.AutoCreateSchemaObjects = AutoCreate.All; - options.DatabaseSchemaName = schemaName; - options.Schema.For() - .FullTextIndex(d => d.Name); - }); - - await theStore.EnsureStorageExistsAsync(typeof(User3778)); - } - - [Theory] - [InlineData("pprd")] - [InlineData("d")] - public async Task TestSchemaNameEndingWith_d_In_Btree_index(string schemaName) - { - StoreOptions(options => - { - options.Connection(ConnectionSource.ConnectionString); - options.AutoCreateSchemaObjects = AutoCreate.All; - options.DatabaseSchemaName = schemaName; - options.Schema.For() - .Metadata(m => - { - m.LastModified.MapTo(f => f.LastModifiedOn); - m.CreatedAt.MapTo(f => f.CreatedOn); - m.Revision.MapTo(f => f.Version); - }) - .Index(f => new { f.CreatedOn, f.IsArchived }) - .UseNumericRevisions(true); - - }); - - await theStore.EnsureStorageExistsAsync(typeof(User3778)); - } -} - -public record User3778(Guid Id, string Name, DateTimeOffset D1, DateOnly D2, User3778 Manager, - DateTimeOffset LastModifiedOn, DateTimeOffset CreatedOn, int Version, bool IsArchived); diff --git a/src/DocumentDbTests/Bugs/Bug_3778_schema_name_issue.cs b/src/DocumentDbTests/Bugs/Bug_3778_schema_name_issue.cs new file mode 100644 index 0000000000..e69de29bb2 From 6b41029b355790da42946d2691e1191432696d3d Mon Sep 17 00:00:00 2001 From: mysticmind Date: Thu, 20 Nov 2025 07:46:51 +0530 Subject: [PATCH 3/3] Refactor unit tests --- .../Bugs/Bug_3778_schema_name_issue.cs | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/src/DocumentDbTests/Bugs/Bug_3778_schema_name_issue.cs b/src/DocumentDbTests/Bugs/Bug_3778_schema_name_issue.cs index e69de29bb2..c0f939d35b 100644 --- a/src/DocumentDbTests/Bugs/Bug_3778_schema_name_issue.cs +++ b/src/DocumentDbTests/Bugs/Bug_3778_schema_name_issue.cs @@ -0,0 +1,48 @@ +using System; +using System.Threading.Tasks; +using JasperFx; +using Marten.Testing; +using Marten.Testing.Harness; +using Weasel.Postgresql.Tables; +using Xunit; + +namespace DocumentDbTests.Bugs; + +public class Bug_3778_schema_name__ending_with_d_issue: OneOffConfigurationsContext +{ + [Theory] + [InlineData("pprd")] + [InlineData("d")] + public async Task TestSchemaNameEndingWith_d_In_Index(string schemaName) + { + StoreOptions(options => + { + options.Connection(ConnectionSource.ConnectionString); + options.AutoCreateSchemaObjects = AutoCreate.All; + options.DatabaseSchemaName = schemaName; + options.Schema.For() + .Index(d => d.D1) + .Index(d => d.D2) + .NgramIndex(d => d.Name) + .FullTextIndex(d => d.Name) + .Duplicate(d => d.Manager.Name, configure: idx => + { + idx.Name = "idx_manager_name"; + idx.Method = IndexMethod.hash; + }) + .Metadata(m => + { + m.LastModified.MapTo(f => f.LastModifiedOn); + m.CreatedAt.MapTo(f => f.CreatedOn); + m.Revision.MapTo(f => f.Version); + }) + .Index(f => new { f.CreatedOn, f.IsArchived }) + .UseNumericRevisions(true); + }); + + await theStore.EnsureStorageExistsAsync(typeof(User3778)); + } +} + +public record User3778(Guid Id, string Name, DateTimeOffset D1, DateOnly D2, User3778 Manager, + DateTimeOffset LastModifiedOn, DateTimeOffset CreatedOn, int Version, bool IsArchived);