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

Commit 96c898b

Browse files
committed
Fix Oracle dialect provider problems with paging, expressions, nullable ids.
Add new tests to Oracle test project. Make TestHelper strip trailing whitespace for better comparisons. JoinSqlBuilderTests, OrmLiteQueryTests, SqlBuilderTests, and TypeWithByteArrayFieldTests now handle parameter string differences. LoadReferencesJoinTests, OrmLiteQueryTests are not sensitive to ids inserted. OrmLiteCreateTableWithIndexesTests handles Oracle name munging.
1 parent e3abfd1 commit 96c898b

File tree

9 files changed

+88
-56
lines changed

9 files changed

+88
-56
lines changed

src/ServiceStack.OrmLite.Oracle.Tests/ServiceStack.OrmLite.Oracle.Tests.csproj

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,9 @@
123123
<Compile Include="..\..\tests\ServiceStack.OrmLite.Tests\Expression\SelectExpressionTests.cs">
124124
<Link>Expression\SelectExpressionTests.cs</Link>
125125
</Compile>
126+
<Compile Include="..\..\tests\ServiceStack.OrmLite.Tests\Expression\SqlExpressionTests.cs">
127+
<Link>Expression\SqlExpressionTests.cs</Link>
128+
</Compile>
126129
<Compile Include="..\..\tests\ServiceStack.OrmLite.Tests\Expression\StringFunctionTests.cs">
127130
<Link>Expression\StringFunctionTests.cs</Link>
128131
</Compile>
@@ -135,6 +138,9 @@
135138
<Compile Include="..\..\tests\ServiceStack.OrmLite.Tests\JoinSqlBuilderTests.cs">
136139
<Link>JoinSqlBuilderTests.cs</Link>
137140
</Compile>
141+
<Compile Include="..\..\tests\ServiceStack.OrmLite.Tests\LoadReferencesJoinTests.cs">
142+
<Link>LoadReferencesJoinTests.cs</Link>
143+
</Compile>
138144
<Compile Include="..\..\tests\ServiceStack.OrmLite.Tests\LoadReferencesTests.cs">
139145
<Link>LoadReferencesTests.cs</Link>
140146
</Compile>
@@ -318,6 +324,9 @@
318324
<Compile Include="..\..\tests\ServiceStack.OrmLite.Tests\UseCase\CustomerOrdersUseCase.cs">
319325
<Link>UseCase\CustomerOrdersUseCase.cs</Link>
320326
</Compile>
327+
<Compile Include="..\..\tests\ServiceStack.OrmLite.Tests\UseCase\FieldFromInterfaceImplementationUseCase.cs">
328+
<Link>UseCase\FieldFromInterfaceImplementationUseCase.cs</Link>
329+
</Compile>
321330
<Compile Include="..\..\tests\ServiceStack.OrmLite.Tests\UseCase\ImageBlobDto.cs">
322331
<Link>UseCase\ImageBlobDto.cs</Link>
323332
</Compile>

