Kenric Nugteren 11 months ago
parent
commit
f7b413b4a5
1 changed files with 75 additions and 40 deletions
  1. 75 40
      inabox.database.sqlite/SQLiteProvider.cs

+ 75 - 40
inabox.database.sqlite/SQLiteProvider.cs

@@ -1472,7 +1472,7 @@ public class SQLiteProvider : IProvider
         };
     }
 
-    private string GetFilterClauseNonGeneric(Type T, SQLiteCommand command, char prefix, IFilter? filter, List<Tuple<string, string, string, string>> tables,
+    private string GetFilterClauseNonGeneric(Type T, SQLiteCommand command, char prefix, IFilter? filter, List<SelectTable> tables,
         Dictionary<string, string> fieldmap, List<string> columns, bool useparams)
     {
         if (filter == null || filter.Expression == null)
@@ -1643,12 +1643,12 @@ public class SQLiteProvider : IProvider
         return result;
     }
 
-    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<SelectTable> tables,
         Dictionary<string, string> fieldmap, List<string> columns, bool useparams) where T : Entity
         => GetFilterClauseNonGeneric(typeof(T), command, prefix, filter, tables, fieldmap, columns, useparams);
 
     private string GetSortClauseNonGeneric(Type T, 
-        SQLiteCommand command, ISortOrder? sort, char prefix, List<Tuple<string, string, string, string>> tables,
+        SQLiteCommand command, ISortOrder? sort, char prefix, List<SelectTable> tables,
         Dictionary<string, string> fieldmap, List<string> columns, bool useparams)
     {
         if (sort == null)
@@ -1689,7 +1689,7 @@ public class SQLiteProvider : IProvider
         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<SelectTable> tables,
         Dictionary<string, string> fieldmap, List<string> columns, bool useparams)
         => GetSortClauseNonGeneric(typeof(T), command, sort, prefix, tables, fieldmap, columns, useparams);
 
@@ -1802,7 +1802,7 @@ public class SQLiteProvider : IProvider
             fieldmap[attribute.Right], fieldmap[attribute.True], fieldmap[attribute.False]);
     }
 
-    private string LoadComplexFormula(SQLiteCommand command, Type type, char prefix, Dictionary<string, string> fieldmap, List<Tuple<string, string, string, string>> tables, List<string> columns, IComplexFormulaNode node, bool useparams)
+    private string LoadComplexFormula(SQLiteCommand command, Type type, char prefix, Dictionary<string, string> fieldmap, List<SelectTable> tables, List<string> columns, IComplexFormulaNode node, bool useparams)
     {
         switch(node)
         {
@@ -1836,11 +1836,11 @@ public class SQLiteProvider : IProvider
 
                 var alias = tables.Count + 1;
 
-                var linkList = string.Join(" , ", links.Keys.Select(x => string.Format("{0}{1}.{2}", prefix, alias, x)));
+                var linkList = links.Keys.Select(x => string.Format("{0}{1}.{2}", prefix, alias, x)).ToHashSet();
 
                 // Don't add the same table with equivalent SQL twice.
                 var tuple = tables.FirstOrDefault(x =>
-                    x.Item1.Equals(subquery) && x.Item4.Equals(linkList) && !x.Item2.Equals(string.Format("{0}1", prefix)));
+                    x.TableDesignator.Equals(subquery) && x.MatchesLinks(linkList) && !x.Alias.Equals($"{prefix}1"));
                 if (tuple == null)
                 {
                     var joins = new List<string>();
@@ -1850,12 +1850,18 @@ public class SQLiteProvider : IProvider
 
                     var join = string.Format("LEFT OUTER JOIN {0} {1}{2} ON {3}", subquery, prefix, alias,
                         string.Join(" AND ", joins));
-                    tuple = new Tuple<string, string, string, string>(subquery, prefix + alias.ToString(), join, linkList);
+                    tuple = new SelectTable()
+                    {
+                        TableDesignator = subquery,
+                        Alias = prefix + alias.ToString(),
+                        FromString = join,
+                        Links = linkList
+                    };
 
                     tables.Add(tuple);
                 }
 
-                return string.Format("{0}.[{1}]", tuple.Item2, aggCol);
+                return string.Format("{0}.[{1}]", tuple.Alias, aggCol);
             case IComplexFormulaConstantNode constantNode:
                 var constant = constantNode.GetConstant();
                 if (constant is FilterConstant filterConstant)
@@ -1978,7 +1984,7 @@ public class SQLiteProvider : IProvider
     }
     
     private void LoadFieldsAndTables(SQLiteCommand command, Type type, char prefix, Dictionary<string, string> fieldmap,
-        List<Tuple<string, string, string, string>> tables, List<string> columns, IBaseColumn baseCol, bool useparams)
+        List<SelectTable> tables, List<string> columns, IBaseColumn baseCol, bool useparams)
     {
         if (fieldmap.ContainsKey(baseCol.Name))
             return;
@@ -2041,10 +2047,10 @@ public class SQLiteProvider : IProvider
                                 
                                 var alias = tables.Count + 1;
 
-                                var link = string.Join(" , ", agg.Links.Keys.Select(x => string.Format("{0}{1}.{2}", prefix, alias, x)));
+                                var linkList = agg.Links.Keys.Select(x => string.Format("{0}{1}.{2}", prefix, alias, x)).ToHashSet();
 
                                 var tuple = tables.FirstOrDefault(x =>
-                                    x.Item1.Equals(linkedtable) && x.Item4.Equals(link) && !x.Item2.Equals(string.Format("{0}1", prefix)));
+                                    x.TableDesignator.Equals(linkedtable) && x.MatchesLinks(linkList) && !x.Alias.Equals(string.Format("{0}1", prefix)));
                                 if (tuple == null)
                                 {
                                     var joins = new List<string>();
@@ -2054,7 +2060,13 @@ public class SQLiteProvider : IProvider
                                             string.Format("IFNULL({0}{1}.[{2}],'') = IFNULL({0}1.[{3}],'')", prefix, alias, key, agg.Links[key]));
                                     var join = string.Format("LEFT OUTER JOIN {0} {1}{2} ON {3}", linkedtable, prefix, alias,
                                         string.Join(" AND ", joins));
