Skip to content

Commit

Permalink
Initial set of changes adding support for NpgsqlDataSource support
Browse files Browse the repository at this point in the history
  • Loading branch information
oskardudycz committed Dec 12, 2023
1 parent d48f67b commit 8a5e5a9
Show file tree
Hide file tree
Showing 19 changed files with 105 additions and 41 deletions.
2 changes: 1 addition & 1 deletion docs/configuration/storeoptions.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public static DocumentStore For(Action<StoreOptions> configure)
return new DocumentStore(options);
}
```
<sup><a href='https://github.com/JasperFx/marten/blob/master/src/Marten/DocumentStore.cs#L508-L518' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_documentstore.for' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/marten/blob/master/src/Marten/DocumentStore.cs#L512-L522' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_documentstore.for' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

The major parts of `StoreOptions` are shown in the class diagram below:
Expand Down
3 changes: 2 additions & 1 deletion docs/documents/plv8.md
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,8 @@ The `Patch.Remove()` operation removes the given item from a child collection:
<!-- snippet: sample_remove_primitive_element -->
<a id='snippet-sample_remove_primitive_element'></a>
```cs
[Fact]public void remove_primitive_element()
[Fact]
public void remove_primitive_element()
{
var random = new Random();
var target = Target.Random();
Expand Down
2 changes: 1 addition & 1 deletion docs/documents/querying/linq/booleans.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@ public void query_by_booleans(IDocumentSession session)
session.Query<Target>().Where(x => x.Flag == false).ToArray();
}
```
<sup><a href='https://github.com/JasperFx/marten/blob/master/src/Marten.Testing/Examples/LinqExamples.cs#L154-L170' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_boolean_queries' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/marten/blob/master/src/Marten.Testing/Examples/LinqExamples.cs#L158-L174' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_boolean_queries' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->
2 changes: 1 addition & 1 deletion docs/documents/querying/linq/nulls.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@ public void query_by_nullable_type_nulls(IDocumentSession session)
session.Query<Target>().Where(x => x.Inner == null);
}
```
<sup><a href='https://github.com/JasperFx/marten/blob/master/src/Marten.Testing/Examples/LinqExamples.cs#L172-L183' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_query_by_nullable_types' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/marten/blob/master/src/Marten.Testing/Examples/LinqExamples.cs#L176-L187' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_query_by_nullable_types' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->
13 changes: 8 additions & 5 deletions docs/documents/querying/linq/operators.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public void select_a_single_value(IDocumentSession session)
session.Query<Target>().Single(x => x.Number == 5);
}
```
<sup><a href='https://github.com/JasperFx/marten/blob/master/src/Marten.Testing/Examples/LinqExamples.cs#L134-L152' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_select_a_single_value' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/marten/blob/master/src/Marten.Testing/Examples/LinqExamples.cs#L138-L156' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_select_a_single_value' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

## Filtering Documents
Expand Down Expand Up @@ -108,9 +108,12 @@ public void order_by(IDocumentSession session)

// You can use multiple order by's
session.Query<Target>().OrderBy(x => x.Date).ThenBy(x => x.Number);

// If you're brave, you can even use raw SQL literals as of Marten v7!
session.Query<Target>().OrderBySql("substring(d.data -> 'String', 1, 2)");
}
```
<sup><a href='https://github.com/JasperFx/marten/blob/master/src/Marten.Testing/Examples/LinqExamples.cs#L84-L97' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_ordering-in-linq' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/marten/blob/master/src/Marten.Testing/Examples/LinqExamples.cs#L85-L101' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_ordering-in-linq' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

## Ordering with dynamic properties
Expand Down Expand Up @@ -143,7 +146,7 @@ public void order_by_dynamic_props(IDocumentSession session)
session.Query<Target>().OrderBy("Date DESC", "Number");
}
```
<sup><a href='https://github.com/JasperFx/marten/blob/master/src/Marten.Testing/Examples/LinqExamples.cs#L99-L123' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_ordering-in-linq-using-dynamic-props' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/marten/blob/master/src/Marten.Testing/Examples/LinqExamples.cs#L103-L127' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_ordering-in-linq-using-dynamic-props' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

## Case-insensitive ordering for strings
Expand Down Expand Up @@ -190,7 +193,7 @@ public async Task sample_aggregation_operations(IQuerySession session)
var average = await session.Query<Target>().AverageAsync(x => x.Number);
}
```
<sup><a href='https://github.com/JasperFx/marten/blob/master/src/Marten.Testing/Examples/LinqExamples.cs#L186-L201' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_aggregation_operations' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/marten/blob/master/src/Marten.Testing/Examples/LinqExamples.cs#L190-L205' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_aggregation_operations' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