src/ServiceStack.OrmLite.Oracle/OracleOrmLiteDialectProvider.cs

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -268,10 +268,13 @@ public override string ToSelectStatement(Type tableType, string sqlFilter, param
268268
var sql = new StringBuilder();
269269
const string selectStatement = "SELECT ";
270270
var modelDef = GetModel(tableType);
271-
var isFullSelectStatement =
272-
!string.IsNullOrEmpty(sqlFilter)
273-
&& sqlFilter.Trim().Length > selectStatement.Length
274-
&& sqlFilter.Trim().Substring(0, selectStatement.Length).ToUpper().Equals(selectStatement);
271+
var isFullSelectStatement = false;
272+
if (!string.IsNullOrEmpty(sqlFilter))
273+
{
274+
var cleanFilter = sqlFilter.Trim().Replace('\r', ' ').Replace('\n', ' ').ToUpperInvariant();
275+
isFullSelectStatement = cleanFilter.Length > selectStatement.Length
276+
&& cleanFilter.Substring(0, selectStatement.Length).Equals(selectStatement);
277+
}
275278

276279
if (isFullSelectStatement)
277280
{
@@ -369,11 +372,11 @@ public override void SetParameterValues<T>(IDbCommand dbCmd, object obj)
369372
pi.GetValue(obj, new object[] { }), isInsert);
370373
if (pi.PropertyType == typeof(String))
371374
pi.SetProperty(obj, result.ToString());
372-
else if (pi.PropertyType == typeof(Int16))
375+
else if (pi.PropertyType == typeof(Int16) || pi.PropertyType == typeof(Int16?))
373376
pi.SetProperty(obj, Convert.ToInt16(result));
374-
else if (pi.PropertyType == typeof(Int32))
377+
else if (pi.PropertyType == typeof(Int32) || pi.PropertyType == typeof(Int32?))
375378
pi.SetProperty(obj, Convert.ToInt32(result));
376-
else if (pi.PropertyType == typeof(Guid))
379+
else if (pi.PropertyType == typeof(Guid) || pi.PropertyType == typeof(Guid?))
377380
pi.SetProperty(obj, result);
378381
else
379382
pi.SetProperty(obj, Convert.ToInt64(result));
@@ -1122,13 +1125,11 @@ public override string ToSelectStatement(ModelDefinition modelDef,
11221125
var sbInner = new StringBuilder(selectExpression);
11231126
sbInner.Append(bodyExpression);
11241127

1125-
if (!rows.HasValue)
1126-
return sbInner + orderByExpression;
1128+
if (!rows.HasValue && !offset.HasValue)
1129+
return sbInner + " " + orderByExpression;
11271130

11281131
if (!offset.HasValue)
1129-
{
11301132
offset = 0;
1131-
}
11321133

11331134
if (string.IsNullOrEmpty(orderByExpression))
11341135
{
@@ -1138,7 +1139,7 @@ public override string ToSelectStatement(ModelDefinition modelDef,
11381139
orderByExpression = string.Format("ORDER BY {0}",
11391140
OrmLiteConfig.DialectProvider.GetQuotedColumnName(modelDef.PrimaryKey.FieldName));
11401141
}
1141-
sbInner.Append(orderByExpression);
1142+
sbInner.Append(" " + orderByExpression);
11421143

11431144
var sql = sbInner.ToString();
11441145

@@ -1147,7 +1148,10 @@ public override string ToSelectStatement(ModelDefinition modelDef,
11471148
sb.AppendLine("SELECT \"_ss_ormlite_1_\".*, ROWNUM RNUM FROM (");
11481149
sb.Append(sql);
11491150
sb.AppendLine(") \"_ss_ormlite_1_\"");
1150-
sb.AppendFormat("WHERE ROWNUM <= {0} + {1}) \"_ss_ormlite_2_\" ", offset.Value, rows.Value);
1151+
if (rows.HasValue)
1152+
sb.AppendFormat("WHERE ROWNUM <= {0} + {1}) \"_ss_ormlite_2_\" ", offset.Value, rows.Value);
1153+
else
1154+
sb.Append(") \"_ss_ormlite_2_\" ");
11511155
sb.AppendFormat("WHERE \"_ss_ormlite_2_\".RNUM > {0}", offset.Value);
11521156

11531157
return sb.ToString();

tests/ServiceStack.OrmLite.Tests/JoinSqlBuilderTests.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,9 @@ public void Can_execute_SqlBuilder_templates_as_SqlExpression()
123123
var tmpl = sb.AddTemplate("SELECT * FROM {0} u INNER JOIN {1} a on a.{2} = u.Id /**where**/"
124124
.Fmt("User".SqlTable(), "Addresses".SqlTable(), "UserId".SqlColumn()));
125125

126-
sb.Where("Age > @age", new { age = 18 });
127-
sb.Where("Countryalias = @country", new { country = "Italy" });
126+
var paramString = OrmLiteConfig.DialectProvider.ParamString;
127+
sb.Where("Age > " + paramString + "age", new { age = 18 });
128+
sb.Where("Countryalias = " + paramString + "country", new { country = "Italy" });
128129

129130
var userId = db.Insert(new User { Age = 27, Name = "Foo" }, selectIdentity: true);
130131
db.Insert(new WithAliasAddress { City = "Rome", Country = "Italy", UserId = (int)userId });

tests/ServiceStack.OrmLite.Tests/LoadReferencesJoinTests.cs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Data;
1+
using System.Collections.Generic;
2+
using System.Data;
23
using System.Linq;
34
using NUnit.Framework;
45
using ServiceStack.OrmLite.Tests.UseCase;
@@ -194,7 +195,8 @@ public void Can_do_joins_with_complex_wheres_using_SqlExpression()
194195
var costs = results.ConvertAll(x => x.Cost);
195196
Assert.That(costs, Is.EquivalentTo(new[] { 1.99m, 1.49m, 9.99m }));
196197
var orderIds = results.ConvertAll(x => x.OrderId);
197-
Assert.That(orderIds, Is.EquivalentTo(new[] { 1, 3, 5 }));
198+
var expectedOrderIds = new []{customers[0].Orders[0].Id, customers[0].Orders[2].Id, customers[0].Orders[4].Id};
199+
Assert.That(orderIds, Is.EquivalentTo(expectedOrderIds));
198200

199201
//Same as above using using db.From<Customer>()
200202
results = db.Select<FullCustomerInfo>(db.From<Customer>()
@@ -375,17 +377,19 @@ public void Does_populate_custom_columns_based_on_property_convention()
375377
db.DropAndCreateTable<CustomerAddress>();
376378
db.DropAndCreateTable<Customer>();
377379

378-
AddCustomerWithOrders();
380+
var customer = AddCustomerWithOrders();
379381

380382
var results = db.Select<FullCustomerInfo, Customer>(q => q
381383
.Join<Customer, CustomerAddress>()
382384
.Join<Customer, Order>());
383385

384386
var addressIds = results.ConvertAll(x => x.CustomerAddressId);
385-
Assert.That(addressIds, Is.EquivalentTo(new[] { 1, 1 }));
387+
var expectedAddressIds = new[] { customer.PrimaryAddress.Id, customer.PrimaryAddress.Id };
388+
Assert.That(addressIds, Is.EquivalentTo(expectedAddressIds));
386389

387390
var orderIds = results.ConvertAll(x => x.OrderId);
388-
Assert.That(orderIds, Is.EquivalentTo(new[] { 1, 2 }));
391+
var expectedOrderIds = new[] {customer.Orders[0].Id, customer.Orders[1].Id};
392+
Assert.That(orderIds, Is.EquivalentTo(expectedOrderIds));
389393

390394
var customerNames = results.ConvertAll(x => x.CustomerName);
391395
Assert.That(customerNames, Is.EquivalentTo(new[] { "Customer 1", "Customer 1" }));
@@ -401,10 +405,10 @@ public void Does_populate_custom_columns_based_on_property_convention()
401405
results = db.Select<FullCustomerInfo>(expr);
402406

403407
addressIds = results.ConvertAll(x => x.CustomerAddressId);
404-
Assert.That(addressIds, Is.EquivalentTo(new[] { 1 }));
408+
Assert.That(addressIds, Is.EquivalentTo(new[] { customer.PrimaryAddress.Id }));
405409

406410
orderIds = results.ConvertAll(x => x.OrderId);
407-
Assert.That(orderIds, Is.EquivalentTo(new[] { 2 }));
411+
Assert.That(orderIds, Is.EquivalentTo(new[] { customer.Orders[1].Id }));
408412

409413
customerNames = results.ConvertAll(x => x.CustomerName);
410414
Assert.That(customerNames, Is.EquivalentTo(new[] { "Customer 1" }));

tests/ServiceStack.OrmLite.Tests/OrmLiteCreateTableWithIndexesTests.cs

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,17 @@ public void Can_create_ModelWithIndexFields_table()
1818

1919
var sql = OrmLiteConfig.DialectProvider.ToCreateIndexStatements(typeof(ModelWithIndexFields)).Join();
2020

21-
SuppressIfOracle("Assert comparisons don't work with Oracle provider because it had to squash names to satisfy length restrictions");
21+
var indexName = "idx_modelwithindexfields_name";
22+
var uniqueName = "uidx_modelwithindexfields_uniquename";
2223

23-
Assert.IsTrue(sql.Contains("idx_modelwithindexfields_name"));
24-
Assert.IsTrue(sql.Contains("uidx_modelwithindexfields_uniquename"));
24+
if (Dialect == Dialect.Oracle)
25+
{
26+
indexName = OrmLiteConfig.DialectProvider.NamingStrategy.ApplyNameRestrictions(indexName);
27+
uniqueName = OrmLiteConfig.DialectProvider.NamingStrategy.ApplyNameRestrictions(uniqueName);
28+
}
29+
30+
Assert.IsTrue(sql.Contains(indexName));
31+
Assert.IsTrue(sql.Contains(uniqueName));
2532
}
2633
}
2734

@@ -36,10 +43,17 @@ public void Can_create_ModelWithCompositeIndexFields_table()
3643

3744
var sql = OrmLiteConfig.DialectProvider.ToCreateIndexStatements(typeof(ModelWithCompositeIndexFields)).Join();
3845

39-
SuppressIfOracle("Assert comparisons don't work with Oracle provider because it had to squash names to satisfy length restrictions");
46+
var indexName = "idx_modelwithcompositeindexfields_name";
47+
var compositeName = "idx_modelwithcompositeindexfields_composite1_composite2";
48+
49+
if (Dialect == Dialect.Oracle)
50+
{
51+
indexName = OrmLiteConfig.DialectProvider.NamingStrategy.ApplyNameRestrictions(indexName);
52+
compositeName = OrmLiteConfig.DialectProvider.NamingStrategy.ApplyNameRestrictions(compositeName);
53+
}
4054

41-
Assert.IsTrue(sql.Contains("idx_modelwithcompositeindexfields_name"));
42-
Assert.IsTrue(sql.Contains("idx_modelwithcompositeindexfields_composite1_composite2"));
55+
Assert.IsTrue(sql.Contains(indexName));
56+
Assert.IsTrue(sql.Contains(compositeName));
4357
}
4458
}
4559

@@ -54,11 +68,18 @@ public void Can_create_ModelWithNamedCompositeIndex_table()
5468

5569
var sql = OrmLiteConfig.DialectProvider.ToCreateIndexStatements(typeof(ModelWithNamedCompositeIndex)).Join();
5670

57-
SuppressIfOracle("Assert comparisons don't work with Oracle provider because it had to squash names to satisfy length restrictions");
71+
var indexName = "idx_modelwithnamedcompositeindex_name";
72+
var compositeName = "uidx_modelwithnamedcompositeindexfields_composite1_composite2";
73+
74+
if (Dialect == Dialect.Oracle)
75+
{
76+
indexName = OrmLiteConfig.DialectProvider.NamingStrategy.ApplyNameRestrictions(indexName);
77+
compositeName = OrmLiteConfig.DialectProvider.NamingStrategy.ApplyNameRestrictions(compositeName);
78+
}
5879

59-
Assert.IsTrue(sql.Contains("idx_modelwithnamedcompositeindex_name"));
80+
Assert.IsTrue(sql.Contains(indexName));
6081
Assert.IsTrue(sql.Contains("custom_index_name"));
61-
Assert.IsFalse(sql.Contains("uidx_modelwithnamedcompositeindexfields_composite1_composite2"));
82+
Assert.IsFalse(sql.Contains(compositeName));
6283
}
6384
}
6485

