Skip to content
This repository was archived by the owner on Dec 24, 2022. It is now read-only.

Commit c2220c3

Browse files
committed
Add new Join behavior to SqlExpression with tests
1 parent cf785b0 commit c2220c3

File tree

4 files changed

+239
-21
lines changed

4 files changed

+239
-21
lines changed

src/ServiceStack.OrmLite/Expressions/SqlExpression.Join.cs

Lines changed: 69 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
namespace ServiceStack.OrmLite
77
{
8-
public abstract partial class SqlExpression<T> : ISqlExpression, ISelectableSqlExpression
8+
public abstract partial class SqlExpression<T> : ISqlExpression
99
{
1010
List<ModelDefinition> tableDefs = new List<ModelDefinition>();
1111

@@ -66,7 +66,8 @@ public string SelectInto<TModel>()
6666
this.tableDefs.Add(modelDef);
6767

6868
var sbSelect = new StringBuilder();
69-
foreach (var fieldDef in modelDef.FieldDefinitions)
69+
var selectDef = typeof(TModel).GetModelDefinition();
70+
foreach (var fieldDef in selectDef.FieldDefinitions)
7071
{
7172
var found = false;
7273

@@ -110,5 +111,71 @@ public string SelectInto<TModel>()
110111

111112
return ToSelectStatement();
112113
}
114+
115+
public virtual SqlExpression<T> Where<Target>(Expression<Func<Target, bool>> predicate)
116+
{
117+
if (predicate == null)
118+
throw new ArgumentNullException("predicate");
119+
120+
var newExpr = Visit(predicate).ToString();
121+
whereExpression = " WHERE " + newExpr;
122+
123+
return this;
124+
}
125+
126+
public virtual SqlExpression<T> Where<Source, Target>(Expression<Func<Source, Target, bool>> predicate)
127+
{
128+
if (predicate == null)
129+
throw new ArgumentNullException("predicate");
130+
131+
var newExpr = Visit(predicate).ToString();
132+
whereExpression = " WHERE " + newExpr;
133+
134+
return this;
135+
}
136+
137+
public virtual SqlExpression<T> And<Target>(Expression<Func<Target, bool>> predicate)
138+
{
139+
if (predicate == null)
140+
throw new ArgumentNullException("predicate");
141+
142+
var newExpr = Visit(predicate).ToString();
143+
whereExpression += " AND " + newExpr;
144+
145+
return this;
146+
}
147+
148+
public virtual SqlExpression<T> And<Source, Target>(Expression<Func<Source, Target, bool>> predicate)
149+
{
150+
if (predicate == null)
151+
throw new ArgumentNullException("predicate");
152+
153+
var newExpr = Visit(predicate).ToString();
154+
whereExpression += " AND " + newExpr;
155+
156+
return this;
157+
}
158+
159+
public virtual SqlExpression<T> Or<Target>(Expression<Func<Target, bool>> predicate)
160+
{
161+
if (predicate == null)
162+
throw new ArgumentNullException("predicate");
163+
164+
var newExpr = Visit(predicate).ToString();
165+
whereExpression += " OR " + newExpr;
166+
167+
return this;
168+
}
169+
170+
public virtual SqlExpression<T> Or<Source, Target>(Expression<Func<Source, Target, bool>> predicate)
171+
{
172+
if (predicate == null)
173+
throw new ArgumentNullException("predicate");
174+
175+
var newExpr = Visit(predicate).ToString();
176+
whereExpression += " OR " + newExpr;
177+
178+
return this;
179+
}
113180
}
114181
}

src/ServiceStack.OrmLite/JoinSqlBuilder.cs

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -494,17 +494,12 @@ public virtual JoinSqlBuilder<TNewPoco, TBasePoco> Limit()
494494
return this;
495495
}
496496

497-
public string ToSelectStatement()
497+
public string SelectInto<T>()
498498
{
499-
return ToSql();
500-
}
499+
var modelDef = typeof(T).GetModelDefinition();
501500

502-
public string ToSql()
503-
{
504501
CheckAggregateUsage(false);
505502

506-
var modelDef = typeof(TNewPoco).GetModelDefinition();
507-
508503
var sbSelect = new StringBuilder();
509504
sbSelect.Append("SELECT ");
510505

@@ -577,7 +572,7 @@ public string ToSql()
577572
var sbWhere = new StringBuilder();
578573
foreach (var where in whereList)
579574
{
580-
sbWhere.AppendFormat("{0}{1}", sbWhere.Length > 0
575+
sbWhere.AppendFormat("{0}{1}", sbWhere.Length > 0
581576
? (where.Value == WhereType.OR ? " OR " : " AND ") : "", where.Key);
582577
}
583578
sbBody.Append("WHERE " + sbWhere + " \n");
@@ -597,7 +592,17 @@ public string ToSql()
597592
var sql = OrmLiteConfig.DialectProvider.ToSelectStatement(
598593
modelDef, sbSelect.ToString(), sbBody.ToString(), sbOrderBy.ToString(), Offset, Rows);
599594

600-
return sql;
595+
return sql;
596+
}
597+
598+
public string ToSql()
599+
{
600+
return SelectInto<TNewPoco>();
601+
}
602+
603+
public string ToSelectStatement()
604+
{
605+
return SelectInto<TNewPoco>();
601606
}
602607
}
603608

