diff --git a/DubUrl.Adomd.Testing/Rewriting/PowerBiDesktopRewriterTest.cs b/DubUrl.Adomd.Testing/Rewriting/PowerBiDesktopRewriterTest.cs index f09795a6..7b146dd9 100644 --- a/DubUrl.Adomd.Testing/Rewriting/PowerBiDesktopRewriterTest.cs +++ b/DubUrl.Adomd.Testing/Rewriting/PowerBiDesktopRewriterTest.cs @@ -67,7 +67,6 @@ public void Map_UrlInfoWithPortAndSegment_DataSource(string input) [Test] [TestCase("foo/bar")] - [TestCase("./foo/bar")] [TestCase("./foo?bar=brz")] public void Map_InvalidUrlInfo_DataSource(string input) { @@ -80,6 +79,19 @@ public void Map_InvalidUrlInfo_DataSource(string input) Assert.Throws(() => Rewriter.Execute(urlInfo)); } + [Test] + [TestCase("./foo/bar")] + public void Map_InvalidUrlInfo_TooManySegments(string input) + { + var discoverer = new Mock(); + discoverer.Setup(x => x.GetPowerBiProcesses(false)) + .Returns(new[] { new PowerBiProcess("foo", 12345, PowerBiType.PowerBI) }); + + var urlInfo = new UrlInfo() { Host = input.Split('/')[0], Segments = input.Split('/').Skip(1).ToArray() }; + var Rewriter = new PowerBiDesktopRewriter(ConnectionStringBuilder, discoverer.Object); + Assert.Throws(() => Rewriter.Execute(urlInfo)); + } + [Test] public void Map_UrlInfo_DiscovererInteraction() { diff --git a/DubUrl.Adomd/Rewriting/PowerBiDesktopRewriter.cs b/DubUrl.Adomd/Rewriting/PowerBiDesktopRewriter.cs index 7e24af42..f2da653c 100644 --- a/DubUrl.Adomd/Rewriting/PowerBiDesktopRewriter.cs +++ b/DubUrl.Adomd/Rewriting/PowerBiDesktopRewriter.cs @@ -15,8 +15,8 @@ namespace DubUrl.Adomd.Rewriting { internal class PowerBiDesktopRewriter : ConnectionStringRewriter { + private const string EXCEPTION_DATABASE_NAME = "Power BI Desktop"; protected internal const string SERVER_KEYWORD = "Data Source"; - protected internal const string DEFAULT_LOCALHOST = "localhost"; protected internal static readonly string[] VALID_HOSTS = new[] { "127.0.0.1", ".", string.Empty, DEFAULT_LOCALHOST }; @@ -56,9 +56,12 @@ public override void Execute(UrlInfo urlInfo) public int GetPortFromSegments(string[] segments) { + if(segments==null || !segments.Any()) + throw new InvalidConnectionUrlMissingSegmentsException(EXCEPTION_DATABASE_NAME); + var pbiName = segments.Length == 1 ? segments[0] - : throw new ArgumentOutOfRangeException(nameof(segments)); + : throw new InvalidConnectionUrlTooManySegmentsException(EXCEPTION_DATABASE_NAME, segments); var processes = Discoverer.GetPowerBiProcesses(); if (processes.Any(x => x.Name == pbiName)) diff --git a/DubUrl.Core/Parsing/Parser.cs b/DubUrl.Core/Parsing/Parser.cs index abdf677d..dbb721e6 100644 --- a/DubUrl.Core/Parsing/Parser.cs +++ b/DubUrl.Core/Parsing/Parser.cs @@ -1,4 +1,5 @@ using DubUrl.Mapping; +using DubUrl.Rewriting; using System; using System.Collections.Generic; using System.Data.Common; @@ -52,7 +53,7 @@ public virtual UrlInfo Parse(string url) if (key != null) { if (options.ContainsKey(key)) - throw new ArgumentException(); + throw new InvalidConnectionUrlException("The query string cannot contains twice the same keyword."); var value = nameValues[key]; if (value != null) options.Add(key, value); diff --git a/DubUrl.Core/Rewriting/Implementation/Db2Rewriter.cs b/DubUrl.Core/Rewriting/Implementation/Db2Rewriter.cs index 0f45cb20..399cff32 100644 --- a/DubUrl.Core/Rewriting/Implementation/Db2Rewriter.cs +++ b/DubUrl.Core/Rewriting/Implementation/Db2Rewriter.cs @@ -12,6 +12,7 @@ namespace DubUrl.Rewriting.Implementation { internal class Db2Rewriter : ConnectionStringRewriter { + private const string EXCEPTION_DATABASE_NAME = "DB2"; internal const string SERVER_KEYWORD = "Server"; internal const string DATABASE_KEYWORD = "Database"; internal const string USERNAME_KEYWORD = "User ID"; @@ -42,10 +43,12 @@ internal class DatabaseMapper : BaseTokenMapper { public override void Execute(UrlInfo urlInfo) { - if (urlInfo.Segments.Length == 1) + if (urlInfo.Segments == null || !urlInfo.Segments.Any()) + throw new InvalidConnectionUrlMissingSegmentsException(EXCEPTION_DATABASE_NAME); + else if (urlInfo.Segments.Length == 1) Specificator.Execute(DATABASE_KEYWORD, urlInfo.Segments.First()); else - throw new ArgumentOutOfRangeException(); + throw new InvalidConnectionUrlTooManySegmentsException(EXCEPTION_DATABASE_NAME, urlInfo.Segments); } } diff --git a/DubUrl.Core/Rewriting/Implementation/DrillOdbcRewriter.cs b/DubUrl.Core/Rewriting/Implementation/DrillOdbcRewriter.cs index b4aba24c..24aae445 100644 --- a/DubUrl.Core/Rewriting/Implementation/DrillOdbcRewriter.cs +++ b/DubUrl.Core/Rewriting/Implementation/DrillOdbcRewriter.cs @@ -1,5 +1,7 @@ using DubUrl.Locating.OdbcDriver; using DubUrl.Locating.Options; +using DubUrl.Mapping; +using DubUrl.Mapping.Database; using DubUrl.Parsing; using DubUrl.Rewriting.Tokening; using System; @@ -15,6 +17,7 @@ namespace DubUrl.Rewriting.Implementation { public class DrillOdbcRewriter : OdbcRewriter, IOdbcConnectionStringRewriter { + private const string EXCEPTION_DATABASE_NAME = "ODBC for Apache Drill"; protected internal const string PORT_KEYWORD = "Port"; protected internal const string SCHEMA_KEYWORD = "Schema"; protected internal const string AUTHENTICATION_KEYWORD = "AuthenticationType"; @@ -80,7 +83,7 @@ public override void Execute(UrlInfo urlInfo) if (urlInfo.Segments.Length == 1 || (urlInfo.Segments.Length == 2 && urlInfo.Segments.First() == "DRILL")) Specificator.Execute(SCHEMA_KEYWORD, urlInfo.Segments.Last()); else if (urlInfo.Segments.Length > 1) - throw new ArgumentOutOfRangeException(); + throw new InvalidConnectionUrlTooManySegmentsException(EXCEPTION_DATABASE_NAME, urlInfo.Segments); } } diff --git a/DubUrl.Core/Rewriting/Implementation/DuckdbRewriter.cs b/DubUrl.Core/Rewriting/Implementation/DuckdbRewriter.cs index b27e7c0a..f381486a 100644 --- a/DubUrl.Core/Rewriting/Implementation/DuckdbRewriter.cs +++ b/DubUrl.Core/Rewriting/Implementation/DuckdbRewriter.cs @@ -34,7 +34,7 @@ public override void Execute(UrlInfo urlInfo) if (!urlInfo.Segments.Any()) segments.Add(":memory:"); else - throw new ArgumentOutOfRangeException($"Expecting no segment in the connectionUrl because the InMemory mode was activated by specifying the host '{urlInfo.Host}' but get {urlInfo.Segments.Length} segments. The list of segments was '{string.Join("', '", urlInfo.Segments.ToArray())}'"); + throw new InvalidConnectionUrlException($"Expecting no segment in the connectionUrl because the InMemory mode was activated by specifying the host '{urlInfo.Host}' but get {urlInfo.Segments.Length} segments. The list of segments was '{string.Join("', '", urlInfo.Segments.ToArray())}'"); } else if (string.IsNullOrEmpty(urlInfo.Host) && urlInfo.Segments.Length > 1 && string.IsNullOrEmpty(urlInfo.Segments[0])) segments = urlInfo.Segments.Skip(1).ToList(); @@ -52,7 +52,7 @@ public override void Execute(UrlInfo urlInfo) private static string BuildPath(IEnumerable segments) { if (segments == null || !segments.Any()) - throw new ArgumentException(); + throw new InvalidConnectionUrlMissingSegmentsException("DuckDB"); var path = new StringBuilder(); foreach (var segment in segments) diff --git a/DubUrl.Core/Rewriting/Implementation/MsSqlServerRewriter.cs b/DubUrl.Core/Rewriting/Implementation/MsSqlServerRewriter.cs index 62928ea6..f5b2ed0d 100644 --- a/DubUrl.Core/Rewriting/Implementation/MsSqlServerRewriter.cs +++ b/DubUrl.Core/Rewriting/Implementation/MsSqlServerRewriter.cs @@ -66,7 +66,7 @@ public override void Execute(UrlInfo urlInfo) if (urlInfo.Segments.Length > 0 && urlInfo.Segments.Length <= 2) Specificator.Execute(DATABASE_KEYWORD, urlInfo.Segments.Last()); else - throw new ArgumentOutOfRangeException($"Expecting one or two segments in the connectionUrl but was {urlInfo.Segments.Length} segments. The list of segments was '{string.Join("', '", urlInfo.Segments.ToArray())}'"); + throw new InvalidConnectionUrlException($"The connection-url for Microsoft SQL Server is expecting one or two segments. This connection-url is containing {urlInfo.Segments.Length} segments: '{string.Join("', '", urlInfo.Segments.ToArray())}'"); } } } diff --git a/DubUrl.Core/Rewriting/Implementation/MySqlConnectorRewriter.cs b/DubUrl.Core/Rewriting/Implementation/MySqlConnectorRewriter.cs index c5abd490..98ec41e6 100644 --- a/DubUrl.Core/Rewriting/Implementation/MySqlConnectorRewriter.cs +++ b/DubUrl.Core/Rewriting/Implementation/MySqlConnectorRewriter.cs @@ -11,6 +11,7 @@ namespace DubUrl.Rewriting.Implementation { internal class MySqlConnectorRewriter : ConnectionStringRewriter { + private const string EXCEPTION_DATABASE_NAME = "MySQL"; protected internal const string SERVER_KEYWORD = "Server"; protected internal const string PORT_KEYWORD = "Port"; protected internal const string DATABASE_KEYWORD = "Database"; @@ -59,12 +60,12 @@ internal class DatabaseMapper : BaseTokenMapper { public override void Execute(UrlInfo urlInfo) { - if (urlInfo.Segments.Length == 1) + if (urlInfo.Segments==null || !urlInfo.Segments.Any()) + throw new InvalidConnectionUrlMissingSegmentsException(EXCEPTION_DATABASE_NAME); + else if (urlInfo.Segments.Length == 1) Specificator.Execute(DATABASE_KEYWORD, urlInfo.Segments.First()); else if (urlInfo.Segments.Length > 1) - throw new ArgumentOutOfRangeException(nameof(urlInfo), $"The connection-url contains more than one segment '{string.Join("', '", urlInfo.Segments)}'. For MySQL, exactly one segment is expected."); - else - throw new ArgumentOutOfRangeException(nameof(urlInfo), $"The connection-url contains no segment. For MySQL, exactly one segment is expected."); + throw new InvalidConnectionUrlTooManySegmentsException(EXCEPTION_DATABASE_NAME, urlInfo.Segments); } } } diff --git a/DubUrl.Core/Rewriting/Implementation/OdbcDbqRewriter.cs b/DubUrl.Core/Rewriting/Implementation/OdbcDbqRewriter.cs index c1ace960..a8170b2c 100644 --- a/DubUrl.Core/Rewriting/Implementation/OdbcDbqRewriter.cs +++ b/DubUrl.Core/Rewriting/Implementation/OdbcDbqRewriter.cs @@ -51,7 +51,7 @@ public override void Execute(UrlInfo urlInfo) private static string BuildPath(IEnumerable segments) { if (segments == null || !segments.Any()) - throw new ArgumentException(); + throw new InvalidConnectionUrlMissingSegmentsException("ODBC DBQ"); var path = new StringBuilder(); foreach (var segment in segments) @@ -72,7 +72,6 @@ public DriverMapper(DriverLocatorFactory driverLocatorFactory) public override void Execute(UrlInfo urlInfo) { - if (!urlInfo.Options.ContainsKey(DRIVER_KEYWORD)) { var otherSchemes = urlInfo.Schemes.Where(x => x != "odbc"); @@ -112,7 +111,7 @@ public override void Execute(UrlInfo urlInfo) foreach (var remainingOption in remainingOptions) { if (Enum.TryParse(remainingOption, scheme, out var value)) - options.Add(remainingOption, value ?? throw new ArgumentNullException()); + options.Add(remainingOption, value ?? throw new InvalidConnectionUrlException($"Connection Url for ODBC DBQ is specifying an unexpected value 'null' for option '{remainingOption.Name}'")); } } var driverLocator = DriverLocatorFactory.Instantiate(secondScheme, options); diff --git a/DubUrl.Core/Rewriting/Implementation/OdbcRewriter.cs b/DubUrl.Core/Rewriting/Implementation/OdbcRewriter.cs index ad4bd164..b168369f 100644 --- a/DubUrl.Core/Rewriting/Implementation/OdbcRewriter.cs +++ b/DubUrl.Core/Rewriting/Implementation/OdbcRewriter.cs @@ -9,11 +9,11 @@ using System.Text; using System.Threading.Tasks; - namespace DubUrl.Rewriting.Implementation { public class OdbcRewriter : ConnectionStringRewriter, IOdbcConnectionStringRewriter { + private const string EXCEPTION_DATABASE_NAME = "ODBC"; protected internal const string SERVER_KEYWORD = "Server"; protected internal const string DATABASE_KEYWORD = "Database"; protected internal const string USERNAME_KEYWORD = "Uid"; @@ -39,7 +39,7 @@ protected OdbcRewriter(DbConnectionStringBuilder csb, BaseTokenMapper[] tokenMap internal DriverLocatorFactory DriverLocatorFactory => (TokenMappers.Single(x => x is DriverMapper) as DriverMapper)?.DriverLocatorFactory - ?? throw new ArgumentNullException(); + ?? throw new NullReferenceException(); protected internal class HostMapper : BaseTokenMapper { @@ -67,7 +67,6 @@ public DriverMapper(DriverLocatorFactory driverLocatorFactory) public override void Execute(UrlInfo urlInfo) { - if (!urlInfo.Options.ContainsKey(DRIVER_KEYWORD)) { var otherSchemes = urlInfo.Schemes.Where(x => x != "odbc"); @@ -107,7 +106,7 @@ public override void Execute(UrlInfo urlInfo) foreach (var remainingOption in remainingOptions) { if (Enum.TryParse(remainingOption, scheme, out var value)) - options.Add(remainingOption, value ?? throw new ArgumentNullException()); + options.Add(remainingOption, value ?? throw new InvalidConnectionUrlException($"Connection Url for ODBC is specifying an unexpected value 'null' for option '{remainingOption.Name}'")); } } var driverLocator = DriverLocatorFactory.Instantiate(secondScheme, options); @@ -146,7 +145,7 @@ public override void Execute(UrlInfo urlInfo) if (urlInfo.Segments.Length <= 2) Specificator.Execute(DATABASE_KEYWORD, urlInfo.Segments.Last()); else - throw new ArgumentOutOfRangeException(); + throw new InvalidConnectionUrlTooManySegmentsException(EXCEPTION_DATABASE_NAME, urlInfo.Segments); } } @@ -160,7 +159,7 @@ public override void Execute(UrlInfo urlInfo) { if (!option.Value.StartsWith("{") || !option.Value.EndsWith("}")) if (option.Value.StartsWith("{") ^ option.Value.EndsWith("}")) - throw new ArgumentOutOfRangeException($"The value of the option '{DRIVER_KEYWORD}' must start with a '{{' and end with '}}' or both should be missing. The value was '{option.Value}'"); + throw new InvalidConnectionUrlException($"The value of the option '{DRIVER_KEYWORD}' must start with a '{{' and end with '}}' or both should be missing. The value was '{option.Value}'"); else Specificator.Execute(option.Key, $"{{{option.Value}}}"); else diff --git a/DubUrl.Core/Rewriting/Implementation/OracleManagedDataAccessRewriter.cs b/DubUrl.Core/Rewriting/Implementation/OracleManagedDataAccessRewriter.cs index bbfeab06..5df0ff83 100644 --- a/DubUrl.Core/Rewriting/Implementation/OracleManagedDataAccessRewriter.cs +++ b/DubUrl.Core/Rewriting/Implementation/OracleManagedDataAccessRewriter.cs @@ -11,6 +11,7 @@ namespace DubUrl.Rewriting.Implementation { internal class OracleManagedDataAccessRewriter : ConnectionStringRewriter { + private const string EXCEPTION_DATABASE_NAME = "Oracle Managed Data Access"; protected internal const string DATASOURCE_KEYWORD = "DATA SOURCE"; protected internal const string SERVER_KEYWORD = "HOST"; protected internal const string PORT_KEYWORD = "PORT"; @@ -61,7 +62,7 @@ public override void Execute(UrlInfo urlInfo) $"({SERVER_KEYWORD}={urlInfo.Host})({PORT_KEYWORD}={(urlInfo.Port > 0 ? urlInfo.Port : 1521)}))(CONNECT_DATA=" + $"({DATABASE_KEYWORD}={urlInfo.Segments.First()})))"); else - throw new ArgumentOutOfRangeException(); + throw new InvalidConnectionUrlTooManySegmentsException(EXCEPTION_DATABASE_NAME, urlInfo.Segments); } } } diff --git a/DubUrl.Core/Rewriting/Implementation/PostgresqlRewriter.cs b/DubUrl.Core/Rewriting/Implementation/PostgresqlRewriter.cs index 17e34c89..8e6efc35 100644 --- a/DubUrl.Core/Rewriting/Implementation/PostgresqlRewriter.cs +++ b/DubUrl.Core/Rewriting/Implementation/PostgresqlRewriter.cs @@ -11,6 +11,7 @@ namespace DubUrl.Rewriting.Implementation { internal class PostgresqlRewriter : ConnectionStringRewriter { + private const string EXCEPTION_DATABASE_NAME = "Postgresql"; protected internal const string SERVER_KEYWORD = "Host"; protected internal const string PORT_KEYWORD = "Port"; protected internal const string DATABASE_KEYWORD = "Database"; @@ -68,10 +69,12 @@ internal class DatabaseMapper : BaseTokenMapper { public override void Execute(UrlInfo urlInfo) { - if (urlInfo.Segments.Length == 1) + if (urlInfo.Segments==null || !urlInfo.Segments.Any()) + throw new InvalidConnectionUrlMissingSegmentsException(EXCEPTION_DATABASE_NAME); + else if (urlInfo.Segments.Length == 1) Specificator.Execute(DATABASE_KEYWORD, urlInfo.Segments.First()); else - throw new ArgumentOutOfRangeException($"Expecting a single segment in the connectionUrl but found {urlInfo.Segments.Length} segments. The list of segments was '{string.Join("', '", urlInfo.Segments.ToArray())}'"); + throw new InvalidConnectionUrlTooManySegmentsException(EXCEPTION_DATABASE_NAME, urlInfo.Segments); } } } diff --git a/DubUrl.Core/Rewriting/Implementation/QuestDbOdbcRewriter.cs b/DubUrl.Core/Rewriting/Implementation/QuestDbOdbcRewriter.cs index c4bb7528..c4f63bf1 100644 --- a/DubUrl.Core/Rewriting/Implementation/QuestDbOdbcRewriter.cs +++ b/DubUrl.Core/Rewriting/Implementation/QuestDbOdbcRewriter.cs @@ -47,7 +47,7 @@ public override void Execute(UrlInfo urlInfo) public override void Execute(UrlInfo urlInfo) { if (string.IsNullOrEmpty(urlInfo.Username) || string.IsNullOrEmpty(urlInfo.Password)) - throw new ArgumentOutOfRangeException($"Username and Password are mandatory for QuestDb."); + throw new InvalidConnectionUrlException($"Username and Password are mandatory for QuestDb."); Specificator.Execute(USERNAME_KEYWORD, urlInfo.Username); Specificator.Execute(PASSWORD_KEYWORD, urlInfo.Password); diff --git a/DubUrl.Core/Rewriting/Implementation/QuestDbRewriter.cs b/DubUrl.Core/Rewriting/Implementation/QuestDbRewriter.cs index 1ee377e3..eda10ddd 100644 --- a/DubUrl.Core/Rewriting/Implementation/QuestDbRewriter.cs +++ b/DubUrl.Core/Rewriting/Implementation/QuestDbRewriter.cs @@ -45,9 +45,9 @@ public override void Execute(UrlInfo urlInfo) if (urlInfo.Segments[0] == DEFAULT_DATABASE || urlInfo.Segments[0] == string.Empty) Specificator.Execute(DATABASE_KEYWORD, DEFAULT_DATABASE); else - throw new ArgumentOutOfRangeException($"One a segment is provided in the connectionUrl it must be '{DEFAULT_DATABASE}'. The segment was '{urlInfo.Segments[0]}'"); + throw new InvalidConnectionUrlException($"One a segment is provided in the connectionUrl it must be '{DEFAULT_DATABASE}'. The segment was '{urlInfo.Segments[0]}'"); else - throw new ArgumentOutOfRangeException($"QuestDb is expecting a maximum of 1 segment and it should be '{DEFAULT_DATABASE}'. The connectionUrl has {urlInfo.Segments.Length} segments: '{string.Join(", ", urlInfo.Segments)}'"); + throw new InvalidConnectionUrlException($"QuestDb is expecting a maximum of 1 segment and it should be '{DEFAULT_DATABASE}'. The connectionUrl has {urlInfo.Segments.Length} segments: '{string.Join(", ", urlInfo.Segments)}'"); } } @@ -56,7 +56,7 @@ public override void Execute(UrlInfo urlInfo) public override void Execute(UrlInfo urlInfo) { if (string.IsNullOrEmpty(urlInfo.Username) || string.IsNullOrEmpty(urlInfo.Password)) - throw new ArgumentOutOfRangeException($"Username and Password are mandatory for QuestDb."); + throw new InvalidConnectionUrlException($"Username and Password are mandatory for QuestDb."); Specificator.Execute(USERNAME_KEYWORD, urlInfo.Username); Specificator.Execute(PASSWORD_KEYWORD, urlInfo.Password); @@ -69,15 +69,16 @@ public override void Execute(UrlInfo urlInfo) { var unexpected = urlInfo.Options.Keys.Except(new[] { STATEMENT_TIMEOUT, COMMAND_TIMEOUT, SERVER_COMPATIBILITY_MODE }); if (unexpected.Any()) - throw new ArgumentOutOfRangeException($"QuestDb is accepting an option named '{STATEMENT_TIMEOUT}' (or its alias '{COMMAND_TIMEOUT}') and also an option named '{SERVER_COMPATIBILITY_MODE}'. The options '{string.Join("', '", unexpected)}' are not supported."); + throw new InvalidConnectionUrlException($"QuestDb is accepting an option named '{STATEMENT_TIMEOUT}' (or its alias '{COMMAND_TIMEOUT}') and also an option named '{SERVER_COMPATIBILITY_MODE}'. The options '{string.Join("', '", unexpected)}' are not supported."); else if (urlInfo.Options.ContainsKey(STATEMENT_TIMEOUT) && urlInfo.Options.ContainsKey(COMMAND_TIMEOUT)) - throw new ArgumentOutOfRangeException($"QuestDb is accepting an option named '{STATEMENT_TIMEOUT}' or its alias '{COMMAND_TIMEOUT}' and also an option named '{SERVER_COMPATIBILITY_MODE}'. You cannot specify both of '{COMMAND_TIMEOUT}' and '{STATEMENT_TIMEOUT}'."); + throw new InvalidConnectionUrlException($"QuestDb is accepting an option named '{STATEMENT_TIMEOUT}' or its alias '{COMMAND_TIMEOUT}' and also an option named '{SERVER_COMPATIBILITY_MODE}'. You cannot specify both of '{COMMAND_TIMEOUT}' and '{STATEMENT_TIMEOUT}'."); else { if (!urlInfo.Options.ContainsKey(SERVER_COMPATIBILITY_MODE)) urlInfo.Options.Add(SERVER_COMPATIBILITY_MODE, NO_TYPE_LOADING); else if (urlInfo.Options[SERVER_COMPATIBILITY_MODE] != NO_TYPE_LOADING) - throw new ArgumentOutOfRangeException($"QuestDb is accepting a single value '{NO_TYPE_LOADING}' for the option named '{SERVER_COMPATIBILITY_MODE}'. The value '{urlInfo.Options[SERVER_COMPATIBILITY_MODE]}' is not supported."); + throw new InvalidConnectionUrlException($"QuestDb is accepting a single value '{NO_TYPE_LOADING}' for the option named '{SERVER_COMPATIBILITY_MODE}'. The value '{urlInfo.Options[SERVER_COMPATIBILITY_MODE]}' is not supported."); + if (urlInfo.Options.TryGetValue(STATEMENT_TIMEOUT, out string? timeout)) { urlInfo.Options.Add(COMMAND_TIMEOUT, timeout); diff --git a/DubUrl.Core/Rewriting/Implementation/SqliteRewriter.cs b/DubUrl.Core/Rewriting/Implementation/SqliteRewriter.cs index 28a399e4..0e321551 100644 --- a/DubUrl.Core/Rewriting/Implementation/SqliteRewriter.cs +++ b/DubUrl.Core/Rewriting/Implementation/SqliteRewriter.cs @@ -42,7 +42,7 @@ public override void Execute(UrlInfo urlInfo) private static string BuildPath(IEnumerable segments) { if (segments == null || !segments.Any()) - throw new ArgumentException(); + throw new InvalidConnectionUrlMissingSegmentsException("Sqlite"); var path = new StringBuilder(); foreach (var segment in segments) diff --git a/DubUrl.Core/Rewriting/Implementation/TeradataRewriter.cs b/DubUrl.Core/Rewriting/Implementation/TeradataRewriter.cs index 96f1f465..f5984d4b 100644 --- a/DubUrl.Core/Rewriting/Implementation/TeradataRewriter.cs +++ b/DubUrl.Core/Rewriting/Implementation/TeradataRewriter.cs @@ -11,6 +11,7 @@ namespace DubUrl.Rewriting.Implementation { internal class TeradataRewriter : ConnectionStringRewriter { + private const string EXCEPTION_DATABASE_NAME = "Teradata"; internal const string SERVER_KEYWORD = "Data Source"; internal const string PORT_KEYWORD = "Port Number"; internal const string DATABASE_KEYWORD = "Database"; @@ -55,7 +56,7 @@ public override void Execute(UrlInfo urlInfo) else if (urlInfo.Segments.Length == 1) Specificator.Execute(DATABASE_KEYWORD, urlInfo.Segments.First()); else - throw new ArgumentOutOfRangeException(); + throw new InvalidConnectionUrlTooManySegmentsException(EXCEPTION_DATABASE_NAME, urlInfo.Segments); } } diff --git a/DubUrl.Core/Rewriting/InvalidConnectionUrlException.cs b/DubUrl.Core/Rewriting/InvalidConnectionUrlException.cs index 1c69dda2..82ecc67b 100644 --- a/DubUrl.Core/Rewriting/InvalidConnectionUrlException.cs +++ b/DubUrl.Core/Rewriting/InvalidConnectionUrlException.cs @@ -11,4 +11,22 @@ public class InvalidConnectionUrlException : DubUrlException public InvalidConnectionUrlException(string message) : base(message) { } } + + public class InvalidConnectionUrlTooManySegmentsException : InvalidConnectionUrlException + { + public InvalidConnectionUrlTooManySegmentsException(string database, string[] segments) + : base($"Connection-url for {database} is not expecting more than a single segment. This connection-url is containing {segments.Length} segments: '{string.Join("', '", segments)}'.") { } + + public InvalidConnectionUrlTooManySegmentsException(string database, string[] segments, int countMaxExpected) + : base($"Connection-url for {database} is not expecting more than {countMaxExpected} segments. This connection-url is containing {segments.Length} segments: '{string.Join("', '", segments)}'.") { } + } + + public class InvalidConnectionUrlMissingSegmentsException : InvalidConnectionUrlException + { + public InvalidConnectionUrlMissingSegmentsException(string database) + : base($"Connection-url for {database} is expecting a minimum of one segment. This connection-url is not containing any segment") { } + + public InvalidConnectionUrlMissingSegmentsException(string database, string[] segments, int countMinExpected) + : base($"Connection-url for {database} is expecting a minimum of {countMinExpected} segments. This connection-url is {(segments.Length==0 ? "not containing any segment" : $"{segments.Length} segments: '{string.Join("', '", segments)}'")}") { } + } } diff --git a/DubUrl.Testing/Rewriting/Implementation/QuestDbRewriterTest.cs b/DubUrl.Testing/Rewriting/Implementation/QuestDbRewriterTest.cs index 5b61be61..6bc9ab75 100644 --- a/DubUrl.Testing/Rewriting/Implementation/QuestDbRewriterTest.cs +++ b/DubUrl.Testing/Rewriting/Implementation/QuestDbRewriterTest.cs @@ -3,6 +3,7 @@ using System.Data.Common; using Npgsql; using DubUrl.Rewriting.Implementation; +using DubUrl.Rewriting; namespace DubUrl.Testing.Rewriting.Implementation { @@ -62,7 +63,7 @@ public void Map_UnexpectedUrlInfo_Throws(string segmentsList) { var urlInfo = new UrlInfo() { Segments = segmentsList.Split('/') }; var Rewriter = new QuestDbRewriter(ConnectionStringBuilder); - var ex = Assert.Throws(() => Rewriter.Execute(urlInfo)); + var ex = Assert.Throws(() => Rewriter.Execute(urlInfo)); } [Test] @@ -87,7 +88,7 @@ public void Map_UrlInfoWithoutUsernamePassword_Throws(string username, string pa { var urlInfo = new UrlInfo() { Username = username, Password = password }; var Rewriter = new QuestDbRewriter(ConnectionStringBuilder); - var ex = Assert.Throws(() => Rewriter.Execute(urlInfo)); + var ex = Assert.Throws(() => Rewriter.Execute(urlInfo)); } [Test] @@ -140,7 +141,7 @@ public void Map_UnexpectedServerCompatibilityMode_Throws() urlInfo.Options.Add("ServerCompatibilityMode", "ANY VALUE"); var Rewriter = new QuestDbRewriter(ConnectionStringBuilder); - var ex = Assert.Throws(() => Rewriter.Execute(urlInfo)); + var ex = Assert.Throws(() => Rewriter.Execute(urlInfo)); } [Test] @@ -150,7 +151,7 @@ public void Map_UnexpectedOption_Throws() urlInfo.Options.Add("any_other_option", "value"); var Rewriter = new QuestDbRewriter(ConnectionStringBuilder); - var ex = Assert.Throws(() => Rewriter.Execute(urlInfo)); + var ex = Assert.Throws(() => Rewriter.Execute(urlInfo)); } } }