## Partitioning Operators
Expand All @@ -209,7 +212,7 @@ public void using_take_and_skip(IDocumentSession session)
session.Query<Target>().Skip(10).Take(10).OrderBy(x => x.Number).ToArray();
}
```
<sup><a href='https://github.com/JasperFx/marten/blob/master/src/Marten.Testing/Examples/LinqExamples.cs#L125-L132' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_take_and_skip' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/marten/blob/master/src/Marten.Testing/Examples/LinqExamples.cs#L129-L136' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_using_take_and_skip' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

TODO -- link to the paging support
Expand Down
3 changes: 2 additions & 1 deletion docs/documents/querying/linq/strings.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,10 @@ public void case_insensitive_string_fields(IDocumentSession session)
session.Query<Target>().Where(x => x.String.Contains("soMeThiNg", StringComparison.OrdinalIgnoreCase));

session.Query<Target>().Where(x => x.String.Equals("ThE SaMe ThInG", StringComparison.OrdinalIgnoreCase));

}
```
<sup><a href='https://github.com/JasperFx/marten/blob/master/src/Marten.Testing/Examples/LinqExamples.cs#L70-L82' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_searching_within_case_insensitive_string_fields' title='Start of snippet'>anchor</a></sup>
<sup><a href='https://github.com/JasperFx/marten/blob/master/src/Marten.Testing/Examples/LinqExamples.cs#L70-L83' title='Snippet source file'>snippet source</a> | <a href='#snippet-sample_searching_within_case_insensitive_string_fields' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

A shorthand for case-insensitive string matching is provided through `EqualsIgnoreCase` (string extension method in *Baseline*):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@
using Npgsql;
using Shouldly;
using Weasel.Postgresql;
using Weasel.Postgresql.Connections;
using Xunit;

namespace CoreTests.DatabaseMultiTenancy;

[CollectionDefinition("multi-tenancy", DisableParallelization = true)]
public class SingleServerMultiTenancyTests : IAsyncLifetime
public class SingleServerMultiTenancyTests: IAsyncLifetime
{
private DefaultNpgsqlDataSourceFactory dataSourceFactory = new();
private SingleServerMultiTenancy theTenancy;

public async Task InitializeAsync()
Expand All @@ -23,7 +25,9 @@ public async Task InitializeAsync()
await DropDatabaseIfExists("database1");
await DropDatabaseIfExists("database2");

theTenancy = new SingleServerMultiTenancy(ConnectionSource.ConnectionString, new StoreOptions());
var dataSource = dataSourceFactory.Create(ConnectionSource.ConnectionString);

theTenancy = new SingleServerMultiTenancy(dataSourceFactory, dataSource, new StoreOptions());
}

public Task DisposeAsync()
Expand Down
2 changes: 1 addition & 1 deletion src/Marten.CommandLine/Marten.CommandLine.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
<PackageReference Include="JasperFx.CodeGeneration.Commands" Version="3.4.0"/>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" PrivateAssets="All"/>
<PackageReference Include="Oakton" Version="6.1.0"/>
<PackageReference Include="Weasel.CommandLine" Version="7.0.0-alpha.3"/>
<PackageReference Include="Weasel.CommandLine" Version="7.0.0-alpha.6"/>
</ItemGroup>
<Import Project="../../Analysis.Build.props"/>
</Project>
8 changes: 5 additions & 3 deletions src/Marten.Testing/Harness/ConnectionSource.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
using System;
using Weasel.Postgresql.Connections;

namespace Marten.Testing.Harness;

public class ConnectionSource : ConnectionFactory
public class ConnectionSource: ConnectionFactory
{
// Keep the default timeout pretty short
public static readonly string ConnectionString = Environment.GetEnvironmentVariable("marten_testing_database")
?? "Host=localhost;Port=5432;Database=marten_testing;Username=postgres;password=postgres;Command Timeout=5";
??
"Host=localhost;Port=5432;Database=marten_testing;Username=postgres;password=postgres;Command Timeout=5";

static ConnectionSource()
{
Expand All @@ -16,7 +18,7 @@ static ConnectionSource()
}


public ConnectionSource() : base(ConnectionString)
public ConnectionSource(): base(new DefaultNpgsqlDataSourceFactory(), ConnectionString)
{
}
}
11 changes: 8 additions & 3 deletions src/Marten/ConnectionFactory.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#nullable enable
using System;
using Npgsql;
using Weasel.Postgresql.Connections;

namespace Marten;

