Skip to content

Commit d35a20d

Browse files
committed
Removed block for query on hierarchical CTE tables.
1 parent d796465 commit d35a20d

File tree

7 files changed

+80
-21
lines changed

7 files changed

+80
-21
lines changed

Lib/CSQLQueryExpress/Compiler/SQLQueryCompiler.cs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.Collections.ObjectModel;
34
using System.Linq;
45
using System.Text;
@@ -36,6 +37,9 @@ public static SQLQueryCompiled Compile(ISQLQuery query,
3637
ISQLQueryParametersBuilder parameterBuilder,
3738
ISQLQueryTableNameResolver tableNameResolver)
3839
{
40+
parameterBuilder.Initialize();
41+
tableNameResolver.Initialize();
42+
3943
var translatedQuery = CompileQuery(query, parameterBuilder, tableNameResolver);
4044

4145
return new SQLQueryCompiled(translatedQuery, new ReadOnlyCollection<SQLQueryParameter>(parameterBuilder.Parameters.Select(p => p.Value).ToList()));
@@ -46,10 +50,7 @@ internal static string CompileQuery(
4650
ISQLQueryParametersBuilder parameterBuilder,
4751
ISQLQueryTableNameResolver tableNameResolver)
4852
{
49-
parameterBuilder.Initialize();
50-
tableNameResolver.Initialize();
51-
52-
var cteList = query.Where(f => f.FragmentType == SQLQueryFragmentType.SelectCte).ToList();
53+
var cteList = query.GetHierachicalSelectCte();
5354
if (cteList.Count > 1 && cteList.Select(t => t.GetType().GenericTypeArguments[0]).Distinct().Count() != cteList.Count)
5455
{
5556
throw new NotSupportedException("Multiple declaration of CTE TABLEs for the same Entity is not supported.");
@@ -59,15 +60,22 @@ internal static string CompileQuery(
5960

6061
var translatedQueryBuilder = new StringBuilder();
6162

63+
var cteFragmentsTranslated = new List<ISQLQueryFragment>();
64+
6265
if (cteList.Count > 0)
6366
{
6467
var idx = cteList.Count - 1;
6568
foreach (var cte in cteList)
6669
{
67-
var withTableFragments = (ISQLQuery)cte;
70+
var withTableFragments = cte;
6871

6972
foreach (var fragment in withTableFragments)
7073
{
74+
if (cteFragmentsTranslated.Contains(fragment))
75+
{
76+
continue;
77+
}
78+
7179
if (translatedQueryBuilder.Length == 0)
7280
{
7381
translatedQueryBuilder.Append("WITH ");
@@ -78,6 +86,8 @@ internal static string CompileQuery(
7886
}
7987

8088
translatedQueryBuilder.Append(fragment.Translate(queryExpressionTranslator));
89+
90+
cteFragmentsTranslated.Add(fragment);
8191
}
8292

8393
if (idx-- > 0)
@@ -91,7 +101,7 @@ internal static string CompileQuery(
91101
}
92102
}
93103

94-
var allFragments = query.Where(f => cteList.Count == 0 || !cteList.Contains(f));
104+
var allFragments = query.Where(f => cteFragmentsTranslated.Count == 0 || !cteFragmentsTranslated.Contains(f));
95105

96106
foreach (var fragment in allFragments)
97107
{

Lib/CSQLQueryExpress/Compiler/SQLQueryUtils.cs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,34 @@ public static bool IsHierarchicalSelectFromCte(this ISQLQuery query)
3131
return false;
3232
}
3333

34+
public static IList<ISQLQuery> GetHierachicalSelectCte(this ISQLQuery query)
35+
{
36+
var selectCteList = new List<ISQLQuery>();
37+
38+
ExtractHierachicalSelectCte(query, selectCteList);
39+
40+
return selectCteList;
41+
}
42+
43+
private static void ExtractHierachicalSelectCte(ISQLQuery query, IList<ISQLQuery> selectCteList)
44+
{
45+
foreach (var fragment in query)
46+
{
47+
if (fragment.FragmentType == SQLQueryFragmentType.FromBySelect ||
48+
fragment.FragmentType == SQLQueryFragmentType.JoinBySelect)
49+
{
50+
var hSelect = ((ISQLQueryFragmentFromSelect)fragment).FromSelect;
51+
52+
ExtractHierachicalSelectCte(hSelect, selectCteList);
53+
54+
if (hSelect.FragmentType == SQLQueryFragmentType.SelectCte)
55+
{
56+
selectCteList.Add(hSelect);
57+
}
58+
}
59+
}
60+
}
61+
3462
public static T[] Merge<T>(this T first, T second, params T[] others)
3563
{
3664
var list = new List<T>

Lib/CSQLQueryExpress/Fragments/SQLQueryFrom.cs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,6 @@ internal SQLQueryFrom(IList<ISQLQueryFragment> fragments, SQLQuerySelect<T> sele
1818
{
1919
_fragments = fragments;
2020

21-
if (select != null && select.IsHierarchicalSelectFromCte())
22-
{
23-
throw new NotSupportedException("Hierachical select queries from CTE TABLE is not supported.");
24-
}
25-
2621
_select = select;
2722

2823
if (_select != null && _select.FragmentType == SQLQueryFragmentType.SelectCte)

Lib/CSQLQueryExpress/Fragments/SQLQueryJoin.cs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,6 @@ internal SQLQueryJoin(IList<ISQLQueryFragment> fragments, SQLQueryJoinType joinT
4141
_type = type;
4242
_select = select;
4343

44-
if (select != null && select.IsHierarchicalSelectFromCte())
45-
{
46-
throw new NotSupportedException("Hierachical select queries from CTE TABLE is not supported.");
47-
}
48-
4944
if ((_joinType == SQLQueryJoinType.CrossApply || _joinType == SQLQueryJoinType.OuterApply) &&
5045
(_select == null || _select.FragmentType == SQLQueryFragmentType.SelectCte))
5146
{

Lib/CSQLQueryExpress/Fragments/SQLQuerySelect.cs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -214,11 +214,6 @@ public SQLQueryInto<T> Into()
214214

215215
public SQLQuerySelect<T> ToCteTable()
216216
{
217-
if (_fragments.Any(f => f.FragmentType == SQLQueryFragmentType.SelectCte))
218-
{
219-
throw new NotSupportedException("CTE TABLE declaration FROM CTE TABLE is not supported.");
220-
}
221-
222217
_useCte = true;
223218
return this;
224219
}

Tests/CSQLQueryExpress.Tests/CSQLQueryExpress.Tests.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@
7878
<None Update="UnitTests\JoinStatements\TestInnerJoin.txt">
7979
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
8080
</None>
81+
<None Update="UnitTests\SelectStatements\TestStatement11.txt">
82+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
83+
</None>
8184
<None Update="UnitTests\SelectStatements\TestStatement2.txt">
8285
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
8386
</None>

Tests/CSQLQueryExpress.Tests/UnitTests/QuerySelectUnitTest.cs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,39 @@ public void TestStatement10()
328328
Assert.DoesNotThrow(() => queryCommand.ToList());
329329
}
330330

331+
[Test]
332+
public void TestStatement11()
333+
{
334+
var queryCategoriesCte = new SQLQuery()
335+
.From<dbo.Categories>()
336+
.Select(c => c.All())
337+
.ToCteTable();
338+
339+
var queryProductsCte = new SQLQuery()
340+
.From<dbo.Products>()
341+
.InnerJoin(queryCategoriesCte, (p, c) => p.CategoryID == c.CategoryID)
342+
.Where((p, c) => p.SupplierID.IsNotNull())
343+
.Select((p, c) => p.All())
344+
.ToCteTable();
345+
346+
var query = new SQLQuery()
347+
.From<dbo.Suppliers>()
348+
.InnerJoin(queryProductsCte, (s, p) => s.SupplierID == p.SupplierID)
349+
.Select((s, p) => s.All());
350+
351+
var compiledQuery = query.Compile();
352+
353+
Assert.That(compiledQuery.Parameters.Count, Is.EqualTo(0));
354+
355+
var statement = GetSQLStatement();
356+
357+
Assert.That(compiledQuery.Statement, Is.EqualTo(statement));
358+
359+
var queryCommand = new SQLQueryCommandReader(ConnectionString, compiledQuery);
360+
361+
Assert.DoesNotThrow(() => queryCommand.ToList());
362+
}
363+
331364
private string GetSQLStatement([CallerMemberName] string memeberName = null)
332365
{
333366
var statement = File.ReadAllText($@"UnitTests\SelectStatements\{memeberName}.txt");

0 commit comments

Comments
 (0)