mirror of
https://github.com/azaion/annotations.git
synced 2026-04-22 11:06:30 +00:00
add manual Tile Processor
zoom on video on pause (temp image)
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
using System.Data;
|
||||
using LinqToDB.Data;
|
||||
using LinqToDB.Mapping;
|
||||
|
||||
namespace Azaion.Common.Database;
|
||||
|
||||
public static class SchemaMigrator
|
||||
{
|
||||
public static void EnsureSchemaUpdated(DataConnection dbConnection, params Type[] entityTypes)
|
||||
{
|
||||
var connection = dbConnection.Connection;
|
||||
var mappingSchema = dbConnection.MappingSchema;
|
||||
|
||||
if (connection.State == ConnectionState.Closed)
|
||||
{
|
||||
connection.Open();
|
||||
}
|
||||
|
||||
foreach (var type in entityTypes)
|
||||
{
|
||||
var entityDescriptor = mappingSchema.GetEntityDescriptor(type);
|
||||
var tableName = entityDescriptor.Name.Name;
|
||||
var existingColumns = GetTableColumns(connection, tableName);
|
||||
|
||||
foreach (var column in entityDescriptor.Columns)
|
||||
{
|
||||
if (existingColumns.Contains(column.ColumnName, StringComparer.OrdinalIgnoreCase))
|
||||
continue;
|
||||
|
||||
var columnDefinition = GetColumnDefinition(column);
|
||||
dbConnection.Execute($"ALTER TABLE {tableName} ADD COLUMN {columnDefinition}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static HashSet<string> GetTableColumns(IDbConnection connection, string tableName)
|
||||
{
|
||||
var columns = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
using var cmd = connection.CreateCommand();
|
||||
cmd.CommandText = $"PRAGMA table_info({tableName})";
|
||||
using var reader = cmd.ExecuteReader();
|
||||
while (reader.Read())
|
||||
columns.Add(reader.GetString(1)); // "name" is in the second column
|
||||
|
||||
return columns;
|
||||
}
|
||||
|
||||
private static string GetColumnDefinition(ColumnDescriptor column)
|
||||
{
|
||||
var type = column.MemberType;
|
||||
var underlyingType = Nullable.GetUnderlyingType(type) ?? type;
|
||||
var sqliteType = GetSqliteType(underlyingType);
|
||||
var defaultClause = GetSqlDefaultValue(type, underlyingType);
|
||||
|
||||
return $"\"{column.ColumnName}\" {sqliteType} {defaultClause}";
|
||||
}
|
||||
|
||||
private static string GetSqliteType(Type type) =>
|
||||
type switch
|
||||
{
|
||||
_ when type == typeof(int)
|
||||
|| type == typeof(long)
|
||||
|| type == typeof(bool)
|
||||
|| type.IsEnum
|
||||
=> "INTEGER",
|
||||
|
||||
_ when type == typeof(double)
|
||||
|| type == typeof(float)
|
||||
|| type == typeof(decimal)
|
||||
=> "REAL",
|
||||
|
||||
_ when type == typeof(byte[])
|
||||
=> "BLOB",
|
||||
|
||||
_ => "TEXT"
|
||||
};
|
||||
|
||||
private static string GetSqlDefaultValue(Type originalType, Type underlyingType)
|
||||
{
|
||||
var isNullable = originalType.IsClass || Nullable.GetUnderlyingType(originalType) != null;
|
||||
if (isNullable)
|
||||
return "NULL";
|
||||
|
||||
var defaultValue = Activator.CreateInstance(underlyingType);
|
||||
|
||||
if (underlyingType == typeof(bool))
|
||||
return $"NOT NULL DEFAULT {(Convert.ToBoolean(defaultValue) ? 1 : 0)}";
|
||||
|
||||
if (underlyingType.IsValueType && defaultValue is IFormattable f)
|
||||
return $"NOT NULL DEFAULT {f.ToString(null, System.Globalization.CultureInfo.InvariantCulture)}";
|
||||
|
||||
return $"NOT NULL DEFAULT '{defaultValue}'";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user