Ver código fonte

Fixing some warnings in SQLiteProvider

Kenric Nugteren 2 anos atrás
pai
commit
ddb7937e7d
1 arquivos alterados com 92 adições e 107 exclusões
  1. 92 107
      inabox.database.sqlite/SQLiteProvider.cs

+ 92 - 107
inabox.database.sqlite/SQLiteProvider.cs

@@ -1,6 +1,7 @@
 using System.Collections;
 using System.Data;
 using System.Data.SQLite;
+using System.Diagnostics.CodeAnalysis;
 using System.Linq.Expressions;
 using System.Reflection;
 using System.Runtime.Serialization.Formatters.Binary;
@@ -98,7 +99,7 @@ namespace InABox.Database.SQLite
 
         public string URL { get; set; }
 
-        public event LogEvent OnLog;
+        public event LogEvent? OnLog;
 
         public Type[] Types { get; set; }
 
@@ -309,9 +310,9 @@ namespace InABox.Database.SQLite
                     result = command.ExecuteNonQuery();
                 }
             }
-            catch (Exception e)
+            catch (Exception)
             {
-                throw e;
+                throw;
             }
 
             return result;
@@ -566,7 +567,7 @@ namespace InABox.Database.SQLite
                 }
                 else if (property.PropertyType.GetInterfaces().Contains(typeof(IEntityLink)))
                 {
-                    var subprop = property.PropertyType.GetProperty("ID");
+                    var subprop = property.PropertyType.GetProperty("ID")!; // Not-null because IEntityLink has ID
                     var subname = ColumnName(prefixes.Concat(new[] { property, subprop }).ToArray());
                     var subtype = ColumnType(subprop.PropertyType);
                     fields[subname] = subtype;
@@ -594,7 +595,7 @@ namespace InABox.Database.SQLite
             foreach (var property in properties)
                 if (property.PropertyType.GetInterfaces().Contains(typeof(IEntityLink)))
                 {
-                    var subprop = property.PropertyType.GetProperty("ID");
+                    var subprop = property.PropertyType.GetProperty("ID")!; // Not-null because IEntityLink has ID
                     var subname = ColumnName(property, subprop);
                     var tablename = type.EntityName().Split('.').Last();
                     result.Add(string.Format("CREATE INDEX idx{0}{1} ON {0} ([{2}])", tablename, subname.Replace(".", ""), subname));
@@ -711,7 +712,7 @@ namespace InABox.Database.SQLite
             }
         }
 