Expand All @@ -9,29 +10,33 @@ namespace Marten;
/// </summary>
public class ConnectionFactory: IConnectionFactory
{
private readonly INpgsqlDataSourceFactory _npgsqlDataSourceFactory;
private readonly Lazy<string> _connectionString;

/// <summary>
/// Supply a lambda that can resolve the connection string
/// for a Postgresql database
/// </summary>
/// <param name="connectionSource"></param>
public ConnectionFactory(Func<string> connectionSource)
public ConnectionFactory(INpgsqlDataSourceFactory npgsqlDataSourceFactory, Func<string> connectionSource)
{
_npgsqlDataSourceFactory = npgsqlDataSourceFactory;
_connectionString = new Lazy<string>(connectionSource);
}

/// <summary>
/// Supply the connection string to the Postgresql database directly
/// </summary>
/// <param name="connectionString"></param>
public ConnectionFactory(string connectionString)
public ConnectionFactory(INpgsqlDataSourceFactory npgsqlDataSourceFactory, string connectionString)
{
_npgsqlDataSourceFactory = npgsqlDataSourceFactory;
_connectionString = new Lazy<string>(() => connectionString);
}

public NpgsqlConnection Create()
{
return new NpgsqlConnection(_connectionString.Value);
var dataSource = _npgsqlDataSourceFactory.Create(_connectionString.Value);
return dataSource.CreateConnection();
}
}
2 changes: 1 addition & 1 deletion src/Marten/DocumentStore.IMartenStorage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,6 @@ ValueTask<IMartenDatabase> IMartenStorage.FindOrCreateDatabase(string tenantIdOr

private MartenDatabase nulloDatabase()
{
return new MartenDatabase(Options, new ConnectionFactory(string.Empty), "NULLO");
return new MartenDatabase(Options, new ConnectionFactory(dataSourceFactory, string.Empty), "NULLO");
}
}
4 changes: 4 additions & 0 deletions src/Marten/DocumentStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
using Marten.Storage;
using Microsoft.Extensions.Logging;
using Weasel.Core.Migrations;
using Weasel.Postgresql.Connections;
using IsolationLevel = System.Data.IsolationLevel;

