|
@@ -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)
|
|
|
{
|