Various small fixes, setting guild config now works

This commit is contained in:
Ske
2020-06-13 19:15:50 +02:00
parent 2038f023a0
commit c875c8af9f
9 changed files with 56 additions and 70 deletions

View File

@@ -1,8 +1,13 @@
using System;
using System.Data;
using System.Threading.Tasks;
using App.Metrics;
using Dapper;
using NodaTime;
using Npgsql;
using Serilog;
@@ -24,6 +29,29 @@ namespace PluralKit.Core
_metrics = metrics;
_logger = logger;
}
public static void InitStatic()
{
// Dapper by default tries to pass ulongs to Npgsql, which rejects them since PostgreSQL technically
// doesn't support unsigned types on its own.
// Instead we add a custom mapper to encode them as signed integers instead, converting them back and forth.
SqlMapper.RemoveTypeMap(typeof(ulong));
SqlMapper.AddTypeHandler(new UlongEncodeAsLongHandler());
SqlMapper.AddTypeHandler(new UlongArrayHandler());
DefaultTypeMap.MatchNamesWithUnderscores = true;
NpgsqlConnection.GlobalTypeMapper.UseNodaTime();
// With the thing we add above, Npgsql already handles NodaTime integration
// This makes Dapper confused since it thinks it has to convert it anyway and doesn't understand the types
// So we add a custom type handler that literally just passes the type through to Npgsql
SqlMapper.AddTypeHandler(new PassthroughTypeHandler<Instant>());
SqlMapper.AddTypeHandler(new PassthroughTypeHandler<LocalDate>());
// Register our custom types to Npgsql
// Without these it'll still *work* but break at the first launch + probably cause other small issues
NpgsqlConnection.GlobalTypeMapper.MapComposite<ProxyTag>("proxy_tag");
NpgsqlConnection.GlobalTypeMapper.MapEnum<PrivacyLevel>("privacy_level");
}
public async Task<IPKConnection> Obtain()
{
@@ -48,5 +76,27 @@ namespace PluralKit.Core
await using var conn = await Obtain();
return await func(conn);
}
private class PassthroughTypeHandler<T>: SqlMapper.TypeHandler<T>
{
public override void SetValue(IDbDataParameter parameter, T value) => parameter.Value = value;
public override T Parse(object value) => (T) value;
}
private class UlongEncodeAsLongHandler: SqlMapper.TypeHandler<ulong>
{
public override ulong Parse(object value) =>
// Cast to long to unbox, then to ulong (???)
(ulong) (long) value;
public override void SetValue(IDbDataParameter parameter, ulong value) => parameter.Value = (long) value;
}
private class UlongArrayHandler: SqlMapper.TypeHandler<ulong[]>
{
public override void SetValue(IDbDataParameter parameter, ulong[] value) => parameter.Value = Array.ConvertAll(value, i => (long) i);
public override ulong[] Parse(object value) => Array.ConvertAll((long[]) value, i => (ulong) i);
}
}
}

View File

@@ -25,13 +25,6 @@ namespace PluralKit.Core
_logger = logger.ForContext<Schemas>();
}
public static void Initialize()
{
// Without these it'll still *work* but break at the first launch + probably cause other small issues
NpgsqlConnection.GlobalTypeMapper.MapComposite<ProxyTag>("proxy_tag");
NpgsqlConnection.GlobalTypeMapper.MapEnum<PrivacyLevel>("privacy_level");
}
public async Task InitializeDatabase()
{
// Run everything in a transaction