namespace Marten;
Expand All @@ -28,13 +29,16 @@ namespace Marten;
public partial class DocumentStore: IDocumentStore, IAsyncDisposable
{
private readonly IMartenLogger _logger;
private readonly INpgsqlDataSourceFactory dataSourceFactory;

/// <summary>
/// Creates a new DocumentStore with the supplied StoreOptions
/// </summary>
/// <param name="options"></param>
public DocumentStore(StoreOptions options)
{
// TODO: Inject here npgsql builder lambda from StoreOptions
dataSourceFactory = new DefaultNpgsqlDataSourceFactory();
options.ApplyConfiguration();
options.Validate();

Expand Down
8 changes: 4 additions & 4 deletions src/Marten/Marten.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.0"/>
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.0"/>
<!-- This is forced by Npgsql peer dependency -->
<PackageReference Include="Npgsql.Json.NET" Version="8.0.0" />
<PackageReference Include="System.Threading.Tasks.Dataflow" Version="8.0.0" />
<PackageReference Include="Weasel.Postgresql" Version="7.0.0-alpha.3"/>
<PackageReference Include="System.Text.Json" Version="8.0.0" />
<PackageReference Include="Npgsql.Json.NET" Version="8.0.0"/>
<PackageReference Include="System.Threading.Tasks.Dataflow" Version="8.0.0"/>
<PackageReference Include="Weasel.Postgresql" Version="7.0.0-alpha.6"/>
<PackageReference Include="System.Text.Json" Version="8.0.0"/>
</ItemGroup>

<!--SourceLink specific settings-->
Expand Down
9 changes: 6 additions & 3 deletions src/Marten/Storage/MartenDatabase.DocumentCleaner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public async Task DeleteAllDocumentsAsync(CancellationToken ct = default)
var builder = new CommandBuilder();
foreach (var table in tables) builder.Append($"truncate {table} cascade;");

await builder.ExecuteNonQueryAsync(conn, ct).ConfigureAwait(false);
await conn.ExecuteNonQueryAsync(builder, ct).ConfigureAwait(false);
}

public void DeleteDocumentsByType(Type documentType)
Expand All @@ -83,7 +83,8 @@ public async Task DeleteDocumentsByTypeAsync(Type documentType, CancellationToke

public void DeleteDocumentsExcept(params Type[] documentTypes)
{
var documentMappings = _options.Storage.DocumentMappingsWithSchema.Where(x => !documentTypes.Contains(x.DocumentType));
var documentMappings =
_options.Storage.DocumentMappingsWithSchema.Where(x => !documentTypes.Contains(x.DocumentType));
foreach (var mapping in documentMappings)
{
var storage = Providers.StorageFor(mapping.DocumentType);
Expand All @@ -93,7 +94,8 @@ public void DeleteDocumentsExcept(params Type[] documentTypes)

public async Task DeleteDocumentsExceptAsync(CancellationToken ct, params Type[] documentTypes)
{
var documentMappings = _options.Storage.DocumentMappingsWithSchema.Where(x => !documentTypes.Contains(x.DocumentType));
var documentMappings =
_options.Storage.DocumentMappingsWithSchema.Where(x => !documentTypes.Contains(x.DocumentType));
foreach (var mapping in documentMappings)
{
var storage = Providers.StorageFor(mapping.DocumentType);
Expand Down Expand Up @@ -124,6 +126,7 @@ public void CompletelyRemove(Type documentType)
{
e.Data[nameof(NpgsqlCommand)] = cmd;
}

MartenExceptionTransformer.WrapAndThrow(e);
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/Marten/Storage/MartenDatabase.EventStorage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ public partial class MartenDatabase
var builder = new CommandBuilder();
handler.ConfigureCommand(builder, null);

await using var reader = await builder.ExecuteReaderAsync(conn, token).ConfigureAwait(false);
await using var reader = await conn.ExecuteReaderAsync(builder, token).ConfigureAwait(false);
return await handler.HandleAsync(reader, null, token).ConfigureAwait(false);
}

Expand Down Expand Up @@ -120,7 +120,7 @@ public partial class MartenDatabase
var builder = new CommandBuilder();
handler.ConfigureCommand(builder, null);

await using var reader = await builder.ExecuteReaderAsync(conn, token).ConfigureAwait(false);
await using var reader = await conn.ExecuteReaderAsync(builder, token).ConfigureAwait(false);
var state = await handler.HandleAsync(reader, null, token).ConfigureAwait(false);

return state?.Sequence ?? 0;
Expand Down
22 changes: 20 additions & 2 deletions src/Marten/Storage/MartenDatabase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using Marten.Internal;
using Marten.Schema;
using Marten.Schema.Identity.Sequences;
using Npgsql;
using Weasel.Core;
using Weasel.Core.Migrations;
using Weasel.Postgresql;
Expand All @@ -22,8 +23,25 @@ public partial class MartenDatabase: PostgresqlDatabase, IMartenDatabase

private Lazy<SequenceFactory> _sequences;

public MartenDatabase(StoreOptions options, IConnectionFactory factory, string identifier)
: base(options, options.AutoCreateSchemaObjects, options.Advanced.Migrator, identifier, factory.Create)
public MartenDatabase(
StoreOptions options,
IConnectionFactory connectionFactory,
string identifier
): base(options, options.AutoCreateSchemaObjects, options.Advanced.Migrator, identifier, connectionFactory.Create)
{
_features = options.Storage;
_options = options;

resetSequences();

Providers = options.Providers;
}

public MartenDatabase(
StoreOptions options,
NpgsqlDataSource npgsqlDataSource,
string identifier
): base(options, options.AutoCreateSchemaObjects, options.Advanced.Migrator, identifier, npgsqlDataSource)
{
_features = options.Storage;
_options = options;
Expand Down
14 changes: 11 additions & 3 deletions src/Marten/Storage/SingleServerMultiTenancy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
using System.Threading.Tasks;
using JasperFx.Core;
using Marten.Schema;
using Npgsql;
using Weasel.Core.Migrations;
using Weasel.Postgresql.Connections;
using Weasel.Postgresql.Migrations;

namespace Marten.Storage;
Expand All @@ -28,6 +30,7 @@ public interface ISingleServerMultiTenancy
internal class SingleServerMultiTenancy: SingleServerDatabaseCollection<MartenDatabase>, ITenancy,
ISingleServerMultiTenancy
{
private readonly INpgsqlDataSourceFactory _dataSourceFactory;
private readonly StoreOptions _options;

private readonly Dictionary<string, string> _tenantToDatabase = new();
Expand All @@ -37,8 +40,13 @@ internal class SingleServerMultiTenancy: SingleServerDatabaseCollection<MartenDa

private ImHashMap<string, Tenant> _tenants = ImHashMap<string, Tenant>.Empty;

public SingleServerMultiTenancy(string masterConnectionString, StoreOptions options): base(masterConnectionString)
public SingleServerMultiTenancy(
INpgsqlDataSourceFactory dataSourceFactory,
NpgsqlDataSource npgsqlDataSource,
StoreOptions options
): base(dataSourceFactory, npgsqlDataSource)
{
_dataSourceFactory = dataSourceFactory;
_options = options;
Cleaner = new CompositeDocumentCleaner(this);
}
Expand Down Expand Up @@ -132,8 +140,8 @@ public async ValueTask<IReadOnlyList<IDatabase>> BuildDatabases()
return AllDatabases();
}

protected override MartenDatabase buildDatabase(string databaseName, string connectionString)
protected override MartenDatabase buildDatabase(string databaseName, NpgsqlDataSource npgsqlDataSource)
{
return new MartenDatabase(_options, new ConnectionFactory(connectionString), databaseName);
return new MartenDatabase(_options, npgsqlDataSource, databaseName);
}
}
Loading

0 comments on commit 8a5e5a9

Please sign in to comment.