diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.QuestDb/QuestDbConnection.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.QuestDb/QuestDbConnection.cs
index 54d430209..f04d4e682 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.QuestDb/QuestDbConnection.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.QuestDb/QuestDbConnection.cs
@@ -42,6 +42,13 @@ internal sealed class QuestDbConnection : IAsyncDisposable, IDisposable
var explicitPool = HasExplicitMaxPoolSize(options.ConnectionString);
if (!explicitPool) csb.MaxPoolSize = DefaultMaxPoolSize;
EffectiveMaxPoolSize = csb.MaxPoolSize;
+ // #758: QuestDB speaks plain PG-wire with no GSS support. Npgsql's default GSS Encryption Mode=Prefer probes
+ // for GSSAPI on every new physical connection, which on Linux logs "Cannot load library libgssapi_krb5.so.2"
+ // when the Kerberos client library is not installed. The probe falls back cleanly, so this only silences a
+ // misleading line; an explicit "GSS Encryption Mode" in the connection string is always kept.
+ if (!HasExplicitKey(options.ConnectionString, "GSSEncryptionMode"))
+ csb.GssEncryptionMode = GssEncryptionMode.Disable;
+ EffectiveGssEncryptionMode = csb.GssEncryptionMode;
(log ?? NullLogger.Instance).LogInformation(
"QuestDB historian connection pool: Maximum Pool Size = {MaxPoolSize} ({Source}).",
EffectiveMaxPoolSize, explicitPool ? "from the connection string" : "default cap");
@@ -51,17 +58,23 @@ internal sealed class QuestDbConnection : IAsyncDisposable, IDisposable
/// The Npgsql Maximum Pool Size in effect (the connection string's own value, else ).
internal int EffectiveMaxPoolSize { get; }
+ /// The Npgsql GSS Encryption Mode in effect (the connection string's own value, else Disable, #758).
+ internal GssEncryptionMode EffectiveGssEncryptionMode { get; }
+
// Npgsql accepts "Maximum Pool Size" and "MaxPoolSize" (case-insensitive); a generic parse keeps the caller's own
// keywords so "was it set" is answered by the string itself, not by the builder's default.
- private static bool HasExplicitMaxPoolSize(string connectionString)
+ private static bool HasExplicitMaxPoolSize(string connectionString) =>
+ HasExplicitKey(connectionString, "MaxPoolSize", "MaximumPoolSize");
+
+ // Spaces are ignored in keywords ("GSS Encryption Mode" == "GSSEncryptionMode"); matching is case-insensitive.
+ private static bool HasExplicitKey(string connectionString, params string[] normalizedKeys)
{
var generic = new System.Data.Common.DbConnectionStringBuilder { ConnectionString = connectionString };
foreach (string key in generic.Keys)
{
- var k = key.Replace(" ", "", StringComparison.Ordinal);
- if (string.Equals(k, "MaxPoolSize", StringComparison.OrdinalIgnoreCase)
- || string.Equals(k, "MaximumPoolSize", StringComparison.OrdinalIgnoreCase))
- return true;
+ var k = key.Replace(" ", "", StringComparison.Ordinal).Replace("_", "", StringComparison.Ordinal);
+ foreach (var wanted in normalizedKeys)
+ if (string.Equals(k, wanted, StringComparison.OrdinalIgnoreCase)) return true;
}
return false;
}
diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.QuestDb.Tests/QuestDbConnectionTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.QuestDb.Tests/QuestDbConnectionTests.cs
index afc09155e..0ed41bf55 100644
--- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.QuestDb.Tests/QuestDbConnectionTests.cs
+++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.QuestDb.Tests/QuestDbConnectionTests.cs
@@ -146,6 +146,24 @@ public sealed class QuestDbConnectionTests
return c.EffectiveMaxPoolSize;
}
+ // ---- GSS probe (#758) -------------------------------------------------------------------------------------------
+
+ private static Npgsql.GssEncryptionMode GssOf(string cs)
+ {
+ using var c = new QuestDbConnection(new QuestDbHistorianOptions { ConnectionString = cs });
+ return c.EffectiveGssEncryptionMode;
+ }
+
+ [Fact]
+ public void An_unset_GSS_Encryption_Mode_is_disabled() =>
+ GssOf("Host=127.0.0.1;Port=1").ShouldBe(Npgsql.GssEncryptionMode.Disable);
+
+ [Theory]
+ [InlineData("Host=127.0.0.1;Port=1;GSS Encryption Mode=Prefer", Npgsql.GssEncryptionMode.Prefer)]
+ [InlineData("Host=127.0.0.1;Port=1;GssEncryptionMode=Require", Npgsql.GssEncryptionMode.Require)]
+ public void An_explicit_GSS_Encryption_Mode_is_kept(string cs, Npgsql.GssEncryptionMode expected) =>
+ GssOf(cs).ShouldBe(expected);
+
[Fact]
public void An_unset_Maximum_Pool_Size_is_capped_at_24() =>
PoolOf("Host=127.0.0.1;Port=1").ShouldBe(24);