tests/ServiceStack.OrmLite.Tests/Expression/SqlExpressionTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ public void Can_select_limit_with_JoinSqlBuilder()
168168
}
169169

170170
[Test]
171-
public void Can_join_with_SqlExpression()
171+
public void Can_add_basic_joins_with_SqlExpression()
172172
{
173173
using (var db = OpenDbConnection())
174174
{

tests/ServiceStack.OrmLite.Tests/LoadReferencesTests.cs

Lines changed: 155 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ public class MismatchAliasAddress
130130
public string Country { get; set; }
131131
}
132132

133-
public class LoadReferencesTests
133+
public class LoadReferencesTests
134134
: OrmLiteTestBase
135135
{
136136
private IDbConnection db;
@@ -161,7 +161,7 @@ public void TestFixtureTearDown()
161161
public void Does_not_include_complex_reference_type_in_sql()
162162
{
163163
db.Select<Customer>();
164-
Assert.That(db.GetLastSql().NormalizeSql(),
164+
Assert.That(db.GetLastSql().NormalizeSql(),
165165
Is.EqualTo("select id, name from customer"));
166166
}
167167

@@ -293,8 +293,7 @@ public void Can_Save_and_Load_MismatchedAlias_References_using_code_conventions(
293293
Assert.That(dbCustomer.PrimaryAddress, Is.Not.Null);
294294
}
295295

296-
[Test]
297-
public void Can_SaveAllReferences_then_Load_them()
296+
private Customer AddCustomerWithOrders()
298297
{
299298
var customer = new Customer
300299
{
@@ -306,13 +305,22 @@ public void Can_SaveAllReferences_then_Load_them()
306305
State = "Northern Territory",
307306
Country = "Australia"
308307
},
309-
Orders = new[] {
310-
new Order { LineItem = "Line 1", Qty = 1, Cost = 1.99m },
311-
new Order { LineItem = "Line 2", Qty = 2, Cost = 2.99m },
308+
Orders = new[]
309+
{
310+
new Order {LineItem = "Line 1", Qty = 1, Cost = 1.99m},
311+
new Order {LineItem = "Line 2", Qty = 2, Cost = 2.99m},
312312
}.ToList(),
313313
};
314314

315-
db.Save(customer, references:true);
315+
db.Save(customer, references: true);
316+
317+
return customer;
318+
}
319+
320+
[Test]
321+
public void Can_SaveAllReferences_then_Load_them()
322+
{
323+
var customer = AddCustomerWithOrders();
316324

317325
Assert.That(customer.Id, Is.GreaterThan(0));
318326
Assert.That(customer.PrimaryAddress.CustomerId, Is.EqualTo(customer.Id));
@@ -337,8 +345,146 @@ public void Can_save_with_null_references()
337345
};
338346

339347
db.Save(customer, references: true);
340-
348+
341349
Assert.That(customer.Id, Is.GreaterThan(0));
342350
}
351+
352+
353+
public class CustomerJoin
354+
{
355+
public int Id { get; set; }
356+
public string Name { get; set; }
357+
public string AddressLine1 { get; set; }
358+
public string City { get; set; }
359+
public string LineItem { get; set; }
360+
public decimal Cost { get; set; }
361+
}
362+
363+
[Test]
364+
public void Can_do_multiple_joins_with_SqlExpression()
365+
{
366+
AddCustomerWithOrders();
367+
368+
var results = db.Select<CustomerJoin, Customer>(q => q
369+
.Join<Customer, CustomerAddress>()
370+
.Join<Customer, Order>());
371+
372+
var costs = results.ConvertAll(x => x.Cost);
373+
Assert.That(costs, Is.EquivalentTo(new[] { 1.99m, 2.99m }));
374+
375+
var expr = db.From<Customer>()
376+
.Join<Customer, CustomerAddress>()
377+
.Join<Customer, Order>();
378+
379+
results = db.Select<CustomerJoin>(expr);
380+
381+
costs = results.ConvertAll(x => x.Cost);
382+
Assert.That(costs, Is.EquivalentTo(new[] { 1.99m, 2.99m }));
383+
}
384+
385+
[Test]
386+
public void Can_do_joins_with_wheres_using_SqlExpression()
387+
{
388+
AddCustomerWithOrders();
389+
390+
var results = db.Select<CustomerJoin, Customer>(q => q
391+
.Join<Customer, CustomerAddress>()
392+
.Join<Customer, Order>((c, o) => c.Id == o.CustomerId && o.Cost < 2));
393+
394+
var costs = results.ConvertAll(x => x.Cost);
395+
Assert.That(costs, Is.EquivalentTo(new[] { 1.99m }));
396+
397+
results = db.Select<CustomerJoin, Customer>(q => q
398+
.Join<Customer, CustomerAddress>()
399+
.Join<Customer, Order>()
400+
.Where<Order>(o => o.Cost < 2));
401+
402+
costs = results.ConvertAll(x => x.Cost);
403+
Assert.That(costs, Is.EquivalentTo(new[] { 1.99m }));
404+
405+
results = db.Select<CustomerJoin, Customer>(q => q
406+
.Join<Customer, CustomerAddress>()
407+
.Join<Customer, Order>()
408+
.Where<Order>(o => o.Cost < 2 || o.LineItem == "Line 2"));
409+
410+
costs = results.ConvertAll(x => x.Cost);
411+
Assert.That(costs, Is.EquivalentTo(new[] { 1.99m, 2.99m }));
412+
413+
var expr = db.From<Customer>()
414+
.Join<Customer, CustomerAddress>()
415+
.Join<Customer, Order>()
416+
.Where<Order>(o => o.Cost < 2 || o.LineItem == "Line 2");
417+
results = db.Select<CustomerJoin>(expr);
418+
419+
costs = results.ConvertAll(x => x.Cost);
420+
Assert.That(costs, Is.EquivalentTo(new[] { 1.99m, 2.99m }));
421+
}
422+
423+
[Test]
424+
public void Can_do_joins_with_complex_wheres_using_SqlExpression()
425+
{
426+
var customer1 = new Customer
427+
{
428+
Name = "Customer 1",
429+
PrimaryAddress = new CustomerAddress
430+
{
431+
AddressLine1 = "1 Humpty Street",
432+
City = "Humpty Doo",
433+
State = "Northern Territory",
434+
Country = "Australia"
435+
},
436+
Orders = new[]
437+
{
438+
new Order {LineItem = "Line 1", Qty = 1, Cost = 1.99m},
439+
new Order {LineItem = "Line 1", Qty = 2, Cost = 3.98m},
440+
new Order {LineItem = "Line 2", Qty = 1, Cost = 1.49m},
441+
new Order {LineItem = "Line 2", Qty = 2, Cost = 2.98m},
442+
new Order {LineItem = "Australia Flag", Qty = 1, Cost = 9.99m},
443+
}.ToList(),
444+
};
445+
446+
db.Save(customer1, references: true);
447+
448+
var customer2 = new Customer
449+
{
450+
Name = "Customer 2",
451+
PrimaryAddress = new CustomerAddress
452+
{
453+
AddressLine1 = "2 Prospect Park",
454+
City = "Brooklyn",
455+
State = "New York",
456+
Country = "USA"
457+
},
458+
Orders = new[]
459+
{
460+
new Order {LineItem = "USA", Qty = 1, Cost = 20m},
461+
}.ToList(),
462+
};
463+
464+
db.Save(customer2, references: true);
465+
466+
var results = db.Select<CustomerJoin, Customer>(q => q
467+
.Join<Customer, CustomerAddress>()
468+
.Join<Customer, Order>()
469+
.Where(c => c.Name == "Customer 1")
470+
.And<Order>(o => o.Cost < 2)
471+
.Or<Order>(o => o.LineItem == "Australia Flag"));
472+
473+
var costs = results.ConvertAll(x => x.Cost);
474+
Assert.That(costs, Is.EquivalentTo(new[] { 1.99m, 1.49m, 9.99m }));
475+
476+
results = db.Select<CustomerJoin, Customer>(q => q
477+
.Join<Customer, CustomerAddress>()
478+
.Join<Customer, Order>()
479+
.Where(c => c.Name == "Customer 2")
480+
.And<CustomerAddress, Order>((a, o) => a.Country == o.LineItem));
481+
482+
db.GetLastSql().Print();
483+
484+
costs = results.ConvertAll(x => x.Cost);
485+
Assert.That(costs, Is.EquivalentTo(new[] { 20m }));
486+
}
487+
343488
}
489+
344490
}

0 commit comments

Comments
 (0)