浏览代码

Improved Database Update Script system
Cobverted DynamicGridFilters to CoreFilterDefintiins

frogsoftware 1 年之前
父节点
当前提交
df848c6295

+ 13 - 1
InABox.Core/Configuration/GlobalConfiguration.cs

@@ -20,7 +20,15 @@ namespace InABox.Configuration
         public string Contents { get; set; }
     }
 
-    public class GlobalConfiguration<T> : Configuration<T> where T : IGlobalConfigurationSettings, new()
+    public interface IGlobalConfiguration
+    {
+        string[] Sections();
+        object Load(bool useCache = true);
+        void Save(object obj);
+        void Delete(Action<Exception?>? callback = null);
+    }
+
+    public class GlobalConfiguration<T> : Configuration<T>, IGlobalConfiguration where T : IGlobalConfigurationSettings, new()
     {
         public GlobalConfiguration(string section = "") : base(section)
         {
@@ -43,6 +51,8 @@ namespace InABox.Configuration
             return result ?? NewSettings();
         }
 
+        object IGlobalConfiguration.Load(bool useCache = true) => Load(useCache);
+        
         public override T Load(bool useCache = true)
         {
             if (useCache)
@@ -77,6 +87,8 @@ namespace InABox.Configuration
             return result;
         }
 
+        void IGlobalConfiguration.Save(object obj) => Save((T)obj);
+        
         public override void Save(T obj)
         {
             ConfigurationCache.Add(ConfigurationCacheType.Global, Section, obj);

+ 1 - 1
InABox.Core/Configuration/IConfiguration.cs

@@ -6,7 +6,7 @@ namespace InABox.Configuration
     
     public interface IConfiguration<T>
     {
-        string[] Sections();
+        public string[] Sections();
 
         T Load(bool useCache = true);
         Dictionary<string, T> LoadAll();

+ 21 - 0
InABox.Core/CoreFilterDefinition.cs

@@ -0,0 +1,21 @@
+using System;
+using InABox.Configuration;
+using InABox.Core;
+using System.Collections.Generic;
+
+namespace InABox.Core
+{
+    public class CoreFilterDefinition : BaseObject
+    {
+        [EditorSequence(1)]
+        [TextBoxEditor]
+        public string Name { get; set; }
+
+        [EditorSequence(2)]
+        [FilterEditor]
+        public string Filter { get; set; }
+    }
+
+    public class CoreFilterDefinitions : List<CoreFilterDefinition>, IGlobalConfigurationSettings { }
+    
+}

+ 15 - 0
InABox.Core/CoreUtils.cs

@@ -559,6 +559,21 @@ namespace InABox.Core
                     return DateTime.Today;
             }
             
+            if (value is FilterConstant && type == typeof(double))
+            {
+                return value;
+                //    if (Equals(FilterConstant.Zero, value))
+                //        return (double)0;
+            }
+            
+            if (value is FilterConstant && type == typeof(int))
+            {
+                return value;
+                //    if (Equals(FilterConstant.Zero, value))
+                //        return 0;
+            }
+            
+            
             if (!(value is IConvertible))
                 return value;
 

+ 1 - 0
InABox.Core/Filter.cs

@@ -91,6 +91,7 @@ namespace InABox.Core
     {
         Today,
         Now,
+        Zero
     }
 
     public interface IFilter : ISerializeBinary

+ 11 - 10
InABox.Database/DataUpdater.cs

@@ -31,7 +31,7 @@ namespace InABox.Database
 
         public bool IsDevelopmentVersion { get; set; }
 
-        private VersionNumber(int majorVersion, int minorVersion, string release, bool isDevelopmentVersion)
+        public VersionNumber(int majorVersion, int minorVersion, string release = "", bool isDevelopmentVersion = false)
         {
             MajorVersion = majorVersion;
             MinorVersion = minorVersion;
@@ -139,7 +139,7 @@ namespace InABox.Database
 
     public static class DataUpdater
     {
-        private static Dictionary<VersionNumber, List<Func<bool>>> updateScripts = new();
+        private static Dictionary<VersionNumber, List<DatabaseUpdateScript>> updateScripts = new();
 
         /// <summary>
         /// Register a migration script to run when updating to this version.
@@ -150,16 +150,17 @@ namespace InABox.Database
         /// </summary>
         /// <param name="version">The version to update to.</param>
         /// <param name="action">The action to be run.</param>
-        public static void RegisterUpdateScript(string version, Func<bool> action)
+        public static void RegisterUpdateScript<TUpdater>()
+            where TUpdater : DatabaseUpdateScript, new()
         {
-            var versionNumber = VersionNumber.Parse(version);
-
-            if(!updateScripts.TryGetValue(versionNumber, out var list))
+            var updater = new TUpdater();
+            
+            if(!updateScripts.TryGetValue(updater.Version, out var list))
             {
                 list = new();
-                updateScripts[versionNumber] = list;
+                updateScripts[updater.Version] = list;
             }
-            list.Add(action);
+            list.Add(updater);
         }
 
         private static bool MigrateDatabase(VersionNumber fromVersion, VersionNumber toVersion, out VersionNumber newVersion)
@@ -189,9 +190,9 @@ namespace InABox.Database
                         break;
                     }
                     Logger.Send(LogType.Information, "", $"Executing update to {version}");
-                    foreach(var script in updateScripts[version])
+                    foreach(var updater in updateScripts[version])
                     {
-                        if (!script())
+                        if (!updater.Update())
                         {
                             Logger.Send(LogType.Error, "", $"Script failed, cancelling migration");
                             return false;

+ 71 - 0
InABox.Database/DatabaseUpdateScript.cs

@@ -0,0 +1,71 @@
+using System.Linq.Expressions;
+using InABox.Core;
+
+namespace InABox.Database;
+
+public abstract class DatabaseUpdateScript
+{
+    public abstract VersionNumber Version { get; }
+    public abstract bool Update();
+        
+    protected struct Map<T>
+    {
+        public String Old;
+        public Expression<Func<T, object>> New;
+
+        public Map(String oldcolumn, Expression<Func<T, object>> newcolumn)
+        {
+            Old = oldcolumn;
+            New = newcolumn;
+        }
+    }
+    
+    protected void Convert<T>(
+        Filter<T> filter,
+        params Map<T>[] maps
+    ) where T : Entity, IPersistent, IRemotable, new()
+    {
+        Logger.Send(LogType.Information, "", $"Converting {typeof(T).EntityName().Split('.').Last()}...");
+        List<T> updates = new List<T>();
+        var columns = new Columns<T>(x => x.ID);
+        foreach (var map in maps)
+        {
+            if (!columns.Items.Any(x=>String.Equals(x.Property,map.Old)))
+                columns.Add(map.Old);
+            
+            if (!columns.Items.Any(x=>String.Equals(x.Property,CoreUtils.GetFullPropertyName<T, object>(map.New, "."))))
+             columns.Add(map.New);
+        }
+
+        CoreTable table = DbFactory.Provider.Query<T>(filter,columns);
+        int iCount = 0;
+        foreach (var row in table.Rows)
+        {
+            
+
+            var update = row.ToObject<T>();
+            foreach (var map in maps)
+                CoreUtils.SetPropertyValue(update, CoreUtils.GetFullPropertyName<T, object>(map.New, "."), CoreUtils.GetPropertyValue(update, map.Old));
+            if (update.IsChanged())
+                updates.Add(update);
+    
+            if (updates.Count == 100)
+            {
+                iCount += updates.Count;
+                Logger.Send(LogType.Information, "", $"Converting {typeof(T).EntityName().Split('.').Last()} Times ({iCount}/{table.Rows.Count}");
+                DbFactory.Provider.Save(updates);
+                updates.Clear();
+            }
+        }
+        
+        if (updates.Count > 0)
+        {
+            iCount += updates.Count;
+            Logger.Send(LogType.Information, "", $"Converting {typeof(T).EntityName().Split('.').Last()} Times ({iCount}/{table.Rows.Count})");
+            DbFactory.Provider.Save(updates);
+            updates.Clear();
+        }
+        
+    }
+    
+}

+ 1 - 0
inabox.database.sqlite/SQLiteProvider.cs

@@ -1354,6 +1354,7 @@ namespace InABox.Database.SQLite
             {
                 FilterConstant.Now => "datetime()",
                 FilterConstant.Today => "strftime('%Y-%m-%d 00:00:00')",
+                FilterConstant.Zero => "0",
                 _ => throw new Exception($"FilterConstant.{constant} is not implemented!"),
             };
         }

+ 9 - 7
inabox.wpf/DynamicGrid/DynamicDataGrid.cs

@@ -29,7 +29,7 @@ namespace InABox.DynamicGrid
 
     public class DynamicDataGrid<TEntity> : DynamicGrid<TEntity>, IDynamicDataGrid where TEntity : Entity, IRemotable, IPersistent, new()
     {
-        public delegate bool FilterSelected(DynamicGridFilter filter);
+        public delegate bool FilterSelected(CoreFilterDefinition filter);
 
         public event FilterSelected OnFilterSelected;
 
@@ -698,7 +698,7 @@ namespace InABox.DynamicGrid
             menu.Items.Add(none);
 
             var tag = GetTag();
-            var filters = new GlobalConfiguration<DynamicGridFilters>(tag).Load();
+            var filters = new GlobalConfiguration<CoreFilterDefinitions>(tag).Load();
             foreach (var filter in filters)
             {
                 var item = new MenuItem { Header = filter.Name, Tag = filter };
@@ -719,7 +719,7 @@ namespace InABox.DynamicGrid
                     var window = new DynamicGridFilterEditor(filters, typeof(TEntity));
                     if (window.ShowDialog() == true)
                     {
-                        new GlobalConfiguration<DynamicGridFilters>(tag).Save(filters);
+                        new GlobalConfiguration<CoreFilterDefinitions>(tag).Save(filters);
                     }
                 };
                 menu.Items.Add(manage);
@@ -735,18 +735,20 @@ namespace InABox.DynamicGrid
             var tag = (sender as MenuItem)?.Tag;
             string text = "";
             Bitmap image;
-            if (tag is DynamicGridFilter filter)
+            if (tag is CoreFilterDefinition filter)
             {
                 SelectedFilter = new(filter.Name, Serialization.Deserialize<Filter<TEntity>>(filter.Filter));
                 image = Wpf.Resources.filter_set;
-                if ((bool)(OnFilterSelected?.Invoke(filter)))
-                    text = filter.Name;
+                text = filter.Name;
+                OnFilterSelected?.Invoke(filter);
+
             }
             else
             {
                 SelectedFilter = null;
                 image = Wpf.Resources.filter;
-                OnFilterSelected?.Invoke(new DynamicGridFilter());
+                text = "";
+                OnFilterSelected?.Invoke(new CoreFilterDefinition());
             }
             UpdateButton(FilterBtn, image.AsBitmapImage(), text);
             Refresh(false, true);

+ 0 - 23
inabox.wpf/DynamicGrid/DynamicGridFilter.cs

@@ -1,23 +0,0 @@
-using InABox.Configuration;
-using InABox.Core;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace InABox.DynamicGrid
-{
-    public class DynamicGridFilter : BaseObject
-    {
-        [EditorSequence(1)]
-        [TextBoxEditor]
-        public string Name { get; set; }
-
-        [EditorSequence(2)]
-        [FilterEditor]
-        public string Filter { get; set; }
-    }
-
-    public class DynamicGridFilters : List<DynamicGridFilter>, IGlobalConfigurationSettings { }
-}

+ 3 - 2
inabox.wpf/DynamicGrid/DynamicGridFilterEditor.xaml.cs

@@ -12,6 +12,7 @@ using System.Windows.Input;
 using System.Windows.Media;
 using System.Windows.Media.Imaging;
 using System.Windows.Shapes;
+using InABox.Core;
 
 namespace InABox.DynamicGrid
 {
@@ -22,7 +23,7 @@ namespace InABox.DynamicGrid
     {
         private DynamicGridFilterGrid FilterGrid;
 
-        public DynamicGridFilterEditor(DynamicGridFilters Filters, Type filterType)
+        public DynamicGridFilterEditor(CoreFilterDefinitions Filters, Type filterType)
         {
             InitializeComponent();
 
@@ -37,7 +38,7 @@ namespace InABox.DynamicGrid
             Grid.Children.Add(FilterGrid);
         }
 
-        public DynamicGridFilters Filters { get => FilterGrid.Filters; }
+        public CoreFilterDefinitions Filters { get => FilterGrid.Filters; }
 
         private void OKButton_Click(object sender, RoutedEventArgs e)
         {

+ 9 - 9
inabox.wpf/DynamicGrid/DynamicGridFilterGrid.cs

@@ -7,14 +7,14 @@ using System.Threading.Tasks;
 
 namespace InABox.DynamicGrid
 {
-    public class DynamicGridFilterGrid : DynamicGrid<DynamicGridFilter>
+    public class DynamicGridFilterGrid : DynamicGrid<CoreFilterDefinition>
     {
-        public DynamicGridFilters Filters;
+        public CoreFilterDefinitions Filters;
         private Type FilterType;
 
         public DynamicGridFilterGrid(Type filterType)
         {
-            Filters = new DynamicGridFilters();
+            Filters = new CoreFilterDefinitions();
             Options.AddRange(DynamicGridOption.RecordCount,
                 DynamicGridOption.AddRows, DynamicGridOption.EditRows, DynamicGridOption.DeleteRows,
                 DynamicGridOption.MultiSelect);
@@ -23,9 +23,9 @@ namespace InABox.DynamicGrid
             OnCustomiseEditor += DynamicGridFilterGrid_OnCustomiseEditor;
         }
 
-        private void DynamicGridFilterGrid_OnCustomiseEditor(IDynamicEditorForm sender, DynamicGridFilter[]? items, DynamicGridColumn column, BaseEditor editor)
+        private void DynamicGridFilterGrid_OnCustomiseEditor(IDynamicEditorForm sender, CoreFilterDefinition[]? items, DynamicGridColumn column, BaseEditor editor)
         {
-            if(column.ColumnName == nameof(DynamicGridFilter.Filter) && editor is FilterEditor filterEditor)
+            if(column.ColumnName == nameof(CoreFilterDefinition.Filter) && editor is FilterEditor filterEditor)
             {
                 filterEditor.Type = FilterType;
             }
@@ -37,17 +37,17 @@ namespace InABox.DynamicGrid
                 Filters.RemoveAt(row.Index);
         }
 
-        protected override DynamicGridFilter LoadItem(CoreRow row)
+        protected override CoreFilterDefinition LoadItem(CoreRow row)
         {
             var index = Data.Rows.IndexOf(row);
             return Filters[index];
         }
 
-        protected override void Reload(Filters<DynamicGridFilter> criteria, Columns<DynamicGridFilter> columns, ref SortOrder<DynamicGridFilter>? sort, Action<CoreTable?, Exception?> action)
+        protected override void Reload(Filters<CoreFilterDefinition> criteria, Columns<CoreFilterDefinition> columns, ref SortOrder<CoreFilterDefinition>? sort, Action<CoreTable?, Exception?> action)
         {
             var result = new CoreTable();
             if (columns == null || !columns.Items.Any())
-                result.LoadColumns(typeof(DynamicGridFilter));
+                result.LoadColumns(typeof(CoreFilterDefinition));
             else
                 foreach (var column in columns.Items)
                     result.Columns.Add(new CoreColumn { ColumnName = column.ToString(), DataType = column.Expression.Type });
@@ -55,7 +55,7 @@ namespace InABox.DynamicGrid
             action.Invoke(result, null);
         }
 
-        public override void SaveItem(DynamicGridFilter item)
+        public override void SaveItem(CoreFilterDefinition item)
         {
             if (!Filters.Contains(item))
                 Filters.Add(item);