Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,19 @@

"extensions": [
"ms-dotnettools.csharp",
"ms-dotnettools.csdevkit",
"formulahendry.dotnet-test-explorer",
"ms-azuretools.vscode-docker",
"mutantdino.resourcemonitor"
]
}
},

"forwardPorts": [5432, 5050],

"remoteEnv": {
"DeveloperBuild": "True"
},

"postCreateCommand": "dotnet restore Npgsql.sln"
"postCreateCommand": "dotnet restore Npgsql.slnx"
}
4 changes: 2 additions & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"dotnet-test-explorer.testProjectPath": "**/*.Tests.csproj",
"dotnet.defaultSolution": "Npgsql.sln"
"dotnet-test-explorer.testProjectPath": "test/**/*.csproj",
"dotnet.defaultSolution": "Npgsql.slnx"
}
2 changes: 2 additions & 0 deletions src/Npgsql/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,5 @@ Npgsql.NpgsqlConnection.ReloadTypesAsync(System.Threading.CancellationToken canc
*REMOVED*Npgsql.NpgsqlSlimDataSourceBuilder.MapEnum<TEnum>(string? pgName = null, Npgsql.INpgsqlNameTranslator? nameTranslator = null) -> Npgsql.TypeMapping.INpgsqlTypeMapper!
static NpgsqlTypes.NpgsqlInet.implicit operator NpgsqlTypes.NpgsqlInet(System.Net.IPNetwork cidr) -> NpgsqlTypes.NpgsqlInet
static readonly NpgsqlTypes.NpgsqlTsVector.Empty -> NpgsqlTypes.NpgsqlTsVector!
Npgsql.Replication.LogicalReplicationConnection.LogicalReplicationConnection(Npgsql.NpgsqlConnection! connection) -> void
Npgsql.Replication.PhysicalReplicationConnection.PhysicalReplicationConnection(Npgsql.NpgsqlConnection! connection) -> void
12 changes: 12 additions & 0 deletions src/Npgsql/Replication/LogicalReplicationConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,16 @@ public LogicalReplicationConnection() {}
/// </summary>
/// <param name="connectionString">The connection used to open the PostgreSQL database.</param>
public LogicalReplicationConnection(string? connectionString) : base(connectionString) {}

/// <summary>
/// Initializes a new instance of <see cref="LogicalReplicationConnection"/> with the given connection.
/// </summary>
/// <param name="connection">The connection to use as a template for logical replication.</param>
/// <remarks>
/// A new connection will be created based on the provided connection's settings, configured for logical replication
/// with pooling, enlistment, multiplexing, and keep-alive disabled. The original connection remains unchanged and
/// can continue to be used normally. This approach preserves sensitive information such as passwords that might
/// not be present in the connection string returned by <see cref="NpgsqlConnection.ConnectionString"/>.
/// </remarks>
public LogicalReplicationConnection(NpgsqlConnection connection) : base(connection) {}
}
12 changes: 12 additions & 0 deletions src/Npgsql/Replication/PhysicalReplicationConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,18 @@ public PhysicalReplicationConnection() {}
/// <param name="connectionString">The connection used to open the PostgreSQL database.</param>
public PhysicalReplicationConnection(string? connectionString) : base(connectionString) {}

/// <summary>
/// Initializes a new instance of <see cref="PhysicalReplicationConnection"/> with the given connection.
/// </summary>
/// <param name="connection">The connection to use as a template for physical replication.</param>
/// <remarks>
/// A new connection will be created based on the provided connection's settings, configured for physical replication
/// with pooling, enlistment, multiplexing, and keep-alive disabled. The original connection remains unchanged and
/// can continue to be used normally. This approach preserves sensitive information such as passwords that might
/// not be present in the connection string returned by <see cref="NpgsqlConnection.ConnectionString"/>.
/// </remarks>
public PhysicalReplicationConnection(NpgsqlConnection connection) : base(connection) {}

/// <summary>
/// Creates a <see cref="PhysicalReplicationSlot"/> that wraps a PostgreSQL physical replication slot and
/// can be used to start physical streaming replication
Expand Down
22 changes: 22 additions & 0 deletions src/Npgsql/Replication/ReplicationConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,28 @@ private protected ReplicationConnection()
private protected ReplicationConnection(string? connectionString) : this()
=> ConnectionString = connectionString;

/// <summary>
/// Initializes a new instance of <see cref="ReplicationConnection"/> with the given connection.
/// The connection's <see cref="NpgsqlConnection.ConnectionString"/> is used to initialize the replication connection.
/// </summary>
/// <param name="connection"></param>
private protected ReplicationConnection(NpgsqlConnection connection)
{
ArgumentNullException.ThrowIfNull(connection);

_requestFeedbackInterval = new TimeSpan(_walReceiverTimeout.Ticks / 2);
var cs = new NpgsqlConnectionStringBuilder(connection.ConnectionString)
{
Pooling = false,
Enlist = false,
Multiplexing = false,
KeepAlive = 0,
ReplicationMode = ReplicationMode
};
_npgsqlConnection = connection.CloneWith(cs.ToString());
_userFacingConnectionString = _npgsqlConnection.ConnectionString;
}

#endregion

#region Properties
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using System.Threading.Tasks;
using NUnit.Framework;
using Npgsql.Replication;

namespace Npgsql.Tests.Replication;

[Platform(Exclude = "MacOsX", Reason = "Replication tests are flaky in CI on Mac")]
[NonParallelizable]
public class LogicalReplicationConnectionConstructorTests : SafeReplicationTestBase<LogicalReplicationConnection>
{
[Test]
public async Task Construct_from_existing_connection()
{
var baseConn = new NpgsqlConnection(TestUtil.ConnectionString);
await using var rc = new LogicalReplicationConnection(baseConn);
await rc.Open();

var csb = new NpgsqlConnectionStringBuilder(rc.ConnectionString);
Assert.That(csb.ReplicationMode, Is.EqualTo(ReplicationMode.Logical));
Assert.That(csb.Pooling, Is.False);
Assert.That(csb.Enlist, Is.False);
Assert.That(csb.Multiplexing, Is.False);
Assert.That(csb.KeepAlive, Is.EqualTo(0));
}

protected override string Postfix => "ctor_l";
}