-        private Dictionary<String, object?> CheckDefaultColumns(IAutoEntityGenerator generator)
+        private Dictionary<string, object?> CheckDefaultColumns(IAutoEntityGenerator generator)
         {
             var viewfields = new Dictionary<string, string>();
             LoadFields(generator.Definition, viewfields, null, new CustomProperty[] { });
@@ -734,7 +735,7 @@ namespace InABox.Database.SQLite
         private void CreateTable(SQLiteWriteAccessor access, Type type, bool includeconstraints, CustomProperty[] customproperties)
         {
             var ddl = new List<string>();
-            AutoEntity view = type.GetCustomAttribute<AutoEntity>();
+            var view = type.GetCustomAttribute<AutoEntity>();
             if (view != null)
             {
                 using (var command = access.CreateCommand())
@@ -760,9 +761,9 @@ namespace InABox.Database.SQLite
                     List<String> queries = new List<String>();
                     foreach (var table in union.Tables)
                     {
-                        
-                        var columns = Activator.CreateInstance(typeof(Columns<>).MakeGenericType(table.Entity)) as IColumns;
-                        Dictionary<String, object?> constants = CheckDefaultColumns(union);
+
+                        var columns = Columns.Create(table.Entity);
+                        var constants = CheckDefaultColumns(union);
                         
                         var interfacefields = new Dictionary<string, string>();
                         LoadFields(union.Definition, interfacefields, null, new CustomProperty[] { });
@@ -786,7 +787,7 @@ namespace InABox.Database.SQLite
                         
                         
                         var selectFnc = typeof(SQLiteProvider).GetMethod("PrepareSelect").MakeGenericMethod(table.Entity);
-                        var query = selectFnc.Invoke(this, new object[]
+                        var query = selectFnc.Invoke(this, new object?[]
                         {
                             new SQLiteCommand(),
                             'A',
@@ -928,7 +929,7 @@ namespace InABox.Database.SQLite
             catch (Exception e)
             {
                 OnLog?.Invoke(LogType.Error, "Unable to Create Table: " + e.Message);
-                throw e;
+                throw;
             }
         }
 
@@ -965,7 +966,7 @@ namespace InABox.Database.SQLite
                 catch (Exception e)
                 {
                     OnLog?.Invoke(LogType.Error, string.Format("RebuildTable({0}) [VIEW] failed: {1}\n{2}", table, e.Message, e.StackTrace));
-                    throw e;
+                    throw;
                 }
             }
             else
@@ -1036,7 +1037,7 @@ namespace InABox.Database.SQLite
                 catch (Exception e)
                 {
                     OnLog?.Invoke(LogType.Error, string.Format("RebuildTable({0}) [TABLE] failed: {1}\n{2}", table, e.Message, e.StackTrace));
-                    throw e;
+                    throw;
                 }
             }
             
@@ -1057,7 +1058,7 @@ namespace InABox.Database.SQLite
             {
                 try
                 {
-                    Type tType = null;
+                    Type tType;
                     var cprop = customproperties.FirstOrDefault(x => string.Equals(x.Name, field));
                     if (cprop != null)
                         tType = cprop.PropertyType;
@@ -1130,17 +1131,17 @@ namespace InABox.Database.SQLite
         //         if (!db_views.ContainsValue(type_view))
         //             ExecuteSQL(access, type_view);            
         // }
-        
+
         #endregion
 
         #region CRUD Operations
 
-        private bool IsNull(object o)
+        private static bool IsNull([NotNullWhen(false)] object? o)
         {
             return o == null || o is DBNull;
         }
 
-        public object Decode(object o, Type type)
+        public object? Decode(object o, Type type)
         {
             if (IsNull(o))
                 return type == typeof(string) ? "" : type.GetDefault();
@@ -1149,54 +1150,56 @@ namespace InABox.Database.SQLite
             {
                 if (!IsNull(o))
                 {
-                    var array = o as byte[];
-                    if (o is byte[])
-                        using (var ms = new MemoryStream((byte[])o))
+                    if (o is byte[] array)
+                        using (var ms = new MemoryStream(array))
                         {
                             var deser = new BinaryFormatter().Deserialize(ms);
                             return deser as string[];
                         }
 
-                    return new string[] { };
+                    return Array.Empty<string>();
                 }
 
-                return new string[] { };
+                return Array.Empty<string>();
             }
 
             if (type.GetInterfaces().Contains(typeof(IPackable)))
             {
-                var packable = Activator.CreateInstance(type) as IPackable;
+                var packable = (Activator.CreateInstance(type) as IPackable)!; // Not-null because of above check
                 if (!IsNull(o))
                 {
-                    var array = o as byte[];
-                    if (o is byte[])
-                        packable.Unpack(new FastBinaryReader((byte[])o));
+                    if (o is byte[] array)
+                        packable.Unpack(new FastBinaryReader(array));
                 }
 
                 return packable;
             }
 
             if (type == typeof(DateTime))
-                return IsNull(o) || string.IsNullOrEmpty(o.ToString()) ? DateTime.MinValue : DateTime.Parse(o.ToString());
+                return IsNull(o) || string.IsNullOrEmpty(o.ToString()) ? DateTime.MinValue : DateTime.Parse(o.ToString() ?? "");
 
             if (type == typeof(TimeSpan))
             {
                 if (IsNull(o))
                     return TimeSpan.MinValue;
-                if (double.TryParse(o.ToString(), out var hrs))
+                var oStr = o.ToString() ?? "";
+                if (double.TryParse(oStr, out var hrs))
                     return TimeSpan.FromHours(hrs);
-                if (o.ToString().Contains(":"))
-                    return TimeSpan.Parse(o.ToString());
+                if (oStr.Contains(':'))
+                    return TimeSpan.Parse(oStr);
             }
 
             if (type == typeof(Guid))
-                return IsNull(o) ? Guid.Empty : Guid.Parse(o.ToString());
+                return IsNull(o) ? Guid.Empty : Guid.Parse(o.ToString() ?? "");
 
             if (type == typeof(bool))
-                return IsNull(o) ? false : o.ToString().Equals("1") || o.ToString().ToUpper().Equals("TRUE");
+            {
+                var oStr = o.ToString() ?? "";
+                return !IsNull(o) && (oStr.Equals("1") || oStr.ToUpper().Equals("TRUE"));
+            }
 
             if (type.IsEnum)
-                return Enum.Parse(type, o.ToString());
+                return Enum.Parse(type, o.ToString() ?? "");
 
             if (IsNull(o))
                 return null;
@@ -1330,32 +1333,30 @@ namespace InABox.Database.SQLite
             { Operator.InQuery, "{0} IN ({1})" }
         };
 
-        private String EscapeValue(object value)
+        private static string EscapeValue(object? value)
         {
             if (IsNull(value))
                 return "NULL";
-            if ((value is String) || (value is Enum) || (value is Guid))
-                return String.Format("\'" + "{0}" + "\'", value.ToString().Replace("\'", "\'\'"));
-            if (value is String[])
+            if ((value is string) || (value is Enum) || (value is Guid))
+                return string.Format("\'" + "{0}" + "\'", value.ToString()?.Replace("\'", "\'\'"));
+            if (value is string[])
                 return string.Format("hex({0})", BitConverter.ToString(Encoding.ASCII.GetBytes(value.ToString())).Replace("-", string.Empty));
-            return value.ToString();
+            return value.ToString() ?? "";
 
         }
 
 
-        private String GetFilterConstant(FilterConstant constant)
+        private static string GetFilterConstant(FilterConstant constant)
         {
-            switch (constant)
+            return constant switch
             {
-                case FilterConstant.Now :
-                    return "datetime()";
-                case FilterConstant.Today :
-                    return "strftime('%Y-%m-%d 00:00:00')";
-            }
-            throw new Exception($"FilterConstant.{constant} is not implemented!");
+                FilterConstant.Now => "datetime()",
+                FilterConstant.Today => "strftime('%Y-%m-%d 00:00:00')",
+                _ => throw new Exception($"FilterConstant.{constant} is not implemented!"),
+            };
         }
-        
-        private string GetFilterClause<T>(SQLiteCommand command, char prefix, Filter<T> filter, List<Tuple<string, string, string, string>> tables,
+
+        private string GetFilterClause<T>(SQLiteCommand command, char prefix, Filter<T>? filter, List<Tuple<string, string, string, string>> tables,
             Dictionary<string, string> fieldmap, List<string> columns, bool useparams) where T : Entity
         {
             if (filter == null || filter.Expression == null)
@@ -1372,9 +1373,8 @@ namespace InABox.Database.SQLite
             }
             else
             {
-                var prop = "";
-                MemberExpression mexp = null;
-                if (CoreUtils.TryFindMemberExpression(filter.Expression, out mexp))
+                string prop;
+                if (CoreUtils.TryFindMemberExpression(filter.Expression, out var mexp))
                 {
                     prop = CoreUtils.GetFullPropertyName(mexp, ".");
                 }
@@ -1394,16 +1394,14 @@ namespace InABox.Database.SQLite
                 {
                     // if, and only if the list contains Guids, we can safely bypass the 
                     // 1000-parameter limit by using building the string ourselves
-                    if (filter.Value is Guid[])
+                    if (filter.Value is Guid[] list)
                     {
-                        var list = filter.Value as Guid[];
                         result = string.Format("(" + operators[filter.Operator] + ")", prop, string.Format("\"{0}\"", string.Join("\",\"", list)));
                     }
-                    else if (filter.Value is IEnumerable)
+                    else if (filter.Value is IEnumerable enumerable)
                     {
-                        var list = filter.Value as IEnumerable;
                         var paramlist = new List<object>();
-                        foreach (var item in list)
+                        foreach (var item in enumerable)
                         {
                             var sParam = string.Format("@p{0}", command.Parameters.Count);
                             command.Parameters.AddWithValue(sParam, Encode(item, mexp.Type));
@@ -1447,8 +1445,8 @@ namespace InABox.Database.SQLite
                 }
                 else
                 {
-                    if (filter.Value is FilterConstant)
-                        result = string.Format("(" + operators[filter.Operator] + ")", prop, GetFilterConstant((FilterConstant)filter.Value));
+                    if (filter.Value is FilterConstant constant)
+                        result = string.Format("(" + operators[filter.Operator] + ")", prop, GetFilterConstant(constant));
                     else
                     {
                         var value = Encode(filter.Value, mexp.Type);
@@ -1524,7 +1522,7 @@ namespace InABox.Database.SQLite
             return result;
         }
 
-        private string GetSortClause<T>(SQLiteCommand command, SortOrder<T> sort, char prefix, List<Tuple<string, string, string, string>> tables,
+        private string GetSortClause<T>(SQLiteCommand command, SortOrder<T>? sort, char prefix, List<Tuple<string, string, string, string>> tables,
             Dictionary<string, string> fieldmap, List<string> columns, bool useparams) where T : Entity
         {
             if (sort == null)
@@ -1533,8 +1531,7 @@ namespace InABox.Database.SQLite
             var result = "";
             if (sort.Expression != null)
             {
-                MemberExpression mexp = null;
-                if (CoreUtils.TryFindMemberExpression(sort.Expression, out mexp))
+                if (CoreUtils.TryFindMemberExpression(sort.Expression, out var mexp))
                     result = CoreUtils.GetFullPropertyName(mexp, ".");
                 else
                     result = sort.Expression.ToString();
@@ -1566,23 +1563,17 @@ namespace InABox.Database.SQLite
             return result;
         }
 
-        private string GetCalculation(AggregateAttribute attribute, string columnname)
+        private static string GetCalculation(AggregateAttribute attribute, string columnname)
         {
-            switch (attribute.Calculation)
+            return attribute.Calculation switch
             {
-                case AggregateCalculation.Sum:
-                    return "TOTAL";
-                case AggregateCalculation.Count:
-                    return "COUNT";
-                case AggregateCalculation.Maximum:
-                    return "MAX";
-                case AggregateCalculation.Minimum:
-                    return "MIN";
-                case AggregateCalculation.Average:
-                    return "AVERAGE";
-            }
-
-            throw new Exception(string.Format("{0}.{1} is not a valid aggregate", columnname, attribute.Calculator.GetType().Name));
+                AggregateCalculation.Sum => "TOTAL",
+                AggregateCalculation.Count => "COUNT",
+                AggregateCalculation.Maximum => "MAX",
+                AggregateCalculation.Minimum => "MIN",
+                AggregateCalculation.Average => "AVERAGE",
+                _ => throw new Exception(string.Format("{0}.{1} is not a valid aggregate", columnname, attribute.Calculator.GetType().Name)),
+            };
         }
 
         private string GetFunction(FormulaAttribute attribute, Dictionary<string, string> fieldmap, string columnname)
@@ -1739,11 +1730,10 @@ namespace InABox.Database.SQLite
                         var attr = prop.GetCustomAttributes().FirstOrDefault(x => x.GetType().Equals(typeof(AggregateAttribute)));
                         // LogStop("GetCustomAttributes(Aggregate)");
 
-                        if (attr != null)
+                        if (attr is AggregateAttribute agg)
                         {
-                            var agg = attr as AggregateAttribute;
-                            
-                            bool internalaggregate = agg.Calculator.GetType().GetInterfaces().Any(x => x.IsGenericType && x.GetGenericTypeDefinition()== typeof(ICoreAggregate<,>));
+                            bool internalaggregate = agg.Calculator.GetType().GetInterfaces()
+                                .Any(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(ICoreAggregate<,>));
 
                             if (internalaggregate)
                             {
@@ -1775,14 +1765,7 @@ namespace InABox.Database.SQLite
                                     }
                                 }
 
-                                // LogStart();
-                                var subcoltype = typeof(Columns<>).MakeGenericType(linkedtype);
-                                // LogStop("Columns<>.MakeGnericType");
-
-                                // LogStart();
-                                var subcols = Activator.CreateInstance(subcoltype) as IColumns;
-                                // LogStop("Columns<>.CreateInstance");
-
+                                var subcols = Columns.Create(linkedtype);
 
                                 foreach (var key in agg.Links.Keys)
                                     subcols.Add(key);
@@ -1810,7 +1793,7 @@ namespace InABox.Database.SQLite
                                 }
                                 
                                 var linkedtable = string.Format("({0})",
-                                    preparemethod.Invoke(this, new object[] { command, newprefix, filter, subcols, null, scols, null, int.MaxValue, false, useparams }));
+                                    preparemethod.Invoke(this, new object?[] { command, newprefix, filter, subcols, null, scols, null, int.MaxValue, false, useparams }));
                                 
                                 var alias = tables.Count + 1;
 
@@ -1853,9 +1836,8 @@ namespace InABox.Database.SQLite
                             attr = prop.GetCustomAttributes().FirstOrDefault(x => x.GetType().Equals(typeof(FormulaAttribute)));
                             // LogStop("GetAttribute(Formula)");
 
-                            if (attr != null)
+                            if (attr is FormulaAttribute fnc)
                             {
-                                var fnc = attr as FormulaAttribute;
                                 var functionmap = new Dictionary<string, string>();
 
                                 // LogStart();
@@ -1885,10 +1867,8 @@ namespace InABox.Database.SQLite
                                 attr = prop.GetCustomAttributes().FirstOrDefault(x => x.GetType().Equals(typeof(ConditionAttribute)));
                                 // LogStop("GetAttribute(Condition)");
 
-                                if (attr != null)
+                                if (attr is ConditionAttribute cnd)
                                 {
-                                    var cnd = attr as ConditionAttribute;
-
                                     var cndmap = new Dictionary<string, string>();
                                     // LogStart();
                                     CheckColumn(columns, cnd.Left);
@@ -1983,13 +1963,7 @@ namespace InABox.Database.SQLite
                                 if (!siblings.Contains("Deleted"))
                                     siblings.Insert(1, "Deleted");
 
-                                // LogStart();
-                                var subcoltype = typeof(Columns<>).MakeGenericType(linkedtype);
-                                // LogStop("Columns<>.MakeGenericType");
-
-                                // LogStart();
-                                var subcols = Activator.CreateInstance(subcoltype) as IColumns;
-                                // LogStop("Columns<>.CreateInstance");
+                                var subcols = Columns.Create(linkedtype);
 
                                 foreach (var sibling in siblings)
                                     subcols.Add(sibling);
@@ -2130,7 +2104,7 @@ namespace InABox.Database.SQLite
             condition = GetFilterClause(command, prefix, filter, tables, fieldmap, fields, useparams);
             sortorder = GetSortClause(command, sort, prefix, tables, fieldmap, fields, useparams);
 
-            SortedDictionary<String,String> combined = new SortedDictionary<String, String>();
+            var combined = new SortedDictionary<string, string>();
             
             fields.Clear();
             foreach (var column in cols.Items)
@@ -2214,7 +2188,7 @@ namespace InABox.Database.SQLite
                     continue;
 
                 var sParam = string.Format("@p{0}", iParam++);
-                object value = null;
+                object? value = null;
                 try
                 {
                     value = Encode(insert[key], insert[key]?.GetType());
@@ -2449,7 +2423,7 @@ namespace InABox.Database.SQLite
                                                 ReadAndDecodeValue(result, reader, row, i);
                                             }
                                         }
-                                        catch (Exception e)
+                                        catch (Exception)
                                         {
                                             row.Values.Add(result.Columns[i].DataType.GetDefault());
                                         }
@@ -2537,7 +2511,7 @@ namespace InABox.Database.SQLite
                                     entity.SetObserving(false);
                                     for (var i = 0; i < reader.FieldCount; i++)
                                     {
-                                        object value = null;
+                                        object value;
                                         if (cols.Items[i].Expression.Type == typeof(long) && !reader.IsDBNull(i))
                                             value = reader.GetInt64(i);
                                         else
@@ -2943,6 +2917,12 @@ namespace InABox.Database.SQLite
             }
 
             var entityType = CoreUtils.Entities.FirstOrDefault(x => x.Name == deletion.HeadTable);
+            if(entityType is null)
+            {
+                Logger.Send(LogType.Error, "", $"Entity {deletion.HeadTable} does not exist; Purge cancelled");
+                return;
+            }
+
             var deletionTypes = GetDeletionTypes(entityType);
 
             var purgeMethod = typeof(SQLiteProvider).GetMethod(nameof(PurgeEntityType), BindingFlags.NonPublic | BindingFlags.Instance)!;
@@ -2963,6 +2943,11 @@ namespace InABox.Database.SQLite
             }
 
             var entityType = CoreUtils.Entities.FirstOrDefault(x => x.Name == deletion.HeadTable);
+            if (entityType is null)
+            {
+                Logger.Send(LogType.Error, "", $"Entity {deletion.HeadTable} does not exist; Recovery cancelled");
+                return;
+            }
             var deletionTypes = GetDeletionTypes(entityType);
 
             var recoveryMethod = typeof(SQLiteProvider).GetMethod(nameof(RecoverEntityType), BindingFlags.NonPublic | BindingFlags.Instance)!;
@@ -2981,6 +2966,6 @@ namespace InABox.Database.SQLite
         }
 
         #endregion
-        
+
     }
 }