tests/ServiceStack.OrmLite.Tests/OrmLiteQueryTests.cs

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,9 @@ public void Can_select_with_filter_from_ModelWithOnlyStringFields_table()
7878
Assert.That(dbRowIds, Has.Count.EqualTo(1));
7979
Assert.That(dbRowIds[0], Is.EqualTo(filterRow.Id));
8080

81-
SuppressIfOracle("Oracle provider is not smart enough to substitute ':' for '@' parameter delimiter.");
82-
8381
rows = db.Select<ModelWithOnlyStringFields>(
84-
"SELECT * FROM {0} WHERE {1} = @AlbumName"
85-
.Fmt("ModelWithOnlyStringFields".SqlTable(), "AlbumName".SqlColumn()),
82+
"SELECT * FROM {0} WHERE {1} = {2}AlbumName"
83+
.Fmt("ModelWithOnlyStringFields".SqlTable(), "AlbumName".SqlColumn(), OrmLiteConfig.DialectProvider.ParamString),
8684
new { filterRow.AlbumName });
8785
dbRowIds = rows.ConvertAll(x => x.Id);
8886
Assert.That(dbRowIds, Has.Count.EqualTo(1));
@@ -180,13 +178,11 @@ public void Can_query_where_and_select_Notes()
180178
Assert.That(notes[0].Id, Is.EqualTo(note.Id));
181179
Assert.That(notes[0].NoteText, Is.EqualTo(note.NoteText));
182180

