diff --git a/src/Marten/Events/Projections/Flattened/KebabConverter.cs b/src/Marten/Events/Projections/Flattened/KebabConverter.cs index 3846add553..3bbde3aefb 100644 --- a/src/Marten/Events/Projections/Flattened/KebabConverter.cs +++ b/src/Marten/Events/Projections/Flattened/KebabConverter.cs @@ -10,11 +10,20 @@ internal static class KebabConverter public static string ToKebabCase(this string str) { // find and replace all parts that starts with one capital letter e.g. Net - var str1 = Regex.Replace(str, "[A-Z][a-z]+", m => $"-{m.ToString().ToLower()}"); + var str1 = KebabConverterRegexExpressions.PascalWordRegex().Replace(str, m => $"-{m.ToString().ToLower()}"); // find and replace all parts that are all capital letter e.g. NET - var str2 = Regex.Replace(str1, "[A-Z]+", m => $"-{m.ToString().ToLower()}"); + var str2 = KebabConverterRegexExpressions.AllCapsWordRegex().Replace(str1, m => $"-{m.ToString().ToLower()}"); return str2.TrimStart('-'); } } + +internal static partial class KebabConverterRegexExpressions +{ + [GeneratedRegex("[A-Z][a-z]+")] + internal static partial Regex PascalWordRegex(); + + [GeneratedRegex("[A-Z]+")] + internal static partial Regex AllCapsWordRegex(); +} diff --git a/src/Marten/Exceptions/MartenCommandNotSupportedException.cs b/src/Marten/Exceptions/MartenCommandNotSupportedException.cs index 4338def02f..d979bfdd3f 100644 --- a/src/Marten/Exceptions/MartenCommandNotSupportedException.cs +++ b/src/Marten/Exceptions/MartenCommandNotSupportedException.cs @@ -41,7 +41,7 @@ public MartenCommandNotSupportedException( NpgsqlCommand? command, Exception innerException, string? message = null - ): base(command, innerException, message) + ) : base(command, innerException, message) { Reason = reason; } @@ -54,7 +54,7 @@ public MartenCommandNotSupportedException( internal class MartenCommandNotSupportedExceptionTransform: IExceptionTransform { - public bool TryTransform(Exception original, [NotNullWhen(true)]out Exception? transformed) + public bool TryTransform(Exception original, [NotNullWhen(true)] out Exception? transformed) { if (original is NpgsqlException e) { @@ -83,13 +83,13 @@ internal sealed class KnownNotSupportedExceptionCause "Full Text Search needs at least Postgres version 10.", NotSupportedReason.FullTextSearchNeedsAtLeastPostgresVersion10, e => e is PostgresException pe && pe.SqlState == PostgresErrorCodes.UndefinedFunction && - new Regex(@"function to_tsvector\((?:regconfig, )?jsonb\) does not exist").IsMatch(pe.Message)); + KnownNotSupportedExceptionCauseRegexExpressions.ToTsvectorOnJsonbRegex().IsMatch(pe.Message)); internal static readonly KnownNotSupportedExceptionCause WebStyleSearch = new( "Full Text Search needs at least Postgres version 10.", NotSupportedReason.WebStyleSearchNeedsAtLeastPostgresVersion11, e => e is PostgresException pe && pe.SqlState == PostgresErrorCodes.UndefinedFunction && - new Regex(@"function websearch_to_tsquery\((?:regconfig, )?text\) does not exist").IsMatch(pe.Message)); + KnownNotSupportedExceptionCauseRegexExpressions.WebStyleSearchRegex().IsMatch(pe.Message)); internal static readonly KnownNotSupportedExceptionCause[] KnownCauses = { ToTsvectorOnJsonb, WebStyleSearch }; private readonly Func match; @@ -109,3 +109,12 @@ internal bool Matches(Exception e) return match(e); } } + +internal static partial class KnownNotSupportedExceptionCauseRegexExpressions +{ + [GeneratedRegex(@"function to_tsvector\((?:regconfig, )?jsonb\) does not exist")] + internal static partial Regex ToTsvectorOnJsonbRegex(); + + [GeneratedRegex(@"function websearch_to_tsquery\((?:regconfig, )?text\) does not exist")] + internal static partial Regex WebStyleSearchRegex(); +} diff --git a/src/Marten/Services/EventStreamUnexpectedMaxEventIdExceptionTransform.cs b/src/Marten/Services/EventStreamUnexpectedMaxEventIdExceptionTransform.cs index 43a8e5594b..16f8da8280 100644 --- a/src/Marten/Services/EventStreamUnexpectedMaxEventIdExceptionTransform.cs +++ b/src/Marten/Services/EventStreamUnexpectedMaxEventIdExceptionTransform.cs @@ -17,10 +17,7 @@ internal class EventStreamUnexpectedMaxEventIdExceptionTransform: IExceptionTran private const string StreamId = "streamid"; private const string Version = "version"; - private static readonly Regex EventStreamUniqueExceptionDetailsRegex = - new(@"\(stream_id, version\)=\((?.*?), (?\w+)\)"); - - public bool TryTransform(Exception original, [NotNullWhen(true)]out Exception? transformed) + public bool TryTransform(Exception original, [NotNullWhen(true)] out Exception? transformed) { if (!Matches(original)) { @@ -37,7 +34,7 @@ public bool TryTransform(Exception original, [NotNullWhen(true)]out Exception? t if (!string.IsNullOrEmpty(postgresException.Detail) && !postgresException.Detail.EqualsIgnoreCase(DetailsRedactedMessage)) { - var details = EventStreamUniqueExceptionDetailsRegex.Match(postgresException.Detail); + var details = EventStreamUnexpectedMaxEventIdExceptionTransformRegexExpressions.EventStreamUniqueExceptionDetailsRegex().Match(postgresException.Detail); if (details.Groups[StreamId].Success) { @@ -72,3 +69,9 @@ private static bool Matches(Exception e) && (pe.ConstraintName == "pk_mt_events_stream_and_version" || pe.ConstraintName == "mt_events_default_stream_id_version_is_archived_idx"); } } + +internal static partial class EventStreamUnexpectedMaxEventIdExceptionTransformRegexExpressions +{ + [GeneratedRegex(@"\(stream_id, version\)=\((?.*?), (?\w+)\)")] + internal static partial Regex EventStreamUniqueExceptionDetailsRegex(); +}