Skip to content

Commit d60328e

Browse files
Large interface changes to resolve an index blunder
1 parent 7768021 commit d60328e

File tree

9 files changed

+197
-119
lines changed

9 files changed

+197
-119
lines changed
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
using Magic.IndexedDb.Helpers;
2+
using Magic.IndexedDb.Models;
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Linq;
6+
using System.Linq.Expressions;
7+
using System.Reflection;
8+
using System.Runtime.CompilerServices;
9+
using System.Text;
10+
using System.Threading.Tasks;
11+
12+
namespace Magic.IndexedDb.Extensions
13+
{
14+
internal static class SharedQueryExtensions
15+
{
16+
internal static MagicQuery<T> Take<T>(MagicQuery<T> magicQuery, int amount)
17+
where T : class
18+
{
19+
var _MagicQuery = new MagicQuery<T>(magicQuery);
20+
var smq = new StoredMagicQuery
21+
{
22+
additionFunction = MagicQueryFunctions.Take,
23+
intValue = amount
24+
};
25+
26+
_MagicQuery.StoredMagicQueries.Add(smq);
27+
return _MagicQuery;
28+
}
29+
30+
public static MagicQuery<T> TakeLast<T>(MagicQuery<T> magicQuery, int amount) where T : class
31+
{
32+
var _MagicQuery = new MagicQuery<T>(magicQuery);
33+
_MagicQuery.StoredMagicQueries.Add(new StoredMagicQuery
34+
{
35+
additionFunction = MagicQueryFunctions.Take_Last,
36+
intValue = amount
37+
});
38+
return _MagicQuery;
39+
}
40+
41+
public static MagicQuery<T> Skip<T>(MagicQuery<T> magicQuery, int amount) where T : class
42+
{
43+
var _MagicQuery = new MagicQuery<T>(magicQuery);
44+
_MagicQuery.StoredMagicQueries.Add(new StoredMagicQuery
45+
{
46+
additionFunction = MagicQueryFunctions.Skip,
47+
intValue = amount
48+
});
49+
return _MagicQuery;
50+
}
51+
52+
public static MagicQuery<T> OrderBy<T>(MagicQuery<T> magicQuery, Expression<Func<T, object>> predicate) where T : class
53+
{
54+
var memberExpression = GetMemberExpressionFromLambda(predicate);
55+
var propertyInfo = memberExpression.Member as PropertyInfo;
56+
57+
if (propertyInfo == null)
58+
throw new ArgumentException("The expression must represent a single property access.");
59+
60+
MagicPropertyEntry mpe = PropertyMappingCache.GetPropertyEntry<T>(propertyInfo);
61+
62+
if (!mpe.PrimaryKey && !mpe.Indexed && !mpe.UniqueIndex)
63+
{
64+
// Intentionally preserved your comment
65+
// throw new ArgumentException(...);
66+
}
67+
68+
var _MagicQuery = new MagicQuery<T>(magicQuery);
69+
_MagicQuery.StoredMagicQueries.Add(new StoredMagicQuery
70+
{
71+
additionFunction = MagicQueryFunctions.Order_By,
72+
property = mpe.JsPropertyName
73+
});
74+
75+
return _MagicQuery;
76+
}
77+
78+
public static MagicQuery<T> OrderByDescending<T>(MagicQuery<T> magicQuery, Expression<Func<T, object>> predicate) where T : class
79+
{
80+
var memberExpression = GetMemberExpressionFromLambda(predicate);
81+
var propertyInfo = memberExpression.Member as PropertyInfo;
82+
83+
if (propertyInfo == null)
84+
throw new ArgumentException("The expression must represent a single property access.");
85+
86+
var _MagicQuery = new MagicQuery<T>(magicQuery);
87+
_MagicQuery.StoredMagicQueries.Add(new StoredMagicQuery
88+
{
89+
additionFunction = MagicQueryFunctions.Order_By_Descending,
90+
property = PropertyMappingCache.GetJsPropertyName<T>(propertyInfo)
91+
});
92+
93+
return _MagicQuery;
94+
}
95+
96+
private static MemberExpression GetMemberExpressionFromLambda<T>(Expression<Func<T, object>> expression)
97+
{
98+
if (expression.Body is MemberExpression m)
99+
return m;
100+
101+
if (expression.Body is UnaryExpression u && u.Operand is MemberExpression um)
102+
return um;
103+
104+
throw new ArgumentException("The expression must represent a single property access.");
105+
}
106+
}
107+
}