183-
SuppressIfOracle("Oracle provider is not smart enough to substitute ':' for '@' parameter delimiter.");
184-
185-
notes = db.Select<Note>("SELECT * FROM Note WHERE {0}=@schemaUri".Fmt("SchemaUri".SqlColumn()), new { schemaUri = "tcm:0-0-0" });
181+
notes = db.Select<Note>("SELECT * FROM Note WHERE {0}={1}schemaUri".Fmt("SchemaUri".SqlColumn(), OrmLiteConfig.DialectProvider.ParamString), new { schemaUri = "tcm:0-0-0" });
186182
Assert.That(notes[0].Id, Is.EqualTo(note.Id));
187183
Assert.That(notes[0].NoteText, Is.EqualTo(note.NoteText));
188184

189-
notes = db.Select<Note>("SchemaUri".SqlColumn() + "=@schemaUri", new { schemaUri = "tcm:0-0-0" });
185+
notes = db.Select<Note>("SchemaUri".SqlColumn() + "={0}schemaUri".Fmt(OrmLiteConfig.DialectProvider.ParamString), new { schemaUri = "tcm:0-0-0" });
190186
Assert.That(notes[0].Id, Is.EqualTo(note.Id));
191187
Assert.That(notes[0].NoteText, Is.EqualTo(note.NoteText));
192188
}
@@ -206,25 +202,23 @@ public void Can_select_NotesDto_with_pretty_sql()
206202
{
207203
db.DropAndCreateTable<Note>();
208204

209-
db.Insert(new Note
205+
var id = db.Insert(new Note
210206
{
211207
SchemaUri = "tcm:0-0-0",
212208
NoteText = "Hello world 5",
213209
LastUpdated = new DateTime(2013, 1, 5),
214210
UpdatedBy = "RC"
215-
});
216-
217-
SuppressIfOracle("Oracle provider is not smart enough to substitute ':' for '@' parameter delimiter.");
211+
}, selectIdentity: true);
218212