-                                    tuple = new Tuple<string, string, string, string>(linkedtable, prefix + alias.ToString(), join, link);
+                                    tuple = new SelectTable()
+                                    {
+                                        TableDesignator = linkedtable,
+                                        Alias = prefix + alias.ToString(),
+                                        FromString = join,
+                                        Links = linkList
+                                    };
 
                                     //tuple = new Tuple<String, String, String, String>(linkedtable, prefix + alias.ToString(), String.Format("LEFT OUTER JOIN {0} {1}{2} ON {1}{2}.[{3}] = {1}1.[ID]", linkedtable, prefix, alias, agg.Link), link);
 
@@ -2064,7 +2076,7 @@ public class SQLiteProvider : IProvider
                                 //if (bits.Last().Equals("ID"))
                                 //    fieldmap[columnname] = String.Format("{0}1.[{1}]", prefix, columnname);
                                 //else
-                                fieldmap[baseCol.Name] = string.Format("{0}.[{1}]", tuple.Item2, agg.Aggregate);
+                                fieldmap[baseCol.Name] = string.Format("{0}.[{1}]", tuple.Alias, agg.Aggregate);
 
                                 //LoadFieldsandTables(command, agg.Type, newprefix, fieldmap, tables, columns, columnname);
                                 //var linkedtable = String.Format("(SELECT [{3}],{0}([{1}]) as [{1}] from {2} group by [{3}])", GetCalculation(agg, columnname), agg.AggregateProperty, agg.Type.EntityName().Split('.').Last(), agg.LinkedProperty);
@@ -2187,35 +2199,38 @@ public class SQLiteProvider : IProvider
                                         + $" GROUP BY [{parent}])";
 
                                     var link = string.Format("{0}.ID", prop.Name);
+                                    var linkList = new HashSet<string> { link };
+
                                     var tuple = tables.FirstOrDefault(x =>
-                                        x.Item1.Equals(linkedTable) && x.Item4.Equals(link) && !x.Item2.Equals(string.Format("{0}1", prefix)));
+                                        x.TableDesignator.Equals(linkedTable) && x.MatchesLinks(linkList) && !x.Alias.Equals(string.Format("{0}1", prefix)));
                                     if (tuple is null)
                                     {
                                         var alias = tables.Count + 1;
-                                        tuple = new Tuple<string, string, string, string>(
-                                            linkedTable,
-                                            prefix + alias.ToString(),
-                                            string.Format(
+                                        tuple = new SelectTable
+                                        {
+                                            TableDesignator = linkedTable,
+                                            Alias = prefix + alias.ToString(),
+                                            FromString = string.Format(
                                                 "LEFT OUTER JOIN {0} {1}{2} ON {1}{2}.[{3}] = {1}1.[ID]",
                                                 linkedTable,
                                                 prefix,
                                                 alias,
                                                 parent
                                             ),
-                                            link
-                                        );
+                                            Links = linkList
+                                        };
                                         tables.Add(tuple);
                                     }
 
                                     //if (bits.Last().Equals("ID"))
                                     //    fieldmap[columnname] = String.Format("{0}1.[{1}]", prefix, columnname);
                                     //else
-                                    fieldmap[baseCol.Name] = string.Format("{0}.[{1}]", tuple.Item2, string.Join(".", bits.Skip(combinecount)));
+                                    fieldmap[baseCol.Name] = string.Format("{0}.[{1}]", tuple.Alias, string.Join(".", bits.Skip(combinecount)));
                                     foreach (var sibling in siblings)
                                     {
                                         var subcol = string.Format("{0}.{1}", string.Join(".", bits.Take(combinecount)), sibling);
                                         if (!subcol.Equals(baseCol.Name))
-                                            fieldmap[subcol] = string.Format("{0}.[{1}]", tuple.Item2, sibling);
+                                            fieldmap[subcol] = string.Format("{0}.[{1}]", tuple.Alias, sibling);
                                     }
                                 }
                                 else
