From a49c93f0b54c96ce6afad6e6e019373ee29dc80b Mon Sep 17 00:00:00 2001 From: Alexander Zaytsev Date: Mon, 7 Oct 2019 00:34:46 +1300 Subject: [PATCH 1/4] Simplify handling of lazy property groups --- .../Hql/Ast/ANTLR/Tree/FromElement.cs | 7 +-- .../Hql/Ast/ANTLR/Tree/FromElementType.cs | 22 ++------ .../Entity/AbstractEntityPersister.cs | 53 ++++--------------- src/NHibernate/Persister/Entity/IQueryable.cs | 13 ----- 4 files changed, 17 insertions(+), 78 deletions(-) diff --git a/src/NHibernate/Hql/Ast/ANTLR/Tree/FromElement.cs b/src/NHibernate/Hql/Ast/ANTLR/Tree/FromElement.cs index fbe060fbb03..40248155c9a 100644 --- a/src/NHibernate/Hql/Ast/ANTLR/Tree/FromElement.cs +++ b/src/NHibernate/Hql/Ast/ANTLR/Tree/FromElement.cs @@ -337,9 +337,10 @@ public string RenderIdentifierSelect(int size, int k) /// the property select SQL fragment. public string RenderPropertySelect(int size, int k) { - return IsAllPropertyFetch - ? _elementType.RenderPropertySelect(size, k, IsAllPropertyFetch) - : _elementType.RenderPropertySelect(size, k, _fetchLazyProperties); + return _elementType.RenderPropertySelect( + size, + k, + IsAllPropertyFetch || _fetchLazyProperties?.Contains(TableAlias) == true); } public override SqlString RenderText(Engine.ISessionFactoryImplementor sessionFactory) diff --git a/src/NHibernate/Hql/Ast/ANTLR/Tree/FromElementType.cs b/src/NHibernate/Hql/Ast/ANTLR/Tree/FromElementType.cs index d8328bfdbf8..ab2cbe4e955 100644 --- a/src/NHibernate/Hql/Ast/ANTLR/Tree/FromElementType.cs +++ b/src/NHibernate/Hql/Ast/ANTLR/Tree/FromElementType.cs @@ -195,31 +195,17 @@ public virtual string RenderScalarIdentifierSelect(int i) /// /// The total number of returned types. /// The sequence of the current returned type. - /// + /// /// the property select SQL fragment. - public string RenderPropertySelect(int size, int k, bool allProperties) - { - return RenderPropertySelect(size, k, null, allProperties); - } - - public string RenderPropertySelect(int size, int k, string[] fetchLazyProperties) - { - return RenderPropertySelect(size, k, fetchLazyProperties, false); - } - - private string RenderPropertySelect(int size, int k, string[] fetchLazyProperties, bool allProperties) + public string RenderPropertySelect(int size, int k, bool fetch) { CheckInitialized(); var queryable = Queryable; if (queryable == null) - return ""; + return string.Empty; - // Use the old method when fetchProperties is null to prevent any breaking changes - // 6.0 TODO: simplify condition by removing the fetchProperties part - string fragment = fetchLazyProperties == null || allProperties - ? queryable.PropertySelectFragment(TableAlias, GetSuffix(size, k), allProperties) - : queryable.PropertySelectFragment(TableAlias, GetSuffix(size, k), fetchLazyProperties); + var fragment = queryable.PropertySelectFragment(TableAlias, GetSuffix(size, k), fetch); return TrimLeadingCommaAndSpaces(fragment); } diff --git a/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs b/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs index 31d85e9c88d..094d8b71c8c 100644 --- a/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs +++ b/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs @@ -177,6 +177,7 @@ public virtual void BindValues(DbCommand ps) private readonly string[][] subclassPropertyColumnNameClosure; private readonly FetchMode[] subclassPropertyFetchModeClosure; private readonly bool[] subclassPropertyNullabilityClosure; + private readonly bool[] subclassPropertyLazyClosure; protected bool[] propertyDefinedOnSubclass; private readonly int[][] subclassPropertyColumnNumberClosure; private readonly int[][] subclassPropertyFormulaNumberClosure; @@ -1636,56 +1637,21 @@ public virtual string IdentifierSelectFragment(string name, string suffix) .ToSqlStringFragment(false); } - public string PropertySelectFragment(string name, string suffix, bool allProperties) + public string PropertySelectFragment(string name, string suffix, bool fetch) { - return PropertySelectFragment(name, suffix, null, allProperties); - } - - public string PropertySelectFragment(string name, string suffix, string[] fetchProperties) - { - return PropertySelectFragment(name, suffix, fetchProperties, false); - } - - private string PropertySelectFragment(string name, string suffix, string[] fetchProperties, bool allProperties) - { - SelectFragment select = new SelectFragment(Factory.Dialect) - .SetSuffix(suffix) - .SetUsedAliases(IdentifierAliases); + var select = new SelectFragment(Factory.Dialect) + .SetSuffix(suffix) + .SetUsedAliases(IdentifierAliases); int[] columnTableNumbers = SubclassColumnTableNumberClosure; string[] columnAliases = SubclassColumnAliasClosure; string[] columns = SubclassColumnClosure; - HashSet fetchColumnsAndFormulas = null; - if (fetchProperties != null) - { - fetchColumnsAndFormulas = new HashSet(); - foreach (var fetchProperty in fetchProperties) - { - var index = GetSubclassPropertyIndex(fetchProperty); - if (index < 0) - { - throw new InvalidOperationException($"Property {fetchProperty} does not exist on entity {EntityName}"); - } - - var columnNames = SubclassPropertyColumnNameClosure[index]; - // Formulas will have all null values - if (columnNames.All(o => o == null)) - { - columnNames = SubclassPropertyFormulaTemplateClosure[index]; - } - - foreach (var columnName in columnNames) - { - fetchColumnsAndFormulas.Add(columnName); - } - } - } for (int i = 0; i < columns.Length; i++) { - bool selectable = (allProperties || !subclassColumnLazyClosure[i] || fetchColumnsAndFormulas?.Contains(columns[i]) == true) && - !IsSubclassTableSequentialSelect(columnTableNumbers[i]) && - subclassColumnSelectableClosure[i]; + bool selectable = (fetch || subclassColumnLazyClosure[i]) && + !IsSubclassTableSequentialSelect(columnTableNumbers[i]) && + subclassColumnSelectableClosure[i]; if (selectable) { string subalias = GenerateTableAlias(name, columnTableNumbers[i]); @@ -1698,8 +1664,7 @@ private string PropertySelectFragment(string name, string suffix, string[] fetch string[] formulaAliases = SubclassFormulaAliasClosure; for (int i = 0; i < formulaTemplates.Length; i++) { - bool selectable = (allProperties || !subclassFormulaLazyClosure[i] || fetchColumnsAndFormulas?.Contains(formulaTemplates[i]) == true) && - !IsSubclassTableSequentialSelect(formulaTableNumbers[i]); + bool selectable = (fetch || subclassFormulaLazyClosure[i]) && !IsSubclassTableSequentialSelect(formulaTableNumbers[i]); if (selectable) { string subalias = GenerateTableAlias(name, formulaTableNumbers[i]); diff --git a/src/NHibernate/Persister/Entity/IQueryable.cs b/src/NHibernate/Persister/Entity/IQueryable.cs index a0fe5934e8d..03cde427534 100644 --- a/src/NHibernate/Persister/Entity/IQueryable.cs +++ b/src/NHibernate/Persister/Entity/IQueryable.cs @@ -10,19 +10,6 @@ public enum Declarer SuperClass } - internal static class AbstractEntityPersisterExtensions - { - /// - /// Given a query alias and an identifying suffix, render the property select fragment. - /// - //6.0 TODO: Merge into IQueryable - public static string PropertySelectFragment(this IQueryable query, string alias, string suffix, string[] fetchProperties) - { - return ReflectHelper.CastOrThrow(query, "individual lazy property fetches") - .PropertySelectFragment(alias, suffix, fetchProperties); - } - } - /// /// Extends the generic ILoadable contract to add operations required by HQL /// From 47e36cd1a17de9c4c00fd9a0822681952964892e Mon Sep 17 00:00:00 2001 From: Alexander Zaytsev Date: Mon, 7 Oct 2019 00:36:07 +1300 Subject: [PATCH 2/4] Remove remnant code from previous attempts --- src/NHibernate/Persister/Entity/AbstractEntityPersister.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs b/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs index 094d8b71c8c..eb552ae9933 100644 --- a/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs +++ b/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs @@ -177,7 +177,6 @@ public virtual void BindValues(DbCommand ps) private readonly string[][] subclassPropertyColumnNameClosure; private readonly FetchMode[] subclassPropertyFetchModeClosure; private readonly bool[] subclassPropertyNullabilityClosure; - private readonly bool[] subclassPropertyLazyClosure; protected bool[] propertyDefinedOnSubclass; private readonly int[][] subclassPropertyColumnNumberClosure; private readonly int[][] subclassPropertyFormulaNumberClosure; From c112f950a41bc87f0a6a7807ee7ecd2dfd6bcff9 Mon Sep 17 00:00:00 2001 From: Alexander Zaytsev Date: Mon, 7 Oct 2019 00:42:51 +1300 Subject: [PATCH 3/4] Indents --- .../Persister/Entity/AbstractEntityPersister.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs b/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs index eb552ae9933..f97a3175dad 100644 --- a/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs +++ b/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs @@ -1639,8 +1639,8 @@ public virtual string IdentifierSelectFragment(string name, string suffix) public string PropertySelectFragment(string name, string suffix, bool fetch) { var select = new SelectFragment(Factory.Dialect) - .SetSuffix(suffix) - .SetUsedAliases(IdentifierAliases); + .SetSuffix(suffix) + .SetUsedAliases(IdentifierAliases); int[] columnTableNumbers = SubclassColumnTableNumberClosure; string[] columnAliases = SubclassColumnAliasClosure; @@ -1649,8 +1649,8 @@ public string PropertySelectFragment(string name, string suffix, bool fetch) for (int i = 0; i < columns.Length; i++) { bool selectable = (fetch || subclassColumnLazyClosure[i]) && - !IsSubclassTableSequentialSelect(columnTableNumbers[i]) && - subclassColumnSelectableClosure[i]; + !IsSubclassTableSequentialSelect(columnTableNumbers[i]) && + subclassColumnSelectableClosure[i]; if (selectable) { string subalias = GenerateTableAlias(name, columnTableNumbers[i]); @@ -1663,7 +1663,8 @@ public string PropertySelectFragment(string name, string suffix, bool fetch) string[] formulaAliases = SubclassFormulaAliasClosure; for (int i = 0; i < formulaTemplates.Length; i++) { - bool selectable = (fetch || subclassFormulaLazyClosure[i]) && !IsSubclassTableSequentialSelect(formulaTableNumbers[i]); + bool selectable = (fetch || subclassFormulaLazyClosure[i]) && + !IsSubclassTableSequentialSelect(formulaTableNumbers[i]); if (selectable) { string subalias = GenerateTableAlias(name, formulaTableNumbers[i]); From b0b54340c0d4a6663b39cd9559915d1eca5e3ff9 Mon Sep 17 00:00:00 2001 From: Alexander Zaytsev Date: Mon, 7 Oct 2019 00:51:50 +1300 Subject: [PATCH 4/4] Fix condition --- src/NHibernate/Persister/Entity/AbstractEntityPersister.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs b/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs index f97a3175dad..1719a1dbbc3 100644 --- a/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs +++ b/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs @@ -1648,7 +1648,7 @@ public string PropertySelectFragment(string name, string suffix, bool fetch) for (int i = 0; i < columns.Length; i++) { - bool selectable = (fetch || subclassColumnLazyClosure[i]) && + bool selectable = (fetch || !subclassColumnLazyClosure[i]) && !IsSubclassTableSequentialSelect(columnTableNumbers[i]) && subclassColumnSelectableClosure[i]; if (selectable) @@ -1663,7 +1663,7 @@ public string PropertySelectFragment(string name, string suffix, bool fetch) string[] formulaAliases = SubclassFormulaAliasClosure; for (int i = 0; i < formulaTemplates.Length; i++) { - bool selectable = (fetch || subclassFormulaLazyClosure[i]) && + bool selectable = (fetch || !subclassFormulaLazyClosure[i]) && !IsSubclassTableSequentialSelect(formulaTableNumbers[i]); if (selectable) {