|
@@ -1,5 +1,4 @@
|
|
|
using System.Collections;
|
|
|
-using System.Collections.Generic;
|
|
|
using System.Data;
|
|
|
using System.Data.SQLite;
|
|
|
using System.Linq.Expressions;
|
|
@@ -7,7 +6,6 @@ using System.Reflection;
|
|
|
using System.Runtime.Serialization.Formatters.Binary;
|
|
|
using System.Text;
|
|
|
using InABox.Core;
|
|
|
-using NPOI.POIFS.FileSystem;
|
|
|
|
|
|
|
|
|
namespace InABox.Database.SQLite
|
|
@@ -711,6 +709,26 @@ namespace InABox.Database.SQLite
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ private Dictionary<String, object?> CheckDefaultColumns(IAutoEntityGenerator generator)
|
|
|
+ {
|
|
|
+ var viewfields = new Dictionary<string, string>();
|
|
|
+ LoadFields(generator.Definition, viewfields, null, new CustomProperty[] { });
|
|
|
+ Dictionary<String, object> result = new Dictionary<string, object>();
|
|
|
+ if (!viewfields.ContainsKey("ID"))
|
|
|
+ result["ID"] = null;
|
|
|
+ if (!viewfields.ContainsKey("Deleted"))
|
|
|
+ result["Deleted"] = null;
|
|
|
+ if (!viewfields.ContainsKey("Created"))
|
|
|
+ result["Created"] = null;
|
|
|
+ if (!viewfields.ContainsKey("CreatedBy"))
|
|
|
+ result["CreatedBy"] = null;
|
|
|
+ if (!viewfields.ContainsKey("LastUpdate"))
|
|
|
+ result["LastUpdate"] = null;
|
|
|
+ if (!viewfields.ContainsKey("LastUpdateBy"))
|
|
|
+ result["LastUpdateBy"] = null;
|
|
|
+ return result;
|
|
|
+ }
|
|
|
|
|
|
private void CreateTable(SQLiteWriteAccessor access, Type type, bool includeconstraints, CustomProperty[] customproperties)
|
|
|
{
|
|
@@ -735,58 +753,133 @@ namespace InABox.Database.SQLite
|
|
|
ddl.Add("CREATE VIEW");
|
|
|
ddl.Add(type.EntityName().Split('.').Last());
|
|
|
ddl.Add("AS");
|
|
|
-
|
|
|
- var union = view.Generator as IAutoEntityUnionGenerator;
|
|
|
- if (union != null)
|
|
|
+
|
|
|
+ if (view.Generator is IAutoEntityUnionGenerator union)
|
|
|
{
|
|
|
-
|
|
|
- var viewfields = new Dictionary<string, string>();
|
|
|
- LoadFields(union.Definition, viewfields, null, new CustomProperty[] { });
|
|
|
- var fields = viewfields.Keys.Select(x => String.Format("[{0}]", x)).ToList();
|
|
|
- if (!fields.Contains("[ID]"))
|
|
|
- fields.Add(String.Format("NULL as [ID]"));
|
|
|
- if (!fields.Contains("[Deleted]"))
|
|
|
- fields.Add(String.Format("NULL as [Deleted]"));
|
|
|
- if (!fields.Contains("[Created]"))
|
|
|
- fields.Add(String.Format("NULL as [Created]"));
|
|
|
- if (!fields.Contains("[CreatedBy]"))
|
|
|
- fields.Add(String.Format("NULL as [CreatedBy]"));
|
|
|
- if (!fields.Contains("[LastUpdate]"))
|
|
|
- fields.Add(String.Format("NULL as [LastUpdate]"));
|
|
|
- if (!fields.Contains("[LastUpdateBy]"))
|
|
|
- fields.Add(String.Format("NULL as [LastUpdateBy]"));
|
|
|
-
|
|
|
List<String> queries = new List<String>();
|
|
|
foreach (var entity in union.Entities)
|
|
|
- queries.Add(String.Format("SELECT {0} {1} FROM {2} WHERE [Deleted] is NULL",
|
|
|
- union.Distinct ? "DISTINCT" : "",
|
|
|
- String.Join(", ", fields),
|
|
|
- entity.EntityName().Split('.').Last())
|
|
|
- );
|
|
|
+ {
|
|
|
+
|
|
|
+ var columns = Activator.CreateInstance(typeof(Columns<>).MakeGenericType(entity)) as IColumns;
|
|
|
+ var viewfields = new Dictionary<string, string>();
|
|
|
+ LoadFields(union.Definition, viewfields, null, new CustomProperty[] { });
|
|
|
+ foreach (var field in viewfields.Keys)
|
|
|
+ columns.Add(field);
|
|
|
+
|
|
|
+ var selectFnc = typeof(SQLiteProvider).GetMethod("PrepareSelect").MakeGenericMethod(entity);
|
|
|
+ var query = selectFnc.Invoke(this, new object[]
|
|
|
+ {
|
|
|
+ new SQLiteCommand(),
|
|
|
+ 'A',
|
|
|
+ union.Filter(entity),
|
|
|
+ columns,
|
|
|
+ null,
|
|
|
+ null,
|
|
|
+ CheckDefaultColumns(union),
|
|
|
+ int.MaxValue,
|
|
|
+ union.Distinct,
|
|
|
+ false
|
|
|
+ }) as string;
|
|
|
+
|
|
|
+ queries.Add(query);
|
|
|
+ }
|
|
|
+ // var viewfields = new Dictionary<string, string>();
|
|
|
+ //LoadFields(union.Definition, viewfields, null, new CustomProperty[] { });
|
|
|
+ // var fields = viewfields.Keys.Select(x => String.Format("[{0}]", x)).ToList();
|
|
|
+ // if (!fields.Contains("[ID]"))
|
|
|
+ // fields.Add(String.Format("NULL as [ID]"));
|
|
|
+ // if (!fields.Contains("[Deleted]"))
|
|
|
+ // fields.Add(String.Format("NULL as [Deleted]"));
|
|
|
+ // if (!fields.Contains("[Created]"))
|
|
|
+ // fields.Add(String.Format("NULL as [Created]"));
|
|
|
+ // if (!fields.Contains("[CreatedBy]"))
|
|
|
+ // fields.Add(String.Format("NULL as [CreatedBy]"));
|
|
|
+ // if (!fields.Contains("[LastUpdate]"))
|
|
|
+ // fields.Add(String.Format("NULL as [LastUpdate]"));
|
|
|
+ // if (!fields.Contains("[LastUpdateBy]"))
|
|
|
+ // fields.Add(String.Format("NULL as [LastUpdateBy]"));
|
|
|
+ //
|
|
|
+ // List<String> queries = new List<String>();
|
|
|
+ // foreach (var entity in union.Entities)
|
|
|
+ // queries.Add(String.Format("SELECT {0} {1} FROM {2} WHERE [Deleted] is NULL",
|
|
|
+ // union.Distinct ? "DISTINCT" : "",
|
|
|
+ // String.Join(", ", fields),
|
|
|
+ // entity.EntityName().Split('.').Last())
|
|
|
+ // );
|
|
|
ddl.Add(String.Join(" UNION ", queries));
|
|
|
}
|
|
|
- else
|
|
|
+ else if ( view.Generator is IAutoEntityCrossGenerator cross)
|
|
|
+ {
|
|
|
+ List<String> constants = new List<string>();
|
|
|
+ foreach (var constant in CheckDefaultColumns(cross))
|
|
|
+ constants.Add($"{EscapeValue(constant.Value)} as [{constant.Key}]");
|
|
|
+
|
|
|
+ String query = String.Format(
|
|
|
+ "SELECT {0} {1}.[{2}] as [{3}], {4}.[{5}] as [{6}], {7} FROM {1}, {4} WHERE {1}.[Deleted] is NULL and {4}.[Deleted] is NULL and {1}.[{8}] = {4}.[{9}]",
|
|
|
+ cross.Distinct ? "DISTINCT" : "",
|
|
|
+ cross.LeftEntity(),
|
|
|
+ cross.LeftProperty(),
|
|
|
+ cross.LeftMapping(),
|
|
|
+ cross.RightEntity(),
|
|
|
+ cross.RightProperty(),
|
|
|
+ cross.RightMapping(),
|
|
|
+ String.Join(", ", constants),
|
|
|
+ cross.LeftLink(),
|
|
|
+ cross.RightLink()
|
|
|
+ );
|
|
|
+
|
|
|
+ ddl.Add(query);
|
|
|
+ }
|
|
|
+ else if ( view.Generator is IAutoEntityCartesianGenerator cartesian)
|
|
|
{
|
|
|
- var cross = view.Generator as IAutoEntityCrossGenerator;
|
|
|
- if (cross != null)
|
|
|
+
|
|
|
+ List<String> fields = new List<string>();
|
|
|
+ List<String> tables = new List<String>();
|
|
|
+ List<String> filters = new List<String>();
|
|
|
+ int iTable = 0;
|
|
|
+ foreach (var table in cartesian.Tables)
|
|
|
{
|
|
|
- String query = String.Format(
|
|
|
- "SELECT {0} {1}.[{2}] as [{3}], {4}.[{5}] as [{6}], NULL as [ID], NULL as [Deleted], NULL as [Created], NULL as [CreatedBy], NULL as [LastUpdate], NULL as [LastUpdateBy] FROM {1}, {4} WHERE {1}.[Deleted] is NULL and {4}.[Deleted] is NULL and {1}.[{7}] = {4}.[{8}]",
|
|
|
- cross.Distinct ? "DISTINCT" : "",
|
|
|
- cross.LeftEntity(),
|
|
|
- cross.LeftProperty(),
|
|
|
- cross.LeftMapping(),
|
|
|
- cross.RightEntity(),
|
|
|
- cross.RightProperty(),
|
|
|
- cross.RightMapping(),
|
|
|
- cross.LeftLink(),
|
|
|
- cross.RightLink()
|
|
|
- );
|
|
|
|
|
|
- ddl.Add(query);
|
|
|
+ var selectFnc = typeof(SQLiteProvider).GetMethod("PrepareSelect").MakeGenericMethod(table.Type);
|
|
|
+ var subQueryText = selectFnc.Invoke(this, new object[]
|
|
|
+ {
|
|
|
+ new SQLiteCommand(),
|
|
|
+ 'A',
|
|
|
+ table.Filter,
|
|
|
+ table.Columns,
|
|
|
+ null,
|
|
|
+ null,
|
|
|
+ null,
|
|
|
+ int.MaxValue,
|
|
|
+ cartesian.Distinct,
|
|
|
+ false
|
|
|
+ }) as string;
|
|
|
+
|
|
|
+ tables.Add($"({subQueryText}) T{iTable}");
|
|
|
+
|
|
|
+ foreach (var mapping in table.Mappings)
|
|
|
+ fields.Add($"T{iTable}.[{mapping.Column.Property}] as [{mapping.Mapping.Property}]");
|
|
|
+
|
|
|
+ iTable++;
|
|
|
}
|
|
|
+
|
|
|
+ foreach (var constant in cartesian.Constants)
|
|
|
+ fields.Add($"{EscapeValue(constant.Constant)} as [{constant.Mapping.Property}]");
|
|
|
+
|
|
|
+ foreach (var constant in CheckDefaultColumns(cartesian))
|
|
|
+ fields.Add($"{EscapeValue(constant.Value)} as [{constant.Key}]");
|
|
|
+
|
|
|
+ StringBuilder sb = new StringBuilder();
|
|
|
+ sb.Append("SELECT ");
|
|
|
+ sb.Append(String.Join(", ", fields));
|
|
|
+ sb.Append(" FROM ");
|
|
|
+ sb.Append(String.Join(", ", tables));
|
|
|
+ if (filters.Any())
|
|
|
+ sb.Append($" WHERE {String.Join(" AND ", filters)}");
|
|
|
+ ddl.Add(sb.ToString());
|
|
|
}
|
|
|
|
|
|
+
|
|
|
ddl.Add(";");
|
|
|
var viewstatement = string.Join(" ", ddl);
|
|
|
}
|
|
@@ -952,7 +1045,7 @@ namespace InABox.Database.SQLite
|
|
|
else
|
|
|
tType = CoreUtils.GetProperty(type, field).PropertyType;
|
|
|
|
|
|
- if (tType == typeof(TimeSpan) && current_fields.ContainsKey(field) && !current_fields[field].Equals(type_fields[field]))
|
|
|
+ if ((view == null) && (tType == typeof(TimeSpan)) && current_fields.ContainsKey(field) && !current_fields[field].Equals(type_fields[field]))
|
|
|
{
|
|
|
var sql = string.Format(
|
|
|
"update {0} set [{1}] = cast(substr([{1}],1,2) as double) + cast(substr([{1}],4,2) as double)/60 + cast(substr([{1}],7,2) as double)/3600 where [{1}] like \"%:%:%\"",
|
|
@@ -1218,8 +1311,33 @@ namespace InABox.Database.SQLite
|
|
|
{ Operator.InQuery, "{0} IN ({1})" }
|
|
|
};
|
|
|
|
|
|
+ private String EscapeValue(object value)
|
|
|
+ {
|
|
|
+ if (IsNull(value))
|
|
|
+ return "NULL";
|
|
|
+ return (value is String) || (value is Enum)
|
|
|
+ ? String.Format("\'"+"{0}"+"\'", value.ToString().Replace("\'", "\'\'"))
|
|
|
+ : value is String[]
|
|
|
+ ? string.Format("hex({0})", BitConverter.ToString(Encoding.ASCII.GetBytes(value.ToString())).Replace("-", string.Empty))
|
|
|
+ : value.ToString();
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ private String GetFilterConstant(FilterConstant constant)
|
|
|
+ {
|
|
|
+ switch (constant)
|
|
|
+ {
|
|
|
+ case FilterConstant.Now :
|
|
|
+ return "datetime()";
|
|
|
+ case FilterConstant.Today :
|
|
|
+ return "date()";
|
|
|
+ }
|
|
|
+ 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,
|
|
|
- Dictionary<string, string> fieldmap, List<string> columns) where T : Entity
|
|
|
+ Dictionary<string, string> fieldmap, List<string> columns, bool useparams) where T : Entity
|
|
|
{
|
|
|
if (filter == null || filter.Expression == null)
|
|
|
return "";
|
|
@@ -1249,7 +1367,7 @@ namespace InABox.Database.SQLite
|
|
|
mexp = CoreUtils.GetMemberExpression(typeof(T), prop);
|
|
|
}
|
|
|
|
|
|
- LoadFieldsandTables(command, typeof(T), prefix, fieldmap, tables, columns, prop);
|
|
|
+ LoadFieldsandTables(command, typeof(T), prefix, fieldmap, tables, columns, prop, useparams);
|
|
|
if (fieldmap.ContainsKey(prop))
|
|
|
prop = fieldmap[prop];
|
|
|
|
|
@@ -1300,39 +1418,52 @@ namespace InABox.Database.SQLite
|
|
|
subColumns,
|
|
|
null,
|
|
|
null,
|
|
|
+ null,
|
|
|
int.MaxValue,
|
|
|
- false
|
|
|
+ false,
|
|
|
+ useparams
|
|
|
}) as string;
|
|
|
|
|
|
result = string.Format("(" + operators[filter.Operator] + ")", prop, subQueryText);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- var value = Encode(filter.Value, mexp.Type);
|
|
|
- if (IsNull(value))
|
|
|
- {
|
|
|
- result = string.Format("({0} {1} NULL)", prop,
|
|
|
- filter.Operator == Operator.IsEqualTo || filter.Operator == Operator.IsLessThan ||
|
|
|
- filter.Operator == Operator.IsLessThanOrEqualTo
|
|
|
- ? "IS"
|
|
|
- : "IS NOT");
|
|
|
- }
|
|
|
+ if (filter.Value is FilterConstant)
|
|
|
+ result = string.Format("(" + operators[filter.Operator] + ")", prop, GetFilterConstant((FilterConstant)filter.Value));
|
|
|
else
|
|
|
{
|
|
|
- var sParam = string.Format("@p{0}", command.Parameters.Count);
|
|
|
-
|
|
|
- if (filter.Expression.Type == typeof(string[]))
|
|
|
+ var value = Encode(filter.Value, mexp.Type);
|
|
|
+ if (IsNull(value))
|
|
|
{
|
|
|
- var bytes = Encoding.ASCII.GetBytes(value.ToString());
|
|
|
- value = BitConverter.ToString(bytes).Replace("-", string.Empty);
|
|
|
- result = string.Format("(" + operators[filter.Operator] + ")", string.Format("hex({0})", prop), sParam);
|
|
|
+ result = string.Format("({0} {1} NULL)", prop,
|
|
|
+ filter.Operator == Operator.IsEqualTo || filter.Operator == Operator.IsLessThan ||
|
|
|
+ filter.Operator == Operator.IsLessThanOrEqualTo
|
|
|
+ ? "IS"
|
|
|
+ : "IS NOT");
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- result = string.Format("(" + operators[filter.Operator] + ")", prop, sParam);
|
|
|
+ if (useparams)
|
|
|
+ {
|
|
|
+ var sParam = string.Format("@p{0}", command.Parameters.Count);
|
|
|
+
|
|
|
+ if (filter.Expression.Type == typeof(string[]))
|
|
|
+ {
|
|
|
+ var bytes = Encoding.ASCII.GetBytes(value.ToString());
|
|
|
+ value = BitConverter.ToString(bytes).Replace("-", string.Empty);
|
|
|
+ result = string.Format("(" + operators[filter.Operator] + ")", string.Format("hex({0})", prop), sParam);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ result = string.Format("(" + operators[filter.Operator] + ")", prop, sParam);
|
|
|
+ }
|
|
|
+
|
|
|
+ command.Parameters.AddWithValue(sParam, value);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ result = string.Format("(" + operators[filter.Operator] + ")", prop, EscapeValue(filter.Value));
|
|
|
}
|
|
|
|
|
|
- command.Parameters.AddWithValue(sParam, value);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -1342,7 +1473,7 @@ namespace InABox.Database.SQLite
|
|
|
{
|
|
|
foreach (var and in filter.Ands)
|
|
|
{
|
|
|
- var AndResult = GetFilterClause(command, prefix, and, tables, fieldmap, columns);
|
|
|
+ var AndResult = GetFilterClause(command, prefix, and, tables, fieldmap, columns, useparams);
|
|
|
if (!string.IsNullOrEmpty(AndResult))
|
|
|
{
|
|
|
result = string.Format("{0} and {1}", result, AndResult);
|
|
@@ -1359,7 +1490,7 @@ namespace InABox.Database.SQLite
|
|
|
{
|
|
|
foreach (var or in filter.Ors)
|
|
|
{
|
|
|
- var OrResult = GetFilterClause(command, prefix, or, tables, fieldmap, columns);
|
|
|
+ var OrResult = GetFilterClause(command, prefix, or, tables, fieldmap, columns, useparams);
|
|
|
if (!string.IsNullOrEmpty(OrResult))
|
|
|
{
|
|
|
result = string.Format("{0} or {1}", result, OrResult);
|
|
@@ -1375,7 +1506,7 @@ namespace InABox.Database.SQLite
|
|
|
}
|
|
|
|
|
|
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) where T : Entity
|
|
|
+ Dictionary<string, string> fieldmap, List<string> columns, bool useparams) where T : Entity
|
|
|
{
|
|
|
if (sort == null)
|
|
|
return "";
|
|
@@ -1392,7 +1523,7 @@ namespace InABox.Database.SQLite
|
|
|
var prop = CoreUtils.GetProperty(typeof(T), result);
|
|
|
if (prop.GetCustomAttribute<DoNotSerialize>() == null && prop.GetCustomAttribute<DoNotPersist>() == null && prop.CanWrite)
|
|
|
{
|
|
|
- LoadFieldsandTables(command, typeof(T), prefix, fieldmap, tables, columns, result);
|
|
|
+ LoadFieldsandTables(command, typeof(T), prefix, fieldmap, tables, columns, result, useparams);
|
|
|
if (fieldmap.ContainsKey(result))
|
|
|
result = fieldmap[result];
|
|
|
|
|
@@ -1411,7 +1542,7 @@ namespace InABox.Database.SQLite
|
|
|
}
|
|
|
|
|
|
foreach (var then in sort.Thens)
|
|
|
- result = result + ", " + GetSortClause(command, then, prefix, tables, fieldmap, columns);
|
|
|
+ result = result + ", " + GetSortClause(command, then, prefix, tables, fieldmap, columns, useparams);
|
|
|
|
|
|
return result;
|
|
|
}
|
|
@@ -1562,7 +1693,7 @@ namespace InABox.Database.SQLite
|
|
|
//}
|
|
|
|
|
|
private void LoadFieldsandTables(SQLiteCommand command, Type type, char prefix, Dictionary<string, string> fieldmap,
|
|
|
- List<Tuple<string, string, string, string>> tables, List<string> columns, string columnname)
|
|
|
+ List<Tuple<string, string, string, string>> tables, List<string> columns, string columnname, bool useparams)
|
|
|
{
|
|
|
if (fieldmap.ContainsKey(columnname))
|
|
|
return;
|
|
@@ -1643,7 +1774,6 @@ namespace InABox.Database.SQLite
|
|
|
|
|
|
// LogStart();
|
|
|
var preparemethod = GetType().GetMethod("PrepareSelect").MakeGenericMethod(linkedtype);
|
|
|
- // LogStop("PrepareSelect<>.MakeGenericMethod");
|
|
|
|
|
|
var filter = Activator.CreateInstance(typeof(Filter<>).MakeGenericType(linkedtype), "Deleted") as IFilter;
|
|
|
filter!.Operator = Operator.IsEqualTo;
|
|
@@ -1657,12 +1787,10 @@ namespace InABox.Database.SQLite
|
|
|
subcols.Add(ff);
|
|
|
filter.And(aggFilter);
|
|
|
}
|
|
|
-
|
|
|
- // LogStart();
|
|
|
+
|
|
|
var linkedtable = string.Format("({0})",
|
|
|
- preparemethod.Invoke(this, new object[] { command, newprefix, filter, subcols, null, scols, int.MaxValue, false }));
|
|
|
- // LogStop("PrepareSelect<>.Invoke");
|
|
|
-
|
|
|
+ preparemethod.Invoke(this, new object[] { command, newprefix, filter, subcols, null, scols, null, int.MaxValue, false, useparams }));
|
|
|
+
|
|
|
var alias = tables.Count + 1;
|
|
|
|
|
|
var link = string.Join(" , ", agg.Links.Keys.Select(x => string.Format("{0}{1}.{2}", prefix, alias, x)));
|
|
@@ -1714,7 +1842,7 @@ namespace InABox.Database.SQLite
|
|
|
// LogStop("Formula.CheckColumn");
|
|
|
|
|
|
//// LogStart();
|
|
|
- LoadFieldsandTables(command, type, prefix, functionmap, tables, columns, fnc.Value);
|
|
|
+ LoadFieldsandTables(command, type, prefix, functionmap, tables, columns, fnc.Value, useparams);
|
|
|
//// LogStop("Formula.LoadFieldsAndTables");
|
|
|
|
|
|
foreach (var column in fnc.Modifiers)
|
|
@@ -1724,7 +1852,7 @@ namespace InABox.Database.SQLite
|
|
|
// LogStop("Formula.Modifiers.CheckColumn");
|
|
|
|
|
|
//// LogStart();
|
|
|
- LoadFieldsandTables(command, type, prefix, functionmap, tables, columns, column);
|
|
|
+ LoadFieldsandTables(command, type, prefix, functionmap, tables, columns, column, useparams);
|
|
|
//// LogStop("Formula.Modifiers.LoadFieldsAndTables");
|
|
|
}
|
|
|
|
|
@@ -1758,19 +1886,19 @@ namespace InABox.Database.SQLite
|
|
|
// LogStop("CheckColumn(False)");
|
|
|
|
|
|
//// LogStart();
|
|
|
- LoadFieldsandTables(command, type, prefix, cndmap, tables, columns, cnd.Left);
|
|
|
+ LoadFieldsandTables(command, type, prefix, cndmap, tables, columns, cnd.Left, useparams);
|
|
|
//// LogStop("LoadFieldsAndTables(Left)");
|
|
|
|
|
|
//// LogStart();
|
|
|
- LoadFieldsandTables(command, type, prefix, cndmap, tables, columns, cnd.Right);
|
|
|
+ LoadFieldsandTables(command, type, prefix, cndmap, tables, columns, cnd.Right, useparams);
|
|
|
//// LogStop("LoadFieldsAndTables(Right)");
|
|
|
|
|
|
//// LogStart();
|
|
|
- LoadFieldsandTables(command, type, prefix, cndmap, tables, columns, cnd.True);
|
|
|
+ LoadFieldsandTables(command, type, prefix, cndmap, tables, columns, cnd.True, useparams);
|
|
|
//// LogStop("LoadFieldsAndTables(True)");
|
|
|
|
|
|
//// LogStart();
|
|
|
- LoadFieldsandTables(command, type, prefix, cndmap, tables, columns, cnd.False);
|
|
|
+ LoadFieldsandTables(command, type, prefix, cndmap, tables, columns, cnd.False, useparams);
|
|
|
//// LogStop("LoadFieldsAndTables(False)");
|
|
|
|
|
|
// LogStart();
|
|
@@ -1845,20 +1973,17 @@ namespace InABox.Database.SQLite
|
|
|
foreach (var sibling in siblings)
|
|
|
subcols.Add(sibling);
|
|
|
|
|
|
- // LogStart();
|
|
|
+
|
|
|
var preparemethod = GetType().GetMethod("PrepareSelect")!.MakeGenericMethod(linkedtype);
|
|
|
- // LogStop("PrepareSelect<>.MakeGenericMethod");
|
|
|
|
|
|
var filter = Activator.CreateInstance(typeof(Filter<>).MakeGenericType(linkedtype), "Deleted") as IFilter;
|
|
|
filter!.Operator = Operator.IsEqualTo;
|
|
|
filter.Value = Guid.Empty;
|
|
|
|
|
|
- // LogStart();
|
|
|
+
|
|
|
var linkedtable = string.Format("({0})",
|
|
|
- preparemethod.Invoke(this, new object?[] { command, newprefix, filter, subcols, null, null, int.MaxValue, false }));
|
|
|
- // LogStop("PrepareSelect<>.Invoke");
|
|
|
+ preparemethod.Invoke(this, new object?[] { command, newprefix, filter, subcols, null, null, null, int.MaxValue, false, useparams }));
|
|
|
|
|
|
- //String linkedtable = linkedtype.EntityName().Split('.').Last();
|
|
|
var link = string.Format("{0}.ID", prop.Name);
|
|
|
var tuple = tables.FirstOrDefault(x =>
|
|
|
x.Item1.Equals(linkedtable) && x.Item4.Equals(link) && !x.Item2.Equals(string.Format("{0}1", prefix)));
|
|
@@ -1915,7 +2040,7 @@ namespace InABox.Database.SQLite
|
|
|
columns.Add(column);
|
|
|
}
|
|
|
|
|
|
- public void FilterFields<T>(Filter<T> filter, List<string> fields)
|
|
|
+ public void FilterFields<T>(Filter<T>? filter, List<string> fields)
|
|
|
{
|
|
|
if (filter == null)
|
|
|
return;
|
|
@@ -1931,7 +2056,7 @@ namespace InABox.Database.SQLite
|
|
|
FilterFields(or, fields);
|
|
|
}
|
|
|
|
|
|
- public void SortFields<T>(SortOrder<T> sort, List<string> fields)
|
|
|
+ public void SortFields<T>(SortOrder<T>? sort, List<string> fields)
|
|
|
{
|
|
|
if (sort == null)
|
|
|
return;
|
|
@@ -1949,36 +2074,26 @@ namespace InABox.Database.SQLite
|
|
|
Count
|
|
|
}
|
|
|
|
|
|
- public string PrepareSelect<T>(SQLiteCommand command, char prefix, Filter<T> filter, Columns<T> columns, SortOrder<T> sort,
|
|
|
- Dictionary<string, string> aggregates, int top = int.MaxValue, bool distinct = false) where T : Entity
|
|
|
+ public string PrepareSelect<T>(SQLiteCommand command, char prefix, Filter<T>? filter, Columns<T>? columns, SortOrder<T>? sort,
|
|
|
+ Dictionary<string, string>? aggregates, Dictionary<string, object>? constants, int top, bool distinct, bool useparams) where T : Entity
|
|
|
{
|
|
|
- //Breadcrumb.Add(typeof(T).Name);
|
|
|
|
|
|
var fieldmap = new Dictionary<string, string>();
|
|
|
-
|
|
|
- //LogStart();
|
|
|
+
|
|
|
var cols = CoreUtils.GetColumns(columns);
|
|
|
- //LogStop("PrepareSelect.GetColumns");
|
|
|
|
|
|
var fields = new List<string>();
|
|
|
-
|
|
|
-
|
|
|
+
|
|
|
fields.AddRange(cols.ColumnNames());
|
|
|
-
|
|
|
- //LogStart();
|
|
|
+
|
|
|
FilterFields(filter, fields);
|
|
|
- //LogStop("PrepareSelect.FilterFields");
|
|
|
-
|
|
|
- //LogStart();
|
|
|
SortFields(sort, fields);
|
|
|
- //LogStop("PrepareSelect.SortFields");
|
|
|
|
|
|
var tables = new List<Tuple<string, string, string, string>>();
|
|
|
|
|
|
var condition = "";
|
|
|
var sortorder = "";
|
|
|
-
|
|
|
-
|
|
|
+
|
|
|
tables.Add(new Tuple<string, string, string, string>(
|
|
|
typeof(T).EntityName().Split('.').Last(),
|
|
|
string.Format("{0}1", prefix),
|
|
@@ -1986,17 +2101,13 @@ namespace InABox.Database.SQLite
|
|
|
"")
|
|
|
);
|
|
|
|
|
|
- foreach (var column in cols.Items) LoadFieldsandTables(command, typeof(T), prefix, fieldmap, tables, fields, column.Property);
|
|
|
+ foreach (var column in cols.Items)
|
|
|
+ LoadFieldsandTables(command, typeof(T), prefix, fieldmap, tables, fields, column.Property, useparams);
|
|
|
|
|
|
var parameters = new Dictionary<string, object>();
|
|
|
-
|
|
|
- //LogStart();
|
|
|
- condition = GetFilterClause(command, prefix, filter, tables, fieldmap, fields);
|
|
|
- //LogStop("PrepareSelect.GetFilterClause");
|
|
|
-
|
|
|
- //LogStart();
|
|
|
- sortorder = GetSortClause(command, sort, prefix, tables, fieldmap, fields);
|
|
|
- //LogStop("PrepareSelect.GetSortClause");
|
|
|
+
|
|
|
+ condition = GetFilterClause(command, prefix, filter, tables, fieldmap, fields, useparams);
|
|
|
+ sortorder = GetSortClause(command, sort, prefix, tables, fieldmap, fields, useparams);
|
|
|
|
|
|
fields.Clear();
|
|
|
foreach (var column in cols.Items)
|
|
@@ -2008,6 +2119,12 @@ namespace InABox.Database.SQLite
|
|
|
fields.Add(string.Format("{0} as [{1}]", fieldmap[column.Property], column.Property));
|
|
|
}
|
|
|
|
|
|
+ if (constants != null)
|
|
|
+ {
|
|
|
+ foreach (var column in constants.Keys)
|
|
|
+ fields.Add(string.Format("{0} as [{1}]", EscapeValue(constants[column]), column));
|
|
|
+ }
|
|
|
+
|
|
|
var result = new List<string>();
|
|
|
result.Add("SELECT");
|
|
|
if (distinct)
|
|
@@ -2181,33 +2298,17 @@ namespace InABox.Database.SQLite
|
|
|
|
|
|
command.CommandText = "";
|
|
|
command.Parameters.Clear();
|
|
|
- command.CommandText = PrepareSelect(command, 'A', filter, cols, sortorder, null, int.MaxValue) + ";";
|
|
|
-
|
|
|
- //stopwatch["PrepareSelect"] = new TimeSpan(sw.ElapsedTicks);
|
|
|
- //sw.Restart();
|
|
|
+ command.CommandText = PrepareSelect(command, 'A', filter, cols, sortorder, null, null, int.MaxValue, false, true) + ";";
|
|
|
|
|
|
using (var reader = command.ExecuteReader())
|
|
|
{
|
|
|
- //stopwatch["QueryDatabase"] = new TimeSpan(sw.ElapsedTicks);
|
|
|
- //sw.Restart();
|
|
|
-
|
|
|
foreach (var row in reader)
|
|
|
{
|
|
|
var values = GetValues(reader, cols.Items.Length);
|
|
|
result.Add(values);
|
|
|
}
|
|
|
- //yield return GetValues(reader, cols.Items.Length);
|
|
|
-
|
|
|
- //stopwatch["ReadData"] = new TimeSpan(sw.ElapsedTicks);
|
|
|
- //sw.Restart();
|
|
|
-
|
|
|
reader.Close();
|
|
|
-
|
|
|
- //stopwatch["Close"] = new TimeSpan(sw.ElapsedTicks);
|
|
|
- //sw.Restart();
|
|
|
}
|
|
|
- //foreach (var key in stopwatch.Keys)
|
|
|
- // OnLog?.Invoke(String.Format("List{0}: {1} = {2,10:0.0000}", typeof(T).EntityName().Split('.').Last(), key, stopwatch[key].TotalMilliseconds), false);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -2240,10 +2341,9 @@ namespace InABox.Database.SQLite
|
|
|
command.Parameters.Clear();
|
|
|
|
|
|
//LogStart();
|
|
|
- String sql = PrepareSelect(command, 'A', filter, cols, sortorder, null, top, distinct) + ";";
|
|
|
+ String sql = PrepareSelect(command, 'A', filter, cols, sortorder, null, null, top, distinct, true) + ";";
|
|
|
|
|
|
command.CommandText = sql;
|
|
|
- //LogStop("PrepareSelect");
|
|
|
|
|
|
try
|
|
|
{
|
|
@@ -2404,7 +2504,7 @@ namespace InABox.Database.SQLite
|
|
|
{
|
|
|
command.CommandText = "";
|
|
|
command.Parameters.Clear();
|
|
|
- command.CommandText = PrepareSelect(command, 'A', filter, cols, sort, null, int.MaxValue) + ";";
|
|
|
+ command.CommandText = PrepareSelect(command, 'A', filter, cols, sort, null, null, int.MaxValue, false, true) + ";";
|
|
|
using (var reader = command.ExecuteReader())
|
|
|
{
|
|
|
if (reader.HasRows)
|