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 6f6ff4a85b..0000000000 --- a/src/DocumentDbTests/Bug_3778_schema_name_issue.cs +++ /dev/null @@ -1,87 +0,0 @@ -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); - }); - - 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_DuplicateFields(string schemaName) - { - StoreOptions(options => - { - options.Connection(ConnectionSource.ConnectionString); - options.AutoCreateSchemaObjects = AutoCreate.All; - options.DatabaseSchemaName = schemaName; - options.Schema.For() - .Duplicate(d => d.Manager.Name, configure: idx => - { - idx.Name = "idx_manager_name"; - idx.Method = IndexMethod.hash; - }); - }); - - await theStore.EnsureStorageExistsAsync(typeof(User3778)); - } -} - -public record User3778(Guid Id, string Name, DateTimeOffset D1, DateOnly D2, User3778 Manager); 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..c0f939d35b --- /dev/null +++ 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); 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, ""); } }