219213
var sql = @"
220214
SELECT
221215
Id, {0}, {1}
222216
FROM {2}
223-
WHERE {0}=@schemaUri
224-
".Fmt("SchemaUri".SqlColumn(), "NoteText".SqlColumn(), "Note".SqlTable());
217+
WHERE {0}={3}schemaUri
218+
".Fmt("SchemaUri".SqlColumn(), "NoteText".SqlColumn(), "Note".SqlTable(), OrmLiteConfig.DialectProvider.ParamString);
225219

226220
var notes = db.Select<NoteDto>(sql, new { schemaUri = "tcm:0-0-0" });
227-
Assert.That(notes[0].Id, Is.EqualTo(1));
221+
Assert.That(notes[0].Id, Is.EqualTo(id));
228222
Assert.That(notes[0].NoteText, Is.EqualTo("Hello world 5"));
229223
}
230224
}

tests/ServiceStack.OrmLite.Tests/SqlBuilderTests.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,8 @@ public void BuilderSelectClause()
6464
[Test]
6565
public void BuilderTemplateWOComposition()
6666
{
67-
SuppressIfOracle("Oracle provider is not smart enough to replace '@' parameter delimiter with ':'");
68-
6967
var builder = new SqlBuilder();
70-
var template = builder.AddTemplate("SELECT COUNT(*) FROM Users WHERE Age = @age", new { age = 5 });
68+
var template = builder.AddTemplate("SELECT COUNT(*) FROM Users WHERE Age = {0}age".Fmt(OrmLiteConfig.DialectProvider.ParamString), new { age = 5 });
7169

7270
if (template.RawSql == null) throw new Exception("RawSql null");
7371
if (template.Parameters == null) throw new Exception("Parameters null");

tests/ServiceStack.OrmLite.Tests/TestHelpers.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ public static string NormalizeSql(this string sql)
1919
.Replace("`", "")
2020
.Replace("_", "")
2121
.Replace(":", "@") //postgresql
22-
.Replace("\n", " ");
22+
.Replace("\n", " ")
23+
.TrimEnd();
2324
}
2425
}
2526
}