Magic.IndexedDb/LinqTranslation/Extensions/MagicCursorExtension.cs

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,11 @@
1212
using System.Text.Json.Nodes;
1313
using System.Collections;
1414
using Magic.IndexedDb.Models.UniversalOperations;
15+
using Magic.IndexedDb.Extensions;
1516

1617
namespace Magic.IndexedDb.LinqTranslation.Extensions
1718
{
18-
internal class MagicCursorExtension<T> : IMagicCursorStage<T> where T : class
19+
internal class MagicCursorExtension<T> : IMagicCursorStage<T>, IMagicCursorSkip<T> where T : class
1920
{
2021
public MagicQuery<T> MagicQuery { get; set; }
2122
public MagicCursorExtension(MagicQuery<T> _magicQuery)
@@ -25,19 +26,38 @@ public MagicCursorExtension(MagicQuery<T> _magicQuery)
2526
}
2627

2728
public IMagicCursorStage<T> Take(int amount)
28-
=> new MagicCursorExtension<T>(MagicQuery).Take(amount);
29+
{
30+
return new MagicCursorExtension<T>(SharedQueryExtensions.Take(this.MagicQuery, amount));
31+
}
2932

3033
public IMagicCursorStage<T> TakeLast(int amount)
31-
=> new MagicCursorExtension<T>(MagicQuery).TakeLast(amount);
32-
34+
{
35+
return new MagicCursorExtension<T>(
36+
SharedQueryExtensions.TakeLast(this.MagicQuery, amount)
37+
);
38+
}
39+
/*public IMagicCursorSkip<T> Skip(int amount)
40+
=> new MagicCursorExtension<T>(MagicQuery).Skip(amount);*/
3341
public IMagicCursorSkip<T> Skip(int amount)
34-
=> new MagicCursorExtension<T>(MagicQuery).Skip(amount);
42+
{
43+
return new MagicCursorExtension<T>(
44+
SharedQueryExtensions.Skip(this.MagicQuery, amount)
45+
);
46+
}
3547

3648
public IMagicCursorStage<T> OrderBy(Expression<Func<T, object>> predicate)
37-
=> new MagicCursorExtension<T>(MagicQuery).OrderBy(predicate);
49+
{
50+
return new MagicCursorExtension<T>(
51+
SharedQueryExtensions.OrderBy(this.MagicQuery, predicate)
52+
);
53+
}
3854

3955
public IMagicCursorStage<T> OrderByDescending(Expression<Func<T, object>> predicate)
40-
=> new MagicCursorExtension<T>(MagicQuery).OrderByDescending(predicate);
56+
{
57+
return new MagicCursorExtension<T>(
58+
SharedQueryExtensions.OrderByDescending(this.MagicQuery, predicate)
59+
);
60+
}
4161

4262
public async IAsyncEnumerable<T> AsAsyncEnumerable(
4363
[EnumeratorCancellation] CancellationToken cancellationToken = default)

Magic.IndexedDb/LinqTranslation/Extensions/MagicQueryExtensions.cs

Lines changed: 14 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
using System.Collections;
1414
using Magic.IndexedDb.Models.UniversalOperations;
1515
using Magic.IndexedDb.LinqTranslation.Models;
16+
using Magic.IndexedDb.Extensions;
1617

1718
namespace Magic.IndexedDb.LinqTranslation.Extensions
1819
{
@@ -84,12 +85,7 @@ public async Task<List<T>> ToListAsync()
8485

8586
public IMagicQueryPaginationTake<T> Take(int amount)
8687
{
87-
var _MagicQuery = new MagicQuery<T>(this.MagicQuery);
88-
StoredMagicQuery smq = new StoredMagicQuery();
89-
smq.additionFunction = MagicQueryFunctions.Take;
90-
smq.intValue = amount;
91-
_MagicQuery.StoredMagicQueries.Add(smq);
92-
return new MagicQueryExtensions<T>(_MagicQuery);
88+
return new MagicQueryExtensions<T>(SharedQueryExtensions.Take(this.MagicQuery, amount));
9389
}
9490

9591
public async Task<T?> FirstOrDefaultAsync()
@@ -129,85 +125,32 @@ public IMagicQueryPaginationTake<T> Take(int amount)
129125

130126
public IMagicQueryFinal<T> TakeLast(int amount)
131127
{
132-
var _MagicQuery = new MagicQuery<T>(this.MagicQuery);
133-
StoredMagicQuery smq = new StoredMagicQuery();
134-
smq.additionFunction = MagicQueryFunctions.Take_Last;
135-
smq.intValue = amount;
136-
_MagicQuery.StoredMagicQueries.Add(smq);
137-
return new MagicQueryExtensions<T>(_MagicQuery);
128+
return new MagicQueryExtensions<T>(
129+
SharedQueryExtensions.TakeLast(this.MagicQuery, amount)
130+
);
138131
}
139132

140133
public IMagicQueryFinal<T> Skip(int amount)
141134
{
142-
var _MagicQuery = new MagicQuery<T>(this.MagicQuery);
143-
StoredMagicQuery smq = new StoredMagicQuery();
144-
smq.additionFunction = MagicQueryFunctions.Skip;
145-
smq.intValue = amount;
146-
_MagicQuery.StoredMagicQueries.Add(smq);
147-
return new MagicQueryExtensions<T>(_MagicQuery);
135+
return new MagicQueryExtensions<T>(
136+
SharedQueryExtensions.Skip(this.MagicQuery, amount)
137+
);
148138
}
149139

150140
// Not currently available in Dexie version 1,2, or 3
151141
public IMagicQueryOrderableTable<T> OrderBy(Expression<Func<T, object>> predicate)
152142
{
153-
var memberExpression = GetMemberExpressionFromLambda(predicate);
154-
var propertyInfo = memberExpression.Member as PropertyInfo;
155-
156-
if (propertyInfo == null)
157-
{
158-
throw new ArgumentException("The expression must represent a single property access.");
159-
}
160-
MagicPropertyEntry mpe = PropertyMappingCache.GetPropertyEntry<T>(propertyInfo);
161-
162-
163-
if (!mpe.PrimaryKey && !mpe.Indexed && !mpe.UniqueIndex)
164-
{
165-
//throw new ArgumentException("The selected property must have either MagicIndexAttribute, MagicUniqueIndexAttribute, or MagicPrimaryKeyAttribute.");
166-
}
167-
168-
var _MagicQuery = new MagicQuery<T>(this.MagicQuery);
169-
StoredMagicQuery smq = new StoredMagicQuery();
170-
smq.additionFunction = MagicQueryFunctions.Order_By;
171-
smq.property = mpe.JsPropertyName;
172-
_MagicQuery.StoredMagicQueries.Add(smq);
173-
return new MagicQueryExtensions<T>(_MagicQuery);
143+
return new MagicQueryExtensions<T>(
144+
SharedQueryExtensions.OrderBy(this.MagicQuery, predicate)
145+
);
174146
}
175147

176148
// Not currently available in Dexie version 1,2, or 3
177149
public IMagicQueryOrderableTable<T> OrderByDescending(Expression<Func<T, object>> predicate)
178150
{
179-
var memberExpression = GetMemberExpressionFromLambda(predicate);
180-
var propertyInfo = memberExpression.Member as PropertyInfo;
181-
182-
if (propertyInfo == null)
183-
{
184-
throw new ArgumentException("The expression must represent a single property access.");
185-
}
186-
187-
var _MagicQuery = new MagicQuery<T>(this.MagicQuery);
188-
StoredMagicQuery smq = new StoredMagicQuery();
189-
smq.additionFunction = MagicQueryFunctions.Order_By_Descending;
190-
191-
// this process could be much more performant
192-
smq.property = PropertyMappingCache.GetJsPropertyName<T>(propertyInfo);
193-
_MagicQuery.StoredMagicQueries.Add(smq);
194-
return new MagicQueryExtensions<T>(_MagicQuery);
195-
}
196-
197-
private MemberExpression GetMemberExpressionFromLambda(Expression<Func<T, object>> expression)
198-
{
199-
if (expression.Body is MemberExpression)
200-
{
201-
return (MemberExpression)expression.Body;
202-
}
203-
else if (expression.Body is UnaryExpression && ((UnaryExpression)expression.Body).Operand is MemberExpression)
204-
{
205-
return (MemberExpression)((UnaryExpression)expression.Body).Operand;
206-
}
207-
else
208-
{
209-
throw new ArgumentException("The expression must represent a single property access.");
210-
}
151+
return new MagicQueryExtensions<T>(
152+
SharedQueryExtensions.OrderByDescending(this.MagicQuery, predicate)
153+
);
211154
}
212155

213156
private FilterNode GetCollectedBinaryJsonExpressions()

Magic.IndexedDb/LinqTranslation/Interfaces/IMagicCursorSkip.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ namespace Magic.IndexedDb
1111
{
1212
public interface IMagicCursorSkip<T> : IMagicExecute<T> where T : class
1313
{
14-
IMagicCursorStage<T> Skip(int amount);
14+
IMagicCursorSkip<T> Skip(int amount);
1515

1616
/// <summary>
1717
/// This always orders first by the primary key, then by whatever is appended afterwards
@@ -26,5 +26,8 @@ public interface IMagicCursorSkip<T> : IMagicExecute<T> where T : class
2626
/// <param name="predicate"></param>
2727
/// <returns></returns>
2828
IMagicCursorStage<T> OrderByDescending(Expression<Func<T, object>> predicate);
29+
30+
Task<T?> FirstOrDefaultAsync();
31+
Task<T?> LastOrDefaultAsync();
2932
}
3033
}

Magic.IndexedDb/LinqTranslation/Interfaces/IMagicCursorStage.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,8 @@ public interface IMagicCursorStage<T> : IMagicExecute<T> where T : class
2929
/// <param name="predicate"></param>
3030
/// <returns></returns>
3131
IMagicCursorStage<T> OrderByDescending(Expression<Func<T, object>> predicate);
32+
33+
Task<T?> FirstOrDefaultAsync();
34+
Task<T?> LastOrDefaultAsync();
3235
}
3336
}