@@ -2235,35 +2250,38 @@ public class SQLiteProvider : IProvider
                                             PrepareSelectNonGeneric(linkedType, command, newprefix, null, subcols.Columns(), null, null, null, null, false, useparams));
 
                                         var link = string.Format("{0}.ID", prop.Name);
+                                        var linkList = new HashSet<string> { link };
+
                                         var tuple = tables.FirstOrDefault(x =>
-                                            x.Item1.Equals(linkedtable) && x.Item4.Equals(link) && !x.Item2.Equals(string.Format("{0}1", prefix)));
+                                            x.TableDesignator.Equals(linkedtable) && x.MatchesLinks(linkList) && !x.Alias.Equals(string.Format("{0}1", prefix)));
                                         if (tuple == null)
                                         {
                                             var alias = tables.Count + 1;
-                                            tuple = new Tuple<string, string, string, string>(
-                                                linkedtable,
-                                                prefix + alias.ToString(),
-                                                string.Format(
+                                            tuple = new SelectTable
+                                            {
+                                                TableDesignator = linkedtable,
+                                                Alias = prefix + alias.ToString(),
+                                                FromString = string.Format(
                                                     "LEFT OUTER JOIN {0} {1}{2} ON {1}{2}.[ID] = {1}1.[{3}.ID]",
                                                     linkedtable,
                                                     prefix,
                                                     alias,
                                                     string.Join(".", bits.Take(combinecount)) //prop.Name
                                                 ),
-                                                link
-                                            );
+                                                Links = linkList
+                                            };
                                             tables.Add(tuple);
                                         }
 
                                         //if (bits.Last().Equals("ID"))
                                         //    fieldmap[columnname] = String.Format("{0}1.[{1}]", prefix, columnname);
                                         //else
-                                        fieldmap[baseCol.Name] = string.Format("{0}.[{1}]", tuple.Item2, string.Join(".", bits.Skip(combinecount)));
+                                        fieldmap[baseCol.Name] = string.Format("{0}.[{1}]", tuple.Alias, string.Join(".", bits.Skip(combinecount)));
                                         foreach (var sibling in siblings)
                                         {
                                             var subcol = string.Format("{0}.{1}", string.Join(".", bits.Take(combinecount)), sibling);
                                             if (!subcol.Equals(baseCol.Name))
-                                                fieldmap[subcol] = string.Format("{0}.[{1}]", tuple.Item2, sibling);
+                                                fieldmap[subcol] = string.Format("{0}.[{1}]", tuple.Alias, sibling);
                                         }
                                     }
                                 }
@@ -2335,6 +2353,22 @@ public class SQLiteProvider : IProvider
         Count
     }
 
+    private class SelectTable
+    {
+        public string TableDesignator { get; set; }
+
+        public string Alias { get; set; }
+
+        public string FromString { get; set; }
+
+        public HashSet<string> Links { get; set; }
+
+        public bool MatchesLinks(HashSet<string> otherLinks)
+        {
+            return Links.Count == otherLinks.Count && Links.All(otherLinks.Contains);
+        }
+    }
+
     public string PrepareSelectNonGeneric(Type T, SQLiteCommand command, char prefix,
         IFilter? filter, IEnumerable<IBaseColumn>? columns, ISortOrder? sort,
         Dictionary<string, string>? aggregates, Dictionary<string, object?>? constants, CoreRange? range, bool distinct, bool useparams)
@@ -2352,18 +2386,19 @@ public class SQLiteProvider : IProvider
         AddFilterFields(filter, fields);
         AddSortFields(sort, fields);
 
-        var tables = new List<Tuple<string, string, string, string>>();
+        var tables = new List<SelectTable>();
 
         var condition = "";
         var sortorder = "";
 
         var entityName = T.EntityName().Split('.').Last();
-        tables.Add(new Tuple<string, string, string, string>(
-            entityName,
-            $"{prefix}1",
-            $"{entityName} {prefix}1",
-            "")
-        );
+        tables.Add(new SelectTable()
+        {
+            TableDesignator = entityName,
+            Alias = $"{prefix}1",
+            FromString = $"{entityName} {prefix}1",
+            Links = new()
+        });
 
         foreach (var column in cols)
         {
@@ -2401,7 +2436,7 @@ public class SQLiteProvider : IProvider
             result.Add("DISTINCT");
         result.Add(string.Join(", ", combined.Values));
         result.Add("FROM");
-        result.AddRange(tables.Select(x => x.Item3));
+        result.AddRange(tables.Select(x => x.FromString));
 
         if (range?.Type == CoreRangeType.Database && range.Offset != 0)
         {