tests/ServiceStack.OrmLite.Tests/TypeWithByteArrayFieldTests.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ public void Can_add_attachment()
5555
[Test, Explicit]
5656
public void Can_upload_attachment_via_sp()
5757
{
58-
SuppressIfOracle("Oracle provider is not smart enough to replace parameter delimiter '@' with ':'");
58+
SuppressIfOracle("Oracle does not like this procedure definition");
5959

6060
using (var db = OpenDbConnection())
6161
{
@@ -75,8 +75,8 @@ @filecontent varbinary(MAX))
7575
AS
7676
begin
7777
INSERT INTO [Attachment]([FileName], [Type], [Data], [Description])
78-
VALUES (@filename, @filetype, @filecontent, @filename)
79-
end");
78+
VALUES ({0}filename, {0}filetype, {0}filecontent, {0}filename)
79+
end".Fmt(OrmLiteConfig.DialectProvider.ParamString));
8080
var bytes = "https://www.google.com/images/srpr/logo11w.png".GetBytesFromUrl();
8181

8282
db.ExecuteNonQuery("EXEC SP_upload_file @filename, @filetype, @filecontent",
@@ -95,7 +95,7 @@ INSERT INTO [Attachment]([FileName], [Type], [Data], [Description])
9595
[Test, Explicit]
9696
public void Can_upload_attachment_via_sp_with_ADONET()
9797
{
98-
SuppressIfOracle("Oracle provider is not smart enough to replace parameter delimiter '@' with ':'");
98+
SuppressIfOracle("Oracle does not like this procedure definition");
9999

100100
using (var db = OpenDbConnection())
101101
{
@@ -115,8 +115,8 @@ @filecontent varbinary(MAX))
115115
AS
116116
begin
117117
INSERT INTO [Attachment]([FileName], [Type], [Data], [Description])
118-
VALUES (@filename, @filetype, @filecontent, @filename)
119-
end");
118+
VALUES ({0}filename, {0}filetype, {0}filecontent, {0}filename)
119+
end".Fmt(OrmLiteConfig.DialectProvider.ParamString));
120120
var bytes = "https://www.google.com/images/srpr/logo11w.png".GetBytesFromUrl();
121121

122122
using (var dbCmd = db.CreateCommand())

0 commit comments

Comments
 (0)