Magic.IndexedDb/LinqTranslation/Interfaces/IMagicQueryStaging.cs

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,20 +27,6 @@ public interface IMagicQueryStaging<T> : IMagicExecute<T> where T : class
2727
IMagicQueryFinal<T> TakeLast(int amount);
2828
IMagicQueryFinal<T> Skip(int amount);
2929

30-
/// <summary>
31-
/// This always orders first by the primary key, then by whatever is appended afterwards
32-
/// </summary>
33-
/// <param name="predicate"></param>
34-
/// <returns></returns>
35-
IMagicQueryOrderable<T> OrderBy(Expression<Func<T, object>> predicate);
36-
37-
/// <summary>
38-
/// This always orders by descending by the primary key first, then by whatever is appended afterwards
39-
/// </summary>
40-
/// <param name="predicate"></param>
41-
/// <returns></returns>
42-
IMagicQueryOrderable<T> OrderByDescending(Expression<Func<T, object>> predicate);
43-
4430
Task<T?> FirstOrDefaultAsync();
4531
Task<T?> LastOrDefaultAsync();
4632
}

Magic.IndexedDb/LinqTranslation/Models/MagicQuery.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,11 @@ public IMagicQueryOrderableTable<T> OrderBy(Expression<Func<T, object>> predicat
101101
public IMagicQueryOrderableTable<T> OrderByDescending(Expression<Func<T, object>> predicate)
102102
=> new MagicQueryExtensions<T>(this).OrderByDescending(predicate);
103103

104-
IMagicQueryOrderable<T> IMagicQueryStaging<T>.OrderBy(Expression<Func<T, object>> predicate)
104+
/*IMagicQueryOrderable<T> IMagicQueryStaging<T>.OrderBy(Expression<Func<T, object>> predicate)
105105
=> OrderBy(predicate);
106106
107107
IMagicQueryOrderable<T> IMagicQueryStaging<T>.OrderByDescending(Expression<Func<T, object>> predicate)
108-
=> OrderByDescending(predicate);
108+
=> OrderByDescending(predicate);*/
109109

110110
public IMagicCursor<T> Cursor(Expression<Func<T, bool>> predicate)
111111
=> new MagicCursor<T>(this).Cursor(predicate);

0 commit comments

